// Cortex — Watchlist & Notes page.
// Two columns: HELD (positions in book) and WATCH (model-flagged + PM-noted).
// Each item shows model agreement, last note, and a quick-action strip.

function ModelAgreement({ row }) {
  // composite agreement score: high quality + low risk = high agreement
  const score = Math.max(0, Math.min(100, Math.round(row.quality * 0.4 + row.growth * 0.3 + row.inflection * 0.15 + (100 - row.risk) * 0.15)));
  const tone = score >= 70 ? CX.accent : score >= 45 ? CX.amber : CX.red;
  const label = score >= 70 ? 'concur' : score >= 45 ? 'mixed' : 'disagree';
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
      <div style={{ width: 70, height: 4, background: CX.line, position: 'relative' }}>
        <div style={{ position: 'absolute', inset: 0, width: `${score}%`, background: tone }} />
      </div>
      <Mono style={{ fontSize: 11, color: tone, letterSpacing: '0.06em' }}>{label}</Mono>
    </div>
  );
}

function WatchCard({ row, kind, note, sizing, weight }) {
  const bcolors = { compounder: CX.accent, cheap_decent: CX.blue, inflection: CX.amber, pullback: CX.dim, danger: CX.red };
  const up = parseFloat(row.thirty_d) >= 0;
  return (
    <div style={{ background: CX.panel, border: `1px solid ${CX.line}`, padding: '20px 22px' }}>
      <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 14 }}>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, flexWrap: 'wrap', minWidth: 0 }}>
          <Mono style={{ fontSize: 20, color: CX.textHi, letterSpacing: '0.01em' }}>{row.ticker}</Mono>
          <span style={{ fontFamily: CX.display, fontSize: 15, color: CX.text }}>{row.name}</span>
          <Mono style={{ fontSize: 11, color: CX.faint }}>{row.country.slice(0, 2).toUpperCase()} · {row.sector}</Mono>
        </div>
        <div style={{ display: 'flex', gap: 6, flexShrink: 0 }}>
          {kind === 'held' && weight && (
            <div style={{ padding: '4px 10px', background: CX.accentDim, color: CX.accent,
              fontFamily: CX.mono, fontSize: 11, letterSpacing: '0.06em' }}>{weight} weight</div>
          )}
          <Mono style={{ padding: '4px 10px', color: bcolors[row.bucket], fontSize: 11, letterSpacing: '0.06em', border: `1px solid ${bcolors[row.bucket]}`, opacity: 0.85 }}>
            ● {row.bucket}
          </Mono>
        </div>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 14, marginTop: 18, paddingTop: 18, borderTop: `1px solid ${CX.line}` }}>
        {[
          ['Δ 30D',     `${up ? '+' : ''}${row.thirty_d}%`, up ? CX.accent : CX.red, false, 'thirty_d'],
          ['Quality',   row.quality, CX.text, true, 'quality_score'],
          ['Risk',      row.risk, row.risk > 70 ? CX.red : row.risk > 40 ? CX.amber : CX.accent, true, 'risk_score'],
          ['Model',     null,    null, false, 'watch_model_agreement'],
        ].map((f, i) => (
          <div key={i} style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
            <div style={{ display: 'flex', alignItems: 'center' }}>
              <Mono style={{ fontSize: 10, color: CX.faint, letterSpacing: '0.14em' }}>{f[0].toUpperCase()}</Mono>
              {f[4] && <Help id={f[4]} />}
            </div>
            {f[0] === 'Model' ? <ModelAgreement row={row} />
              : f[3] ? (
                <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                  <div style={{ width: 60, height: 4, background: CX.line, position: 'relative' }}>
                    <div style={{ position: 'absolute', inset: 0, width: `${f[1]}%`, background: f[2] }} />
                  </div>
                  <Mono style={{ fontSize: 11, color: CX.text }}>{f[1]}</Mono>
                </div>
              ) : <Mono style={{ fontSize: 14, color: f[2] }}>{f[1]}</Mono>}
          </div>
        ))}
      </div>

      {note && (
        <div style={{ marginTop: 18, paddingTop: 18, borderTop: `1px solid ${CX.line}` }}>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 12 }}>
            <Mono style={{ fontSize: 10, color: CX.accent, letterSpacing: '0.16em' }}>{note.author}</Mono>
            <Mono style={{ fontSize: 11, color: CX.faint }}>{note.date}</Mono>
            {sizing && <Mono style={{ marginLeft: 'auto', fontSize: 11, color: CX.amber, letterSpacing: '0.08em' }}>{sizing}</Mono>}
          </div>
          <div style={{ marginTop: 8, fontFamily: CX.display, fontSize: 14, color: CX.text, lineHeight: 1.55, textWrap: 'pretty' }}>{note.body}</div>
        </div>
      )}

      <div style={{ marginTop: 18, display: 'flex', gap: 6 }}>
        <button style={cortexBtn(CX, 'ghost')}
          onClick={() => window.cortexGoTo?.({ page: 'tearsheet', ticker: row.ticker })}>
          Tear sheet
        </button>
        <button style={cortexBtn(CX, 'ghost')}
          onClick={() => window.cortexGoTo?.({ page: 'similar', ticker: row.ticker })}>
          Similar to…
        </button>
      </div>
    </div>
  );
}

