// Cortex — production model rankings.

function _fmtPct(v) {
  if (v == null || Number.isNaN(Number(v))) return '—';
  const n = Number(v) * 100;
  return `${n >= 0 ? '+' : ''}${n.toFixed(1)}%`;
}

function _fmtScore(v) {
  if (v == null || Number.isNaN(Number(v))) return '—';
  return Number(v).toFixed(4);
}

function PagePredictions() {
  const summary = PREDICTIONS?.summary || [];
  const rowsByModel = PREDICTIONS?.rows_by_model || {};
  const asofByModel = PREDICTIONS?.asof_by_model || {};
  const defaultModel = PREDICTIONS?.selected_model || (summary[0]?.model) || null;
  const [model, setModel] = React.useState(defaultModel);
  const rows = (model && rowsByModel[model]) || PREDICTIONS?.rows || [];
  const modelAsof = (model && asofByModel[model]) || PREDICTIONS?.asof || '—';
  const [query, setQuery] = React.useState('');
  const [sector, setSector] = React.useState('all');
  const sectors = React.useMemo(() => {
    return ['all', ...Array.from(new Set(rows.map(r => r.sector).filter(Boolean))).sort()];
  }, [rows]);
  const filtered = React.useMemo(() => {
    const q = query.trim().toLowerCase();
    return rows.filter(r => {
      const hit = !q || String(r.ticker || '').toLowerCase().includes(q) || String(r.industry || '').toLowerCase().includes(q);
      const sec = sector === 'all' || r.sector === sector;
      return hit && sec;
    });
  }, [rows, query, sector]);

  return (
    <div style={{ padding: '32px 32px 64px', overflowY: 'auto', height: '100%' }}>
      <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', marginBottom: 24 }}>
        <div>
          <div style={{ display: 'flex', alignItems: 'center' }}>
            <Mono style={{ fontSize: 10, color: CX.accent, letterSpacing: '0.18em' }}>05 · /Q.MODEL</Mono>
            <Help id="model_rankings_page" />
          </div>
          <h1 style={{ fontFamily: CX.display, fontSize: 40, fontWeight: 400, letterSpacing: '-0.02em', margin: '8px 0 4px', color: CX.textHi }}>
            Model rankings<span style={{ color: CX.accent }}>.</span>
          </h1>
          <div style={{ display: 'flex', alignItems: 'center' }}>
            <Mono style={{ fontSize: 11, color: CX.accent, letterSpacing: '0.08em' }}>
              {model || 'no model'}
            </Mono>
            <Help id="model_selected" />
            <Mono style={{ fontSize: 11, color: CX.faint, letterSpacing: '0.08em' }}>
              &nbsp;· prediction date {modelAsof}
            </Mono>
            <Help id="model_prediction_date" />
            <Mono style={{ fontSize: 11, color: CX.faint, letterSpacing: '0.08em' }}>
              &nbsp;· {rows.length} rows
            </Mono>
          </div>
        </div>
        <div style={{ display: 'flex', gap: 8 }}>
          <input
            value={query}
            onChange={e => setQuery(e.target.value)}
            placeholder="ticker / industry"
            style={{
              width: 190, background: CX.panel, color: CX.text, border: `1px solid ${CX.lineHi}`,
              padding: '8px 10px', fontFamily: CX.mono, fontSize: 11, outline: 'none',
            }}
          />
          <select
            value={sector}
            onChange={e => setSector(e.target.value)}
            style={{
              width: 190, background: CX.panel, color: CX.text, border: `1px solid ${CX.lineHi}`,
              padding: '8px 10px', fontFamily: CX.mono, fontSize: 11, outline: 'none',
            }}
          >
            {sectors.map(s => <option key={s} value={s}>{s}</option>)}
          </select>
        </div>
      </div>

      {(() => {
        // Restrict tiles to production models — those with exported daily
        // predictions. The summary table also holds per-fold CV stats
        // (fold_1..fold_8) for diagnostic purposes; they're not actionable
        // from this page.
        const productionTiles = summary.filter(s => s.model && rowsByModel[s.model]?.length);
        const tiles = productionTiles.length
          ? productionTiles.slice(0, 4)
          : (summary.length ? summary.slice(0, 4) : [{ model: defaultModel || '—' }]);
        return (
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 1, background: CX.line, border: `1px solid ${CX.line}`, marginBottom: 24 }}>
        {tiles.map((s, i) => {
          const isActive = s.model === model;
          const hasRows = Boolean(s.model && rowsByModel[s.model]?.length);
          const clickable = hasRows && s.model;
          // `<div role="button">` rather than `<button>` because the tile body
          // contains nested `<button>` elements (the Help ? icons). HTML
          // forbids button-in-button — Chrome auto-closes the outer button,
          // which breaks click handling on the tile.
          return (
            <div
              key={i}
              role="button"
              tabIndex={clickable ? 0 : -1}
              aria-disabled={!clickable}
              onClick={() => { if (clickable) setModel(s.model); }}
              onKeyDown={(e) => {
                if (!clickable) return;
                if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); setModel(s.model); }
              }}
              title={!hasRows ? `no exported predictions for ${s.model}` : `switch to ${s.model}`}
              style={{
                background: isActive ? CX.accentVery : CX.panel,
                padding: '18px 18px 20px',
                borderTop: `2px solid ${isActive ? CX.accent : 'transparent'}`,
                cursor: clickable ? 'pointer' : 'not-allowed',
                opacity: clickable ? 1 : 0.55,
                userSelect: 'none',
                transition: 'background .12s, border-color .12s',
              }}
              onMouseEnter={(e) => { if (clickable && !isActive) e.currentTarget.style.background = CX.panelHi; }}
              onMouseLeave={(e) => { if (clickable && !isActive) e.currentTarget.style.background = CX.panel; }}
            >
              <div style={{ display: 'flex', alignItems: 'center' }}>
                <Mono style={{ fontSize: 10, color: isActive ? CX.accent : CX.faint, letterSpacing: '0.16em' }}>{String(s.model || 'MODEL').toUpperCase()}</Mono>
                <Help id="model_tile" />
              </div>
              <div style={{ display: 'flex', alignItems: 'center', marginTop: 10 }}>
                <Mono style={{ fontSize: 28, color: isActive ? CX.accent : CX.text }}>
                  {_fmtPct(s.avg_excess_return_12m)}
                </Mono>
                <Help id="model_avg_excess_return_12m" />
              </div>
              <div style={{ display: 'flex', alignItems: 'center', marginTop: 4 }}>
                <Mono style={{ fontSize: 11, color: CX.dim, letterSpacing: '0.04em' }}>
                  hit {_fmtPct(s.avg_hit_rate)}
                </Mono>
                <Help id="model_avg_hit_rate" />
                <Mono style={{ fontSize: 11, color: CX.dim, letterSpacing: '0.04em' }}>
                  &nbsp;· {s.periods || 0} periods
                </Mono>
                <Help id="model_periods" />
              </div>
            </div>
          );
        })}
      </div>
        );
      })()}

      <div style={{ border: `1px solid ${CX.line}`, background: CX.panel, overflow: 'hidden' }}>
        <div style={{ display: 'grid', gridTemplateColumns: '64px 96px 110px 1fr 1fr 110px 100px', borderBottom: `1px solid ${CX.line}` }}>
          {[
            ['RANK',     'model_prediction_rank'],
            ['TICKER',   null],
            ['SCORE',    'model_prediction_score'],
            ['SECTOR',   null],
            ['INDUSTRY', null],
            ['COUNTRY',  null],
            ['MARKET',   null],
          ].map(([h, helpId]) => (
            <div key={h} style={{ display: 'flex', alignItems: 'center', padding: '12px 10px' }}>
              <Mono style={{ fontSize: 10, color: CX.faint, letterSpacing: '0.1em' }}>{h}</Mono>
              {helpId && <Help id={helpId} />}
            </div>
          ))}
        </div>
        <div style={{ maxHeight: 620, overflowY: 'auto' }}>
          {filtered.map((r, i) => (
            <div key={`${r.model}-${r.security_id}`} style={{
              display: 'grid', gridTemplateColumns: '64px 96px 110px 1fr 1fr 110px 100px',
              borderBottom: `1px solid ${CX.line}`,
              background: i % 2 ? 'transparent' : 'rgba(255,255,255,0.012)',
            }}>
              <Mono style={{ padding: '11px 10px', color: r.rank <= 20 ? CX.accent : CX.faint, fontSize: 12 }}>{r.rank}</Mono>
              <Mono style={{ padding: '11px 10px', color: CX.textHi, fontSize: 12 }}>{r.ticker}</Mono>
              <Mono style={{ padding: '11px 10px', color: CX.accent, fontSize: 12 }}>{_fmtScore(r.score)}</Mono>
              <Mono style={{ padding: '11px 10px', color: CX.dim, fontSize: 11 }}>{r.sector || '—'}</Mono>
              <Mono style={{ padding: '11px 10px', color: CX.dim, fontSize: 11 }}>{r.industry || '—'}</Mono>
              <Mono style={{ padding: '11px 10px', color: CX.text, fontSize: 11 }}>{r.country || '—'}</Mono>
              <Mono style={{ padding: '11px 10px', color: CX.faint, fontSize: 11 }}>{r.market || '—'}</Mono>
            </div>
          ))}
          {!filtered.length && (
            <div style={{ padding: 36, textAlign: 'center' }}>
              <Mono style={{ fontSize: 11, color: CX.faint, letterSpacing: '0.12em' }}>NO MODEL PREDICTIONS EXPORTED</Mono>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

window.PagePredictions = PagePredictions;
