<?php
// /execute/tabs/tab_forecast.php
$symbol = $_GET['symbol'] ?? $_POST['symbol'] ?? '';
$uid    = substr(md5(uniqid('',true)),0,8);
$apiBase = rtrim(dirname(dirname($_SERVER['SCRIPT_NAME'])), '/'); // …/execute
?>
<div id="fcTab-<?= $uid ?>" class="fcTab" data-symbol="<?= htmlspecialchars($symbol) ?>" data-h="20" data-atr="1.4">
	<div class="card">
		<div class="card-body">
			<div id="fcStatus" class="text-muted small"></div>
			<div id="fcOut"></div>
		</div>
	</div>
</div>

<script>
(function(){
  var root = document.getElementById('fcTab-<?= $uid ?>');
  if(!root) return;

  // Helpers
  function ensure(id, cls){
	var el = root.querySelector('#'+id);
	if(!el){ el=document.createElement('div'); el.id=id; if(cls) el.className=cls; root.appendChild(el); }
	return el;
  }
  var status = ensure('fcStatus','text-muted small');
  var out    = ensure('fcOut','mt-2');

  var sym = root.getAttribute('data-symbol')||'';
  var h   = root.getAttribute('data-h')||'20';
  var atr = root.getAttribute('data-atr')||'1.4';
  var apiBase = <?= json_encode($apiBase) ?>; // z.B. "/execute"

  function spin(on){
	status.innerHTML = on
	  ? '<div class="spinner-border spinner-border-sm text-secondary" role="status" aria-hidden="true"></div><span class="ms-2">Berechne k-NN Forecast…</span>'
	  : '';
  }
  function fmtP(x){ return (x==null?'—':(x*100).toFixed(1)+'%'); }
  function fmtR(x){ return (x==null?'—':(x*100).toFixed(2)+'%'); }
  function get(o,a,b,c,d){ try{ var v=o; if(a) v=v[a]; if(b) v=v[b]; if(c) v=v[c]; if(d) v=v[d]; return v; }catch(e){ return undefined; } }
  function classify(j){
	var prob=j.prob_up||0, conf=get(j,'meta','confidence')||0, p50=get(j,'retiles','p50')||0, rr50=get(j,'risk','rr_p50');
	var reg=get(j,'meta','regime','trend')||'Range', stopPct=get(j,'risk','stop_pct'), expDD=get(j,'expectations','exp_maxdd');
	if(conf<0.35||prob<0.52||(reg==='Downtrend'&&p50<=0)) return {label:'Rot',reason:'niedrige Edge/Confidence oder Downtrend'};
	var green=(prob>=0.60)&&(conf>=0.50)&&(p50>0)&&((rr50==null)||rr50>=1.2);
	var ddOK=(stopPct==null||expDD==null)?true:Math.abs(expDD)<=Math.abs(stopPct)*0.8;
	return (green&&ddOK)?{label:'Grün',reason:'gute Edge & Risiko im Rahmen'}:{label:'Gelb',reason:'mittlere Edge oder erhöhtes Risiko'};
  }
  function url(){ return apiBase+'/forecast/forecast.php?symbol='+encodeURIComponent(sym)+'&h='+encodeURIComponent(h)+'&atr='+encodeURIComponent(atr); }

  function render(j){
	var name=j.name||'', exch=j.exchange||'';
	var header=(name&&exch)?(name+' - '+exch):(name||exch||'');
	var close=get(j,'risk','close'); close=(close!=null)?close.toFixed(2):'—';
	var lastDate=j.last_date||'';
	var amp=classify(j), badge=amp.label==='Grün'?'bg-success':(amp.label==='Gelb'?'bg-warning text-dark':'bg-danger');
	var detsArr=j.detectors||[], dets=detsArr.length?detsArr.map(function(d){return (d.id||'?')+' ('+Math.round((d.confidence||0)*100)+'%)';}).join(', '):'—';
	var regime=get(j,'meta','regime') ? (j.meta.regime.trend+' • vol '+j.meta.regime.vol) : '—';
	var stopMult=get(j,'risk','stop_mult'); var stopLbl=stopMult?('ATR×'+stopMult):('ATR×'+atr);
	var stopTxt=get(j,'risk','stop'); stopTxt=(stopTxt!=null)?stopTxt.toFixed(2):'—';
	var t50=get(j,'targets','t_p50'), t90=get(j,'targets','t_p90'); var tgtTxt=(t50!=null&&t90!=null)?(t50.toFixed(2)+' / '+t90.toFixed(2)):'—';
	var rr50=get(j,'risk','rr_p50'), rr90=get(j,'risk','rr_p90'); var rrTxt=(rr50!=null&&rr90!=null)?(rr50.toFixed(2)+' / '+rr90.toFixed(2)):'—';
	var conf=get(j,'meta','confidence'); var confTxt=(conf!=null)?Math.round(conf*100)+'%':'—';

	var rows=[
	  ['Ampel','<span class="badge '+badge+'">'+amp.label+'</span>',amp.reason],
	  ['Wahrscheinlichkeit',fmtP(j.prob_up),'Kalibrierte Wahrscheinlichkeit für positive Rendite (H).'],
	  ['Erw. Rendite',fmtR(get(j,'expectations','exp_ret')),'Gewichteter Erwartungswert der H-Tages-Rendite.'],
	  ['Erw. MaxDD bis H',fmtR(get(j,'expectations','exp_maxdd')),'Erwarteter max. Rückgang bis H.'],
	  ['P10',fmtR(get(j,'retiles','p10')),'10%-Quantil (konservativ).'],
	  ['P50 (Median)',fmtR(get(j,'retiles','p50')),'Median der Verteilung.'],
	  ['P90',fmtR(get(j,'retiles','p90')),'90%-Quantil (optimistisch).'],
	  ['Stop ('+stopLbl+')',stopTxt,'ATR-basiertes Stop-Niveau.'],
	  ['Ziele P50 / P90',tgtTxt,'Zielpreise aus P50/P90.'],
	  ['CRV (P50 / P90)',rrTxt,'Chance/Risiko relativ zum Stop.'],
	  ['Regime',regime,'Trend- & Volatilitätszustand.'],
	  ['Confidence',confTxt,'Ähnlichkeitsgüte (höher = verlässlicher).'],
	  ['k-NN k',(get(j,'meta','k')||'—'),'Anzahl berücksichtigter Nachbarn.'],
	  ['Historie geladen',(j.scanned||'—'),'Verfügbare Bars.'],
	  ['Horizont (Tage)',(j.horizon_days||h),'Prognosehorizont.'],
	  ['Muster-Detektoren',dets,'Erkannte Muster im aktuellen Setup.']
	];
	var tbody=rows.map(function(r){return '<tr><th>'+r[0]+'</th><td>'+r[1]+'</td><td class="text-muted">'+r[2]+'</td></tr>';}).join('');
	out.innerHTML =
	  '<div class="mb-2"><h4 class="mb-0">'+
		'<span class="text-dark">'+(j.symbol||sym)+'</span>'+(header?'<span class="text-muted small"> - '+header+'</span>':'')+
		'<span class="badge '+badge+' ms-2">'+amp.label+'</span>'+
	  '</h4>'+
	  '<div class="text-muted small">Letzter Kurs: '+close+(lastDate?(' ('+lastDate+')'):'')+'</div></div>'+
	  '<table class="table align-middle mb-0 mt-3"><thead class="table-dark"><tr><th>Kennzahl</th><th>Wert</th><th>Erklärung</th></tr></thead><tbody>'+tbody+'</tbody></table>';
  }

  function load(){
	if(!sym){ out.innerHTML='<div class="alert alert-warning mb-0">Kein Symbol übergeben.</div>'; return; }
	spin(true);
	fetch(url(),{headers:{'Accept':'application/json'}})
	  .then(function(r){ return r.text().then(function(t){ return {ok:r.ok,status:r.status,text:t}; }); })
	  .then(function(res){
		if(!res.ok){ out.innerHTML='<div class="alert alert-danger mb-0">HTTP '+res.status+': '+res.text.slice(0,200)+'</div>'; return; }
		var j; try{ j=JSON.parse(res.text);}catch(e){ out.innerHTML='<div class="alert alert-danger mb-0">Kein JSON: '+res.text.slice(0,200)+'...</div>'; return; }
		if(!j.ok){ out.innerHTML='<div class="alert alert-danger mb-0">Fehler: '+(j.error||'unbekannt')+'</div>'; return; }
		render(j);
	  })
	  .catch(function(e){ out.innerHTML='<div class="alert alert-danger mb-0">Request-Fehler: '+String(e).slice(0,200)+'</div>'; })
	  .finally(function(){ spin(false); });
  }

  // Auto-Load & optionale Reload-Schnittstelle
  root.addEventListener('fc:reload', load);
  root.fcReload = load;
  load();
})();
</script>