// Fin45 — shared site components
// Nav · Ticker · Scoreboard strip · Footer · Wordmark · charts · mascot wrappers

const { useState, useEffect, useMemo, useRef } = React;
const D = window.FIN_DATA;

// ── small helpers ──────────────────────────────────────────────
const fmtMoney = (n) => '$' + n.toLocaleString('en-US', { maximumFractionDigits: 0 });
const fmtSigned = (n) => (n > 0 ? '+' : '') + n.toFixed(2);

function navTo(path) {
  window.location.hash = path;
}

function useHashRoute() {
  const get = () => {
    const h = window.location.hash.replace(/^#/, '');
    return h || '/';
  };
  const [route, setRoute] = useState(get);
  useEffect(() => {
    const on = () => setRoute(get());
    window.addEventListener('hashchange', on);
    return () => window.removeEventListener('hashchange', on);
  }, []);
  return route;
}

// ── Wordmark ───────────────────────────────────────────────────
function Wordmark({ size = 'md', accentTuned }) {
  return (
    <span className={`wm wm-${size}`} aria-label="Fin45">
      <span className="wm-fin">Fin</span>
      <span className="wm-45">45</span>
    </span>
  );
}
window.Wordmark = Wordmark;

// ── Top nav ────────────────────────────────────────────────────
function TopNav() {
  const route = useHashRoute();
  const item = (path, label) => {
    const on = route === path || (path !== '/' && route.startsWith(path));
    return (
      <li key={path}>
        <a href={'#' + path} className={on ? 'on' : ''}>{label}</a>
      </li>
    );
  };
  return (
    <nav className="topnav">
      <a className="nav-brand" href="#/">
        <Wordmark size="md" />
      </a>
      <ul className="nav-links">
        {item('/today',     'Today')}
        {item('/archive',   'Archive')}
        {item('/portfolio', 'Portfolio')}
        {item('/trackers',  'Trackers')}
        {item('/lookback',  'Lookback')}
        {item('/about',     'About')}
      </ul>
      <div className="nav-cta">
        <a href="#subscribe" className="btn-subscribe">Subscribe</a>
      </div>
    </nav>
  );
}
window.TopNav = TopNav;

// ── Market ticker (top edge) ───────────────────────────────────
function TickerStrip() {
  // duplicate twice for seamless scroll
  const items = [...D.ticker, ...D.ticker];
  return (
    <div className="ticker">
      <div className="ticker-track">
        {items.map((t, i) => (
          <span key={i} className={'tk' + (t.isFin45 ? ' is-fin45' : '')}>
            <span className="tk-sym">{t.sym}</span>
            <span className="tk-price">{t.px}</span>
            <span className={'tk-delta ' + t.dir}>{t.d}</span>
            <span className="ticker-sep">/</span>
          </span>
        ))}
      </div>
    </div>
  );
}
window.TickerStrip = TickerStrip;

// ── Scoreboard strip (below ticker, narrow band) ──────────────
function ScoreboardStrip() {
  const s = D.scoreboard;
  const m = D.meta;
  const moodCls = s.mood === 'RISK-ON' ? '' : s.mood === 'RISK-OFF' ? 'risk-off' : 'neutral';
  const dDir = s.deltaUsd > 0 ? 'up' : 'dn';
  return (
    <div className="score-strip">
      <span className="score-cell">
        <span className="lbl">Day</span>
        <span className="val">{m.day} of {m.totalDays}</span>
      </span>
      <span className="score-sep">·</span>
      <span className="score-cell">
        <span className="lbl">Portfolio</span>
        <span className="val gold">{fmtMoney(s.value)}</span>
      </span>
      <span className="score-sep">·</span>
      <span className="score-cell">
        <span className={'val ' + dDir}>{s.deltaUsd >= 0 ? '+' : ''}{fmtMoney(s.deltaUsd).replace('$','$')}</span>
        <span className={dDir}>({s.deltaPct >= 0 ? '+' : ''}{s.deltaPct}%)</span>
        <span className="lbl">today</span>
      </span>
      <span className="score-sep">·</span>
      <span className="score-cell">
        <span className={'mood-badge ' + moodCls}>
          <span className="mood-dot" />
          {s.mood}
        </span>
      </span>
      <span className="score-sep">·</span>
      <span className="score-cell">
        <span className="lbl">Win rate</span>
        <span className="val">{s.winRate}%</span>
      </span>
      <span className="score-sep">·</span>
      <span className="score-cell">
        <span className="lbl">Open</span>
        <span className="val">{s.openPositions} positions</span>
      </span>
    </div>
  );
}
window.ScoreboardStrip = ScoreboardStrip;

// ── Scoreboard tile (used inside editions) ────────────────────
function ScoreboardTile() {
  const s = D.scoreboard;
  const dDir = s.deltaUsd > 0 ? 'up' : 'dn';
  const moodCls = s.mood === 'RISK-ON' ? '' : s.mood === 'RISK-OFF' ? 'risk-off' : 'neutral';
  return (
    <div className="sb-tile">
      <div className="sb-row1">
        <div>
          <div className="sb-value">{fmtMoney(s.value)}</div>
        </div>
        <div className={'sb-delta ' + dDir}>
          {s.deltaUsd >= 0 ? '+' : ''}{fmtMoney(s.deltaUsd)} ({s.deltaPct >= 0 ? '+' : ''}{s.deltaPct}%)
        </div>
        <span className={'mood-badge ' + moodCls}>
          <span className="mood-dot" />
          {s.mood}
        </span>
      </div>
      <div>
        <div className="sb-bar">
          <div className="sb-bar-fill" style={{ width: (s.monthProgressPct / s.monthlyTargetPct * 100) + '%' }} />
        </div>
        <div className="sb-bar-meta">
          <span>Monthly progress · {s.monthProgressPct}%</span>
          <span>Target {s.monthlyTargetPct}%</span>
        </div>
      </div>
      <div className="sb-stats">
        <span className="sb-stat"><span className="lbl">Open</span><span className="val">{s.openPositions}</span></span>
        <span className="sb-stat"><span className="lbl">Win rate</span><span className="val">{s.winRate}%</span></span>
        <span className="sb-stat"><span className="lbl">Mood</span><span className="val">{s.mood}</span></span>
        <span className="sb-stat"><span className="lbl">Cash</span><span className="val">58.7%</span></span>
      </div>
    </div>
  );
}
window.ScoreboardTile = ScoreboardTile;

// ── Signal map list ───────────────────────────────────────────
function SignalMap({ limit }) {
  const rows = limit ? D.signals.slice(0, limit) : D.signals;
  return (
    <div className="signal-list">
      {rows.map((s, i) => (
        <div key={i} className="signal-row">
          <span className="signal-arrow">▸</span>
          <span className="signal-text">{s.text}</span>
          <span className={'signal-tag ' + s.tag}>{s.tag}</span>
        </div>
      ))}
    </div>
  );
}
window.SignalMap = SignalMap;

// ── Blotter ────────────────────────────────────────────────────
function Blotter({ limit }) {
  const rows = limit ? D.blotter.slice(0, limit) : D.blotter;
  return (
    <div className="blotter">
      {rows.map((r, i) => (
        <div key={i} className={'blotter-row ' + r.act.toLowerCase()}>
          <span>{
            r.act === 'BUY'  ? '▐' :
            r.act === 'SELL' ? '▌' :
            r.act === 'HOLD' ? '◆' : '░'
          }</span>
          <span className="act">{r.act}</span>
          <span>
            <span className="tick">{r.tk}</span>
            {r.size ? <span style={{ color: 'var(--text-muted)', marginLeft: 10 }}>{r.size}</span> : null}
            <div className="why" style={{ marginTop: 4 }}>{r.why}</div>
          </span>
          <span className="conv">Conv {r.conv.toFixed(2)}</span>
          <span className="ts">{r.ts}</span>
        </div>
      ))}
    </div>
  );
}
window.Blotter = Blotter;

// ── Honest Number comparison ──────────────────────────────────
function HonestNumber({ compact = false }) {
  const h = D.honest;
  const fin = h.fin45;
  const spy = h.spy;
  const max = Math.max(fin, spy, 0.01);
  const finPct = (fin / max) * 100;
  const spyPct = (spy / max) * 100;
  return (
    <div className="honest">
      <div className="honest-h">The Honest Number{compact ? '' : ' · Fin45 vs SPY'}</div>
      <div className="honest-row">
        <span className="name">Fin45</span>
        <div className="honest-bar">
          <div className={'honest-bar-fill' + (h.ahead ? '' : ' behind')} style={{ width: finPct + '%' }} />
        </div>
        <span className="pct up">+{fin.toFixed(2)}%</span>
      </div>
      <div className="honest-row">
        <span className="name">S&P 500 (SPY)</span>
        <div className="honest-bar">
          <div className="honest-bar-fill spy" style={{ width: spyPct + '%' }} />
        </div>
        <span className="pct">+{spy.toFixed(2)}%</span>
      </div>
      <div className="honest-foot">Updated daily after market close · {h.period}</div>
    </div>
  );
}
window.HonestNumber = HonestNumber;

// ── Equity curve SVG ──────────────────────────────────────────
function EquityCurve({ height = 280, withMarkers = true }) {
  const data = D.equityCurve;
  const W = 1200, H = height, padL = 8, padR = 8, padT = 24, padB = 24;
  const min = Math.min(...data) - 200;
  const max = Math.max(...data) + 200;
  const xs = (i) => padL + (i / (data.length - 1)) * (W - padL - padR);
  const ys = (v) => padT + (1 - (v - min) / (max - min)) * (H - padT - padB);
  const path = data.map((v, i) => (i === 0 ? 'M' : 'L') + xs(i).toFixed(1) + ' ' + ys(v).toFixed(1)).join(' ');
  const areaPath = path + ` L ${xs(data.length - 1).toFixed(1)} ${(H - padB).toFixed(1)} L ${xs(0).toFixed(1)} ${(H - padB).toFixed(1)} Z`;

  // gridlines at 100k, 105k, 110k
  const grid = [100000, 102500, 105000];
  const startY = ys(100000);
  const buys = [0, 5, 10, 17, 22, 29, 35, 41, 46];
  const sells = [12, 25, 37];
  return (
    <svg className="equity-svg" viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="none">
      <defs>
        <linearGradient id="eq-fill" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="#D4A24C" stopOpacity="0.35" />
          <stop offset="100%" stopColor="#D4A24C" stopOpacity="0" />
        </linearGradient>
      </defs>
      {/* grid */}
      {grid.map((g) => (
        <line key={g} x1={padL} x2={W - padR} y1={ys(g)} y2={ys(g)} stroke="rgba(255,255,255,0.06)" strokeWidth="1" />
      ))}
      {/* starting line at $100k */}
      <line x1={padL} x2={W - padR} y1={startY} y2={startY} stroke="rgba(255,255,255,0.18)" strokeDasharray="4 6" strokeWidth="1" />
      <text x={W - padR - 4} y={startY - 6} fill="rgba(255,255,255,0.4)" fontFamily="JetBrains Mono, monospace" fontSize="11" textAnchor="end">$100,000 start</text>

      {/* area */}
      <path d={areaPath} fill="url(#eq-fill)" />
      {/* curve */}
      <path d={path} fill="none" stroke="#D4A24C" strokeWidth="2.2" strokeLinejoin="round" strokeLinecap="round" />

      {withMarkers && buys.map(i => (
        <circle key={'b' + i} cx={xs(i)} cy={ys(data[i])} r="3.5" fill="#10B981" stroke="#000" strokeWidth="1.5" />
      ))}
      {withMarkers && sells.map(i => (
        <circle key={'s' + i} cx={xs(i)} cy={ys(data[i])} r="3.5" fill="#EF4444" stroke="#000" strokeWidth="1.5" />
      ))}
      {/* end label */}
      <circle cx={xs(data.length - 1)} cy={ys(data[data.length - 1])} r="5" fill="#D4A24C" />
      <text x={xs(data.length - 1) - 10} y={ys(data[data.length - 1]) - 14} fill="#E8C079"
            fontFamily="JetBrains Mono, monospace" fontSize="14" fontWeight="600" textAnchor="end">
        ${data[data.length - 1].toLocaleString()}
      </text>
    </svg>
  );
}
window.EquityCurve = EquityCurve;

// ── Positions table ───────────────────────────────────────────
function PositionsTable() {
  const totalSize = D.positions.reduce((s, p) => s + p.size, 0);
  return (
    <>
      <table className="positions-table">
        <thead>
          <tr>
            <th>Ticker</th>
            <th className="pt-right">Entry</th>
            <th className="pt-right">Current</th>
            <th className="pt-right">P&L</th>
            <th className="pt-right">Hold</th>
            <th className="pt-right">Size</th>
            <th className="pt-right">Weight</th>
          </tr>
        </thead>
        <tbody>
          {D.positions.map((p, i) => {
            const pnl = (p.cur - p.entry) / p.entry * 100;
            const dir = pnl >= 0 ? 'up' : 'dn';
            return (
              <tr key={i}>
                <td className="pt-tick">{p.tk}</td>
                <td className="pt-right">${p.entry.toFixed(2)}</td>
                <td className="pt-right">${p.cur.toFixed(2)}</td>
                <td className={'pt-right pt-pnl ' + dir}>{pnl >= 0 ? '+' : ''}{pnl.toFixed(1)}%</td>
                <td className="pt-right">{p.hold}d</td>
                <td className="pt-right">${p.size.toLocaleString()}</td>
                <td className="pt-right">{p.weight.toFixed(1)}%</td>
              </tr>
            );
          })}
        </tbody>
      </table>
      <div className="positions-foot">
        <span>Total exposure: <strong>${totalSize.toLocaleString()}</strong> ({(totalSize/103240*100).toFixed(1)}%)</span>
        <span>Cash: <strong>${(103240 - totalSize).toLocaleString()}</strong> ({((103240-totalSize)/103240*100).toFixed(1)}%)</span>
      </div>
    </>
  );
}
window.PositionsTable = PositionsTable;

// ── Allocation bar ────────────────────────────────────────────
function AllocationBar() {
  return (
    <>
      <div className="alloc-bar">
        {D.alloc.map((a, i) => (
          <div key={i} className="alloc-seg"
            style={{ width: a.pct + '%', background: a.color, color: a.pct > 8 && a.name !== 'Cash' ? '#000' : '#D4A24C' }}>
            {a.pct > 8 ? a.pct.toFixed(0) + '%' : ''}
          </div>
        ))}
      </div>
      <div className="alloc-legend">
        {D.alloc.map((a, i) => (
          <span key={i}><span className="sw" style={{ background: a.color }} />{a.name} {a.pct.toFixed(1)}%</span>
        ))}
      </div>
    </>
  );
}
window.AllocationBar = AllocationBar;

// ── Monthly returns grid ──────────────────────────────────────
function MonthsGrid() {
  const months = ['Jun','Jul','Aug','Sep','Oct','Nov','Dec','Jan','Feb','Mar','Apr','May'];
  // Only June (index 0) has data → +4.8%, below 10% target → "low"
  const data2026 = [
    { pct: '+4.8%', cls: 'low' },
    null, null, null, null, null, null, null, null, null, null, null,
  ];
  const target = months.map(() => '+10%');
  return (
    <div className="months-grid">
      <div className="cell hd"></div>
      {months.map(m => <div key={m} className="cell hd">{m}</div>)}
      <div className="cell row-lbl">2026</div>
      {data2026.map((d, i) => (
        <div key={i} className={'cell ' + (d ? d.cls : 'fut')}>{d ? d.pct : '—'}</div>
      ))}
      <div className="cell row-lbl">Target</div>
      {target.map((t, i) => <div key={i} className="cell">{t}</div>)}
    </div>
  );
}
window.MonthsGrid = MonthsGrid;

// ── Footer ────────────────────────────────────────────────────
function Footer() {
  return (
    <footer className="site-footer">
      <div className="ft-top">
        <Wordmark size="md" />
        <p className="ft-line">The AI experiment, documented.</p>
      </div>
      <div className="ft-grid">
        <div>
          <span className="ft-h">Editions</span>
          <a href="#/today">Today</a>
          <a href="#/archive">Archive</a>
          <a href="#/lookback">Lookback</a>
          <a href="#/report-card">Report card</a>
        </div>
        <div>
          <span className="ft-h">Data</span>
          <a href="#/portfolio">Portfolio</a>
          <a href="#/trackers">Trackers</a>
          <a href="#/methodology">Methodology</a>
          <a href="#/changelog">Changelog</a>
        </div>
        <div>
          <span className="ft-h">Trackers</span>
          <a href="#/tracker/congress">Congress</a>
          <a href="#/tracker/musk">Elon Musk</a>
          <a href="#/tracker/spy">SPY · S&amp;P 500</a>
          <a href="#/trackers">All trackers →</a>
        </div>
        <div>
          <span className="ft-h">Legal</span>
          <a href="#/about">About</a>
          <a href="#/legal">Disclaimers</a>
          <a href="#/privacy">Privacy policy</a>
          <a href="#/terms">Terms of service</a>
        </div>
      </div>
      <div className="ft-bottom">
        <span>© 2026 Fin45 · fin45.ai · Zagoso LLC · Bend, Oregon</span>
        <span>
          <a href="https://x.com/andrewcmcguire" style={{ marginRight: 18 }}>x.com/andrewcmcguire</a>
          <a href="mailto:hello@fin45.ai">hello@fin45.ai</a>
        </span>
      </div>
    </footer>
  );
}
window.Footer = Footer;

// ── Subscribe CTA section ─────────────────────────────────────
function SubscribeCTA({ heading }) {
  return (
    <section className="subscribe-cta" id="subscribe">
      <h2 className="cta-headline">{heading || (<>The AI experiment,<br />in your inbox.</>)}</h2>
      <p className="cta-sub">5:30 PM ET, Monday through Friday · Free</p>
      <form className="cta-form" onSubmit={(e) => e.preventDefault()}>
        <input type="email" placeholder="you@domain.com" />
        <button type="submit">Subscribe</button>
      </form>
      <p className="cta-meta">No referral program. No stock picks. Unsubscribe is one click.</p>
    </section>
  );
}
window.SubscribeCTA = SubscribeCTA;

// ── Mascot sized wrapper (Fin must be available) ──────────────
function FinMascot({ pose = 'ticker', size = 280 }) {
  const Fin = window.Fin;
  if (!Fin) return <div style={{ width: size, height: size }} />;
  return <Fin pose={pose} size={size} bg="transparent" glow={true} style={{ background: 'transparent', borderRadius: 0 }} />;
}
window.FinMascot = FinMascot;
