/* Overview "Predictive evidence" (W_Evidence): which of the dashboard's signals have earned the right to be
 * believed as forecasts. Data: /api/research-evidence (src/research_evidence.js weekly walk-forward test,
 * src/research_tracker.js prospective State A tracker, and the Expected Move scorecard).
 * Display text comes from window.OverviewFormat (pure, tested in Node). */

const { useState: useStateEV, useEffect: useEffectEV } = React;

const EV_REFRESH_MS = 10 * 60 * 1000;

const evPretty = (f) => String(f || '').replace(/^comp_/, '').replace(/_/g, ' ');

function EV_Row({ name, chip, chipLabel, children, title }) {
  return (
    <div style={{ display: 'grid', gridTemplateColumns: 'minmax(180px, 1.1fr) 168px minmax(0, 2fr)', gap: 14, alignItems: 'baseline', padding: '9px 0', borderTop: '1px solid var(--border-soft)' }}>
      <div style={{ fontSize: 12.5, color: 'var(--text-2)' }} title={title}>{name}</div>
      <span className={'chip ' + chip} style={{ justifySelf: 'start', whiteSpace: 'nowrap' }}><span className="chip-dot" /> {chipLabel}</span>
      <div style={{ fontSize: 11.5, color: 'var(--text-3)', lineHeight: 1.5 }}>{children}</div>
    </div>
  );
}

function EV_View({ data, loading, error }) {
  const F = window.OverviewFormat;
  const ev = data && data.evidence, tracks = (data && data.tracks) || [], em = data && data.expected_move;
  const verdict = em ? F.sizeVerdict(em.avgSizeRatio, em.avgSizeRatioCi95) : null;
  const stateA = tracks.find((t) => t.id === 'state_a_v1');
  const trackChip = !stateA || stateA.status === 'not started' ? { chip: 'neutral', label: 'Not started' }
    : stateA.status === 'paused' ? { chip: 'bear', label: 'Paused' }
    : stateA.grade && stateA.grade.status === 'supported' ? { chip: 'bull', label: 'Supported' }
    : stateA.grade && stateA.grade.status === 'contradicted' ? { chip: 'bear', label: 'Contradicted' }
    : stateA.grade && stateA.grade.status === 'inconclusive' ? { chip: 'neutral', label: 'Inconclusive' }
    : { chip: 'info', label: 'Tracking' };

  return (
    <div className="card" style={{ gridColumn: 'span 12' }}>
      <div className="card-h" style={{ flexWrap: 'wrap', gap: 10 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>
          <h3 style={{ margin: 0 }}>Predictive evidence</h3>
          <span className="chip neutral" title="Walk-forward: the rule is learned on earlier data and scored on later data it never saw">out-of-sample</span>
        </div>
        {ev && <span style={{ fontSize: 10.5, color: 'var(--text-4)' }}>tested {new Date(ev.computed_at).toLocaleDateString([], { day: 'numeric', month: 'short' })} · refreshed weekly</span>}
      </div>
      <div className="card-b">
        {!ev && !em && (
          <div style={{ padding: '24px 0', textAlign: 'center', color: 'var(--text-3)', fontSize: 12.5 }}>
            {loading ? 'Loading…' : error ? 'The evidence is unavailable right now.' : 'The first weekly test runs shortly after the server starts.'}
          </div>
        )}
        {(ev || em) && (
          <>
            <div style={{ fontSize: 12, color: 'var(--text-3)', marginBottom: 6, lineHeight: 1.55 }}>
              Market pressure describes current conditions. Whether any of it forecasts BTC has to be shown on data the test never saw, so each signal below is graded on that alone.
            </div>
            {ev && ev.families.map((f) => {
              const st = F.evidenceStatus(f.status);
              return (
                <EV_Row key={f.id} name={f.name} chip={st.chip} chipLabel={st.label}
                        title={'Tested at 1, 3, 6, 12, 24 and 48 hours ahead (' + f.cells_tested + ' comparisons in this family)'}>
                  {f.best ? (
                    <>Best held-out result: {evPretty(f.best.feature)} at {f.best.horizon_h}h, correlation {F.signed(f.best.oos_r, 2)}, {f.best.folds} test blocks positive, adjusted p {f.best.p_adj == null ? '–' : f.best.p_adj.toFixed(2)}. {st.text}.</>
                  ) : <>Not enough history to test out-of-sample.</>}
                </EV_Row>
              );
            })}
            {verdict && verdict.text && (
              <EV_Row name="Expected-move size" chip={verdict.tone === 'bear' ? 'bear' : 'info'} chipLabel={verdict.tone === 'bear' ? 'Too narrow' : verdict.tone === 'info' ? 'Conservative' : 'Calibrated'}
                      title="Mean of |actual move| ÷ forecast size. Below 100% means the forecast was wider than the realised move.">
                {verdict.text} {F.sampleText(em.n, em.nIndependent)}{em.avgSizeRatioCi95 ? ' · 95% interval ' + F.range(em.avgSizeRatioCi95.map((v) => v * 100), 0, '%') : ''}. It forecasts the size of a move, never its direction.
              </EV_Row>
            )}
            {stateA && (
              <EV_Row name="State A: strong MACD while price structure is weak" chip={trackChip.chip} chipLabel={trackChip.label}
                      title="Rule frozen before any forward data: MACD component ≥ 70 and price-structure component ≤ 40, one entry per episode, 24h and 48h horizons">
                {F.trackLine(stateA)} Found in history, so it is a candidate until enough untouched forward observations are in.
              </EV_Row>
            )}
            <div style={{ marginTop: 12, fontSize: 10.5, color: 'var(--text-4)', lineHeight: 1.5 }}>
              {ev && <>Walk-forward test of {ev.candle_hours.toLocaleString('en-US')} hourly candles ({String(ev.from).slice(0, 10)} to {String(ev.to).slice(0, 10)}), controlled for BTC's own past returns, with the p-values adjusted for {ev.tests} comparisons. </>}
              “No demonstrated edge” means nothing held up in this much history; it is not proof that no relationship exists. Not financial advice.
            </div>
          </>
        )}
      </div>
    </div>
  );
}

function W_Evidence() {
  const [state, setState] = useStateEV({ data: null, error: null, loading: true });
  useEffectEV(() => {
    let cancelled = false, timer;
    const load = () => {
      fetch('/api/research-evidence')
        .then((r) => r.json())
        .then((j) => { if (!cancelled) setState({ data: j.ok ? j.data : null, error: j.ok ? null : (j.error || 'unavailable'), loading: false }); })
        .catch(() => { if (!cancelled) setState((s) => ({ ...s, error: 'unavailable', loading: false })); })
        .finally(() => { if (!cancelled) timer = setTimeout(load, EV_REFRESH_MS); });
    };
    load();
    return () => { cancelled = true; clearTimeout(timer); };
  }, []);
  return <EV_View data={state.data} loading={state.loading} error={state.error} />;
}

Object.assign(window, { W_Evidence, EV_View });