function PageWatchlist() {
  // pick rows: held = compounder + cheap_decent at top; watch = inflection + flagged
  const held = ROWS.filter(r => r.held).slice(0, 6);
  const watch = ROWS.filter(r => r.watch && !r.held).slice(0, 6);

  // Notes / sizing / weights come from live data once PMs start using the
  // system. Until then these maps are empty — cards render without a note
  // block. Live source: window.NOTES_BY_TICKER (cortex.notes table).
  const liveNotes = window.NOTES_BY_TICKER || {};
  const notes = Object.fromEntries(
    Object.entries(liveNotes).map(([t, list]) => [t, Array.isArray(list) && list[0] ? list[0] : null])
      .filter(([_, n]) => n)
  );
  const noteCount = Object.values(liveNotes).reduce((n, list) => n + (Array.isArray(list) ? list.length : 0), 0);
  const sizing = {};
  const weights = {};

  const [tab, setTab] = React.useState('all');

  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' }}>05 · /Q.WATCH</Mono>
          <h1 style={{ fontFamily: CX.display, fontSize: 40, fontWeight: 400, letterSpacing: '-0.02em', margin: '8px 0 4px', color: CX.textHi }}>
            Watchlist &amp; notes<span style={{ color: CX.accent }}>.</span>
          </h1>
          <Mono style={{ fontSize: 11, color: CX.faint, letterSpacing: '0.08em' }}>
            {held.length} held · {watch.length} watching · 12 notes this week
          </Mono>
        </div>
        <div style={{ display: 'flex', gap: 4 }}>
          {[['all', 'All'], ['held', 'Held'], ['watch', 'Watching'], ['mine', 'Mine']].map(([id, label]) => {
            const on = tab === id;
            return (
              <button key={id} onClick={() => setTab(id)} style={{
                appearance: 'none', cursor: 'pointer',
                padding: '8px 14px',
                background: on ? CX.accentDim : 'transparent',
                color: on ? CX.accent : CX.dim,
                border: `1px solid ${on ? CX.accent : CX.lineHi}`,
                fontFamily: CX.mono, fontSize: 11, letterSpacing: '0.08em',
              }}>{label}</button>
            );
          })}
        </div>
      </div>

      {/* summary strip */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(5, 1fr)', gap: 1, background: CX.line, border: `1px solid ${CX.line}`, marginBottom: 28 }}>
        {[
          ['Positions held',   String(held.length), 'from watchlist data', CX.text],
          ['Watching',         String(watch.length), 'active watchlist',    CX.text],
          ['Concur — model',   String(held.filter(r => r.quality >= 70 && r.risk <= 50).length), `of ${held.length} held`, CX.accent],
          ['High risk held',   String(held.filter(r => r.risk > 70).length), 'risk score > 70', CX.red],
          ['Notes',            String(noteCount), 'persisted notes',        CX.text],
        ].map((k, i) => (
          <div key={i} style={{ background: CX.panel, padding: '18px 18px 20px' }}>
            <Mono style={{ fontSize: 10, color: CX.faint, letterSpacing: '0.16em' }}>{k[0].toUpperCase()}</Mono>
            <Mono style={{ display: 'block', fontSize: 28, color: k[3], marginTop: 10, letterSpacing: '-0.01em' }}>{k[1]}</Mono>
            <Mono style={{ display: 'block', fontSize: 11, color: CX.dim, marginTop: 4 }}>{k[2]}</Mono>
          </div>
        ))}
      </div>

      {/* two columns */}
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 24 }}>
        <div>
          <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 14 }}>
            <Mono style={{ fontSize: 11, color: CX.accent, letterSpacing: '0.16em' }}>● HELD — {held.length} POSITIONS</Mono>
            <Mono style={{ fontSize: 11, color: CX.dim }}>sorted · weight ↓</Mono>
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
            {held.length === 0 && (
              <div style={{ background: CX.panel, border: `1px solid ${CX.line}`, padding: '22px 24px' }}>
                <Mono style={{ fontSize: 11, color: CX.faint, letterSpacing: '0.06em', whiteSpace: 'normal' }}>
                  no held positions yet — held names are flagged by INSERTing into
                  cortex.watchlist with bucket = 'held'. Until then this column is
                  intentionally empty (not broken).
                </Mono>
              </div>
            )}
            {held.map(r => (
              <WatchCard key={r.security_id ?? r.ticker} row={r} kind="held"
                note={notes[r.ticker]} sizing={sizing[r.ticker]} weight={weights[r.ticker]} />
            ))}
          </div>
        </div>
        <div>
          <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 14 }}>
            <Mono style={{ fontSize: 11, color: CX.amber, letterSpacing: '0.16em' }}>● WATCH — {watch.length} CANDIDATES</Mono>
            <Mono style={{ fontSize: 11, color: CX.dim }}>sorted · rank ↑</Mono>
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
            {watch.length === 0 && (
              <div style={{ background: CX.panel, border: `1px solid ${CX.line}`, padding: '22px 24px' }}>
                <Mono style={{ fontSize: 11, color: CX.faint, letterSpacing: '0.06em', whiteSpace: 'normal' }}>
                  no candidates on the watchlist — candidates are flagged by
                  INSERTing into cortex.watchlist with status = 'Active'. Until
                  then this column is intentionally empty (not broken).
                </Mono>
              </div>
            )}
            {watch.map(r => (
              <WatchCard key={r.security_id ?? r.ticker} row={r} kind="watch" note={notes[r.ticker]} sizing={sizing[r.ticker]} />
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

window.PageWatchlist = PageWatchlist;
