// Cortex — Similar To… page.
// Vector search over the universe. Anchor ticker + distance metric tabs.

function SimilarityBar({ value, w = 240 }) {
  // value 0..1, 1 = identical
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
      <div style={{ width: w, height: 5, background: CX.line, position: 'relative' }}>
        <div style={{ position: 'absolute', inset: 0, width: `${value * 100}%`, background: CX.accent }} />
      </div>
      <Mono style={{ fontSize: 11, color: CX.text, width: 44, textAlign: 'right' }}>{(value * 100).toFixed(1)}</Mono>
    </div>
  );
}

function PageSimilar({ initialAnchor }) {
  const [anchor, setAnchor] = React.useState(
    (initialAnchor && ROWS.find(r => r.ticker === initialAnchor)) || ROWS[0]
  );
  // If the parent updates initialAnchor via cross-page nav, follow it.
  React.useEffect(() => {
    if (!initialAnchor) return;
    const next = ROWS.find(r => r.ticker === initialAnchor);
    if (next) setAnchor(next);
  }, [initialAnchor]);
  const [metric, setMetric] = React.useState('factor');
  const [universe, setUniverse] = React.useState('all_nordics');
  const [k, setK] = React.useState(12);

  // compute pseudo-similarity to the anchor based on score-vector distance
  function distance(a, b) {
    const keys = ['quality', 'value', 'growth', 'momentum', 'inflection', 'risk'];
    let d = 0;
    keys.forEach(k => { d += ((a[k] - b[k]) / 100) ** 2; });
    if (metric === 'sector' && a.sector !== b.sector) d += 0.4;
    if (metric === 'narrative' && a.bucket !== b.bucket) d += 0.25;
    return Math.sqrt(d);
  }
  const results = React.useMemo(() => {
    // Prefer server-side neighbors when the live data ships them (factor
    // metric only — narrative/sector/return variants stay client-side).
    const live = window.SIMILAR_BY_TICKER?.[anchor.ticker];
    if (metric === 'factor' && live && live.length) {
      return live.slice(0, k).map((entry, i) => {
        const row = ROWS.find(r => r.ticker === entry.ticker) || {
          ticker: entry.ticker, name: entry.name || entry.ticker,
          country: entry.country || '', sector: entry.sector || '',
          bucket: entry.bucket || 'cheap_decent', thirty_d: entry.thirty_d ?? '0.0',
        };
        return { row, dist: 1 - (entry.similarity ?? 0), sim: entry.similarity ?? 0, rank: i + 1 };
      });
    }
    return ROWS
      .filter(r => r.ticker !== anchor.ticker)
      .map(r => ({ row: r, dist: distance(anchor, r) }))
      .sort((a, b) => a.dist - b.dist)
      .slice(0, k)
      .map((x, i) => ({ ...x, sim: Math.max(0, 1 - x.dist / 1.4), rank: i + 1 }));
  }, [anchor, metric, k]);

  // Only the factor metric is wired to real server-side data
  // (cortex.similar_companies). Sector / Narrative / Returns variants were
  // present in the design but never wired; removed to avoid the "looks
  // implemented but isn't" trap.
  const tabs = [
    ['factor', 'Factor vector', '12-dim financial fingerprint, Euclidean over rank-z-scored features', 'similarity_numeric'],
  ];

  return (
    <div style={{ padding: '32px 32px 64px', overflowY: 'auto', height: '100%' }}>
      <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', marginBottom: 24 }}>
        <div>
          <Mono style={{ fontSize: 10, color: CX.accent, letterSpacing: '0.18em' }}>03 · /Q.NEIGHBORS</Mono>
          <h1 style={{ fontFamily: CX.display, fontSize: 40, fontWeight: 400, letterSpacing: '-0.02em', margin: '8px 0 4px', color: CX.textHi }}>
            Similar to<span style={{ color: CX.accent }}>…</span>
          </h1>
          <Mono style={{ fontSize: 11, color: CX.faint, letterSpacing: '0.08em' }}>nearest neighbours in the Nordic universe · k = {k}</Mono>
        </div>
        <TickerSelector value={anchor} onChange={setAnchor} />
      </div>

      {/* metric tabs */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 0, border: `1px solid ${CX.line}`, marginBottom: 24, background: CX.panel }}>
        {tabs.map(([id, label, sub, helpId]) => {
          const on = metric === id;
          return (
            <div key={id} role="button" tabIndex={0}
              onClick={() => setMetric(id)}
              onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); setMetric(id); } }}
              style={{ cursor: 'pointer', textAlign: 'left',
                padding: '18px 22px', borderRight: `1px solid ${CX.line}`,
                background: on ? CX.accentVery : 'transparent',
                borderTop: `2px solid ${on ? CX.accent : 'transparent'}`,
                userSelect: 'none',
                marginTop: -1,
              }}>
              <div style={{ display: 'flex', alignItems: 'center' }}>
                <Mono style={{ fontSize: 10, color: on ? CX.accent : CX.faint, letterSpacing: '0.16em' }}>METRIC</Mono>
                <Help id={helpId} />
              </div>
              <div style={{ fontFamily: CX.display, fontSize: 16, color: on ? CX.textHi : CX.text, marginTop: 8 }}>{label}</div>
              <Mono style={{ fontSize: 11, color: CX.dim, marginTop: 6, display: 'block', letterSpacing: '0.04em' }}>{sub}</Mono>
            </div>
          );
        })}
      </div>

      {/* controls */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 24, marginBottom: 18, padding: '14px 18px',
        border: `1px solid ${CX.line}`, background: CX.panel }}>
        <Mono style={{ fontSize: 10, color: CX.faint, letterSpacing: '0.14em' }}>UNIVERSE</Mono>
        <div style={{ display: 'flex', gap: 4 }}>
          {[['all_nordics', 'All Nordics'], ['investable', 'Investable only'], ['held', 'Held + watch']].map(([id, label]) => {
            const on = universe === id;
            return (
              <button key={id} onClick={() => setUniverse(id)} style={{
                appearance: 'none', cursor: 'pointer',
                padding: '6px 12px',
                background: on ? CX.accentDim : 'transparent',
                color: on ? CX.accent : CX.dim,
                border: `1px solid ${on ? CX.accent : CX.line}`,
                fontFamily: CX.mono, fontSize: 11, letterSpacing: '0.04em',
              }}>{label}</button>
            );
          })}
        </div>
        <div style={{ width: 1, height: 18, background: CX.line }} />
        <Mono style={{ fontSize: 10, color: CX.faint, letterSpacing: '0.14em' }}>k</Mono>
        <div style={{ display: 'flex', gap: 4 }}>
          {[6, 12, 24, 48].map(n => {
            const on = k === n;
            return (
              <button key={n} onClick={() => setK(n)} style={{
                appearance: 'none', cursor: 'pointer',
                padding: '6px 12px', minWidth: 44,
                background: on ? CX.accentDim : 'transparent',
                color: on ? CX.accent : CX.dim,
                border: `1px solid ${on ? CX.accent : CX.line}`,
                fontFamily: CX.mono, fontSize: 11,
              }}>{n}</button>
            );
          })}
        </div>
        <div style={{ flex: 1 }} />
        <Mono style={{ fontSize: 11, color: CX.dim }}>compute · 14ms · cached</Mono>
      </div>

      {/* anchor row banner */}
      <div style={{ background: CX.panelHi, border: `1px solid ${CX.lineHi}`, padding: '16px 22px', marginBottom: 0,
        display: 'flex', alignItems: 'center', gap: 24 }}>
        <Mono style={{ fontSize: 10, color: CX.accent, letterSpacing: '0.18em' }}>ANCHOR</Mono>
        <Mono style={{ fontSize: 18, color: CX.textHi }}>{anchor.ticker}</Mono>
        <span style={{ fontFamily: CX.display, fontSize: 15, color: CX.text }}>{anchor.name}</span>
        <Mono style={{ fontSize: 11, color: CX.dim }}>{anchor.country} · {anchor.sector}</Mono>
        <div style={{ flex: 1 }} />
        <Mono style={{ fontSize: 11, color: CX.faint, letterSpacing: '0.06em' }}>vector: [{anchor.quality}, {anchor.value}, {anchor.growth}, {anchor.momentum}, {anchor.inflection}, {anchor.risk}]</Mono>
      </div>

      {/* result list */}
      <div style={{ border: `1px solid ${CX.line}`, borderTop: 'none', background: CX.panel }}>
        <div style={{ display: 'grid', gridTemplateColumns: '40px 80px 200px 70px 140px 1fr 90px 90px',
          padding: '12px 18px', borderBottom: `1px solid ${CX.line}`,
          fontFamily: CX.mono, fontSize: 10, color: CX.faint, letterSpacing: '0.1em' }}>
          <div>#</div><div>TICKER</div><div>COMPANY</div><div>CTRY</div><div>SECTOR</div>
          <div style={{ display: 'flex', alignItems: 'center' }}>SIMILARITY<Help id={metric === 'narrative' ? 'similarity_semantic' : 'similarity_numeric'} /></div>
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end' }}>BUCKET<Help id="primary_signal_bucket" side="left" /></div>
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end' }}>Δ 30D<Help id="thirty_d" side="left" /></div>
        </div>
        {results.map((res, i) => {
          const r = res.row;
          const bcolors = { compounder: CX.accent, cheap_decent: CX.blue, inflection: CX.amber, pullback: CX.dim, danger: CX.red };
          const up = parseFloat(r.thirty_d) >= 0;
          return (
            <div key={r.security_id ?? r.ticker} style={{
              display: 'grid', gridTemplateColumns: '40px 80px 200px 70px 140px 1fr 90px 90px',
              padding: '12px 18px', borderBottom: i < results.length - 1 ? `1px solid ${CX.line}` : 'none',
              alignItems: 'center', fontFamily: CX.mono, fontSize: 12, color: CX.text,
            }}>
              <Mono style={{ color: CX.faint }}>{res.rank}</Mono>
              <Mono style={{ color: CX.textHi }}>{r.ticker}</Mono>
              <div style={{ fontFamily: CX.display, color: CX.dim, fontSize: 13 }}>{r.name}</div>
              <Mono style={{ color: CX.dim }}>{ { Sverige:'SE', Norge:'NO', Danmark:'DK', Finland:'FI', Island:'IS' }[r.country] }</Mono>
              <Mono style={{ color: CX.dim, fontSize: 11 }}>{r.sector}</Mono>
              <SimilarityBar value={res.sim} />
              <Mono style={{ textAlign: 'right', color: r.bucket ? bcolors[r.bucket] : CX.faint, fontSize: 11, letterSpacing: '0.04em' }}>● {r.bucket || 'unflagged'}</Mono>
              <Mono style={{ textAlign: 'right', color: up ? CX.accent : CX.red }}>{up ? '+' : ''}{r.thirty_d}%</Mono>
            </div>
          );
        })}
      </div>

      <Mono style={{ display: 'block', marginTop: 14, fontSize: 11, color: CX.faint, letterSpacing: '0.06em' }}>
        results are neighbours in factor / embedding space, not investment recommendations. methodology →
      </Mono>
    </div>
  );
}

window.PageSimilar = PageSimilar;
