// Positions — the real-money ledger (ONC-1239). Open + closed tables,
// record-fill and close forms. Fills are human-entered, never assumed.
(function () {
  const fmtPx = v => v == null ? '—' : '$' + Number(v).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
  const fmtMoney = v => v == null ? '—' : '$' + Math.round(v).toLocaleString('en-US');
  const posNeg = v => v == null ? 'var(--ink-500)' : (v >= 0 ? 'var(--buy)' : 'var(--pass)');
  const MONO = 'var(--font-mono)';

  // Local calendar date, not UTC — toISOString() rolls over to tomorrow from
  // mid-afternoon Pacific onward, which is wrong for a date-entry default.
  const todayLocal = () => {
    const d = new Date();
    return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
  };

  const REASONS = [
    ['target_hit', 'Target hit'], ['stop_hit', 'Stop hit'],
    ['discretionary', 'Discretionary'], ['thesis_broken', 'Thesis broken'],
  ];
  const reasonLabel = v => (REASONS.find(r => r[0] === v) || [null, v || '—'])[1];

  const daysHeld = (entryDate, endDate) => {
    if (!entryDate) return null;
    const start = new Date(entryDate);
    const end = endDate ? new Date(endDate) : new Date();
    if (Number.isNaN(start.getTime()) || Number.isNaN(end.getTime())) return null;
    return Math.max(0, Math.round((end - start) / 86400000));
  };

  const realizedPct = p => (p.entry_price && p.exit_price != null)
    ? (p.exit_price / p.entry_price - 1) * 100 : null;
  const realizedPnl = p => (p.size_usd != null && realizedPct(p) != null)
    ? p.size_usd * (realizedPct(p) / 100) : null;

  const unrealizedPct = p => (p.entry_price && p.latest_price != null)
    ? (p.latest_price / p.entry_price - 1) * 100 : null;

  const ALERT_LABELS = { target_hit: 'TARGET', stop_hit: 'STOP', trailing_stop: 'TRAIL', avg_down: 'AVG DOWN' };
  const alertColor = t => t === 'target_hit' ? 'var(--buy)' : t === 'avg_down' ? 'var(--warn)' : 'var(--pass)';
  const alertDate = iso => {
    if (!iso) return '';
    const d = new Date(iso);
    if (Number.isNaN(d.getTime())) return '';
    return `${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
  };
  const THESIS_LABELS = { INTACT: 'INTACT', REVIEW: 'REVIEW', BROKEN: 'BROKEN', NO_CARD: 'NO CARD' };
  const THESIS_COLORS = {
    INTACT: 'var(--buy)', REVIEW: 'var(--warn)', BROKEN: 'var(--pass)', NO_CARD: 'var(--ink-500)',
  };
  function ThesisChip({ state }) {
    if (!state) return null;
    return (
      <span style={{
        fontSize: 9.5, fontWeight: 700, padding: '2px 7px', borderRadius: 20,
        color: 'white', background: THESIS_COLORS[state] || 'var(--ink-500)',
        whiteSpace: 'nowrap', marginLeft: 8, letterSpacing: '0.03em' }}>
        {THESIS_LABELS[state] || state}
      </span>
    );
  }

  function AlertBadges({ alerts }) {
    if (!alerts || !alerts.length) return null;
    return (
      <div style={{ display: 'flex', gap: 4, flexWrap: 'wrap', justifyContent: 'flex-end' }}>
        {alerts.map((a, i) => (
          <span key={i} style={{
            fontSize: 9.5, fontWeight: 700, padding: '2px 6px', borderRadius: 20,
            color: 'white', background: alertColor(a.trigger_type), whiteSpace: 'nowrap' }}>
            {(ALERT_LABELS[a.trigger_type] || a.trigger_type)} {alertDate(a.fired_at)}
          </span>
        ))}
      </div>
    );
  }

  function Card({ children, style }) {
    return <div className="card" style={{ padding: '16px 18px', marginBottom: 14, ...style }}>{children}</div>;
  }
  function CardTitle({ children, right }) {
    return (
      <div style={{ fontSize: 12.5, fontWeight: 600, color: 'var(--ink-800)',
        margin: '0 0 12px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <span>{children}</span>{right}
      </div>
    );
  }
  const th = (label, num) => (
    <th style={{
      textAlign: num ? 'right' : 'left', fontFamily: MONO, fontSize: 9, fontWeight: 600,
      letterSpacing: '0.1em', textTransform: 'uppercase', color: 'var(--ink-500)',
      padding: '7px 10px', borderBottom: '1px solid var(--ink-300)', whiteSpace: 'nowrap' }}>
      {label}</th>
  );
  const td = { padding: '7px 10px', borderBottom: '1px solid var(--ink-150)' };

  // ── Close-form modal ────────────────────────────────────────────────────
  function CloseModal({ position, onClose, onSubmit }) {
    const { useState } = React;
    const [exitPrice, setExitPrice] = useState('');
    const [exitDate, setExitDate] = useState(todayLocal);
    const [exitReason, setExitReason] = useState('discretionary');
    const [notes, setNotes] = useState('');
    const [busy, setBusy] = useState(false);
    const [err, setErr] = useState(null);

    const submit = async () => {
      if (!exitPrice || !exitDate) { setErr('Exit price and exit date are required.'); return; }
      setBusy(true); setErr(null);
      try {
        await onSubmit({
          exit_price: Number(exitPrice),
          exit_date: exitDate,
          exit_reason: exitReason,
          notes: notes || undefined,
        });
      } catch (e) { setErr(e.message || String(e)); }
      finally { setBusy(false); }
    };

    const label = { fontSize: 11, fontWeight: 600, color: 'var(--ink-600)', marginBottom: 4, display: 'block' };
    const input = { width: '100%', padding: '8px 10px', fontSize: 13, border: '1px solid var(--ink-200)',
      borderRadius: 7, outline: 'none', color: 'var(--ink-900)', fontFamily: 'inherit', boxSizing: 'border-box' };

    return (
      <div onClick={(e) => { if (e.target === e.currentTarget) onClose(); }} style={{
        position: 'fixed', inset: 0, zIndex: 60, background: 'rgba(10,20,40,0.45)',
        display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <div style={{ width: 420, maxWidth: '92vw', background: 'var(--paper)', borderRadius: 14,
          overflow: 'hidden', border: '1px solid var(--ink-150)', boxShadow: '0 24px 60px rgba(10,22,40,0.22)' }}>
          <div style={{ padding: '16px 20px', borderBottom: '1px solid var(--ink-150)',
            display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
            <div style={{ fontSize: 13, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.06em', color: 'var(--ink-900)' }}>
              Close {position.ticker || position.analyses?.ticker}
            </div>
            <button onClick={onClose} title="Close" style={{ width: 26, height: 26, borderRadius: 6,
              background: 'transparent', border: 'none', color: 'var(--ink-500)', cursor: 'pointer' }}>
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none">
                <path d="M6 6l12 12M18 6l-12 12" stroke="currentColor" strokeWidth="2" strokeLinecap="round"/>
              </svg>
            </button>
          </div>
          <div style={{ padding: '18px 20px', display: 'grid', gap: 14 }}>
            {err && <window.ErrorBanner error={{ message: err }}/>}
            <div>
              <label style={label}>Exit price</label>
              <input style={input} type="number" step="0.01" value={exitPrice}
                onChange={e => setExitPrice(e.target.value)} placeholder="0.00"/>
            </div>
            <div>
              <label style={label}>Exit date</label>
              <input style={input} type="date" value={exitDate} onChange={e => setExitDate(e.target.value)}/>
            </div>
            <div>
              <label style={label}>Reason</label>
              <select style={input} value={exitReason} onChange={e => setExitReason(e.target.value)}>
                {REASONS.map(([v, l]) => <option key={v} value={v}>{l}</option>)}
              </select>
            </div>
            <div>
              <label style={label}>Notes (optional)</label>
              <textarea style={{ ...input, minHeight: 60, resize: 'vertical' }} value={notes}
                onChange={e => setNotes(e.target.value)}/>
            </div>
          </div>
          <div style={{ padding: '14px 20px', borderTop: '1px solid var(--ink-150)',
            display: 'flex', justifyContent: 'flex-end', gap: 8 }}>
            <button onClick={onClose} disabled={busy} style={{
              padding: '8px 16px', fontSize: 12.5, background: 'var(--ink-100)', color: 'var(--ink-800)',
              border: '1px solid var(--ink-200)', borderRadius: 7, cursor: 'pointer', fontFamily: 'inherit' }}>
              Cancel</button>
            <button onClick={submit} disabled={busy} style={{
              padding: '8px 16px', fontSize: 12.5, fontWeight: 500, background: 'var(--onni-primary)',
              color: 'white', border: 'none', borderRadius: 7,
              cursor: busy ? 'wait' : 'pointer', opacity: busy ? 0.6 : 1, fontFamily: 'inherit' }}>
              {busy ? 'Closing…' : 'Close position'}</button>
          </div>
        </div>
      </div>
    );
  }

  // ── Open positions table ────────────────────────────────────────────────
  function OpenTable({ rows, onClose, goto }) {
    if (!rows.length) return <window.EmptyState title="No open positions" hint="Record a fill from an approved BUY on the Approvals page."/>;
    return (
      <Card>
        <CardTitle>Open</CardTitle>
        <div style={{ overflowX: 'auto' }}>
          <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12.5 }}>
            <thead><tr>
              {th('Ticker')}{th('Company')}{th('Entry date')}{th('Entry px', true)}
              {th('Size', true)}{th('Now', true)}{th('Unrealized', true)}
              {th('Target', true)}{th('Stop', true)}{th('Days', true)}{th('Alerts', true)}{th('')}
            </tr></thead>
            <tbody className="row-hover">
              {rows.map(p => {
                const upnl = p.unrealized_pnl_usd;
                const upct = unrealizedPct(p);
                return (
                <tr key={p.id}>
                  <td
                    style={{
                      ...td, fontFamily: MONO, fontWeight: 600,
                      cursor: p.analysis_id ? 'pointer' : 'default',
                    }}
                    onClick={() => p.analysis_id && goto && goto('analysis', { analysisId: p.analysis_id })}
                    title={p.analysis_id ? 'View analysis' : undefined}
                  >
                    {p.ticker || p.analyses?.ticker || '—'}
                    <ThesisChip state={p.thesis_state}/>
                  </td>
                  <td style={{ ...td, color: 'var(--ink-600)' }}>{p.analyses?.company_name || '—'}</td>
                  <td style={{ ...td, fontFamily: MONO, color: 'var(--ink-600)' }}>{p.entry_date}</td>
                  <td style={{ ...td, fontFamily: MONO, textAlign: 'right' }}>{fmtPx(p.entry_price)}</td>
                  <td style={{ ...td, fontFamily: MONO, textAlign: 'right' }}>{fmtMoney(p.size_usd)}</td>
                  <td style={{ ...td, fontFamily: MONO, textAlign: 'right' }}>{fmtPx(p.latest_price)}</td>
                  <td style={{ ...td, fontFamily: MONO, textAlign: 'right', fontWeight: 600, color: posNeg(upnl) }}>
                    {fmtMoney(upnl)}{upct != null && <span style={{ fontSize: 10.5, marginLeft: 4, fontWeight: 400 }}>({upct >= 0 ? '+' : ''}{upct.toFixed(1)}%)</span>}
                  </td>
                  <td style={{ ...td, fontFamily: MONO, textAlign: 'right', color: 'var(--ink-600)' }}>{fmtPx(p.target_price)}</td>
                  <td style={{ ...td, fontFamily: MONO, textAlign: 'right', color: 'var(--ink-600)' }}>{fmtPx(p.stop_price)}</td>
                  <td style={{ ...td, fontFamily: MONO, textAlign: 'right', color: 'var(--ink-500)' }}>{daysHeld(p.entry_date)}</td>
                  <td style={{ ...td, textAlign: 'right' }}><AlertBadges alerts={p.alerts}/></td>
                  <td style={{ ...td, textAlign: 'right' }}>
                    <button onClick={() => onClose(p)} style={{
                      padding: '5px 12px', fontSize: 11.5, background: 'var(--ink-100)', color: 'var(--ink-800)',
                      border: '1px solid var(--ink-200)', borderRadius: 7, cursor: 'pointer', fontFamily: 'inherit' }}>
                      Close</button>
                  </td>
                </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </Card>
    );
  }

  // ── Closed positions table ──────────────────────────────────────────────
  function ClosedTable({ rows }) {
    if (!rows.length) return null;
    return (
      <Card>
        <CardTitle>Closed</CardTitle>
        <div style={{ overflowX: 'auto' }}>
          <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12.5 }}>
            <thead><tr>
              {th('Ticker')}{th('Company')}{th('Entry → exit')}{th('Entry px', true)}
              {th('Exit px', true)}{th('Realized P&L', true)}{th('Days', true)}{th('Reason')}
            </tr></thead>
            <tbody className="row-hover">
              {rows.map(p => {
                const pnl = realizedPnl(p);
                const pct = realizedPct(p);
                return (
                  <tr key={p.id}>
                    <td style={{ ...td, fontFamily: MONO, fontWeight: 600 }}>{p.ticker || p.analyses?.ticker || '—'}</td>
                    <td style={{ ...td, color: 'var(--ink-600)' }}>{p.analyses?.company_name || '—'}</td>
                    <td style={{ ...td, fontFamily: MONO, color: 'var(--ink-600)' }}>{p.entry_date} → {p.exit_date}</td>
                    <td style={{ ...td, fontFamily: MONO, textAlign: 'right' }}>{fmtPx(p.entry_price)}</td>
                    <td style={{ ...td, fontFamily: MONO, textAlign: 'right' }}>{fmtPx(p.exit_price)}</td>
                    <td style={{ ...td, fontFamily: MONO, textAlign: 'right', fontWeight: 600, color: posNeg(pnl) }}>
                      {fmtMoney(pnl)}{pct != null && <span style={{ fontSize: 10.5, marginLeft: 4, fontWeight: 400 }}>({pct >= 0 ? '+' : ''}{pct.toFixed(1)}%)</span>}
                    </td>
                    <td style={{ ...td, fontFamily: MONO, textAlign: 'right', color: 'var(--ink-500)' }}>{daysHeld(p.entry_date, p.exit_date)}</td>
                    <td style={{ ...td }}>
                      <span style={{
                        fontSize: 10.5, fontWeight: 600, padding: '3px 8px', borderRadius: 20,
                        background: p.exit_reason === 'target_hit' ? 'var(--buy-soft)'
                          : p.exit_reason === 'stop_hit' ? 'var(--pass-soft)' : 'var(--ink-100)',
                        color: p.exit_reason === 'target_hit' ? 'var(--buy)'
                          : p.exit_reason === 'stop_hit' ? 'var(--pass)' : 'var(--ink-600)' }}>
                        {reasonLabel(p.exit_reason)}
                      </span>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </Card>
    );
  }

  window.Positions = function Positions({ goto, session }) {
    const [rows, setRows] = React.useState(null);
    const [closing, setClosing] = React.useState(null); // position being closed
    const [err, setErr] = React.useState(null);

    const load = React.useCallback(async () => {
      try {
        const res = await window.EQ_API.getPositions();
        setRows(res.data || []);
      } catch (e) { setErr(String(e.message || e)); }
    }, []);
    React.useEffect(() => { load(); }, [load]);

    const open = (rows || []).filter(r => r.status === 'open');
    const closed = (rows || []).filter(r => r.status === 'closed')
      .sort((a, b) => (b.exit_date || '').localeCompare(a.exit_date || ''));

    const submitClose = async (form) => {
      await window.EQ_API.closePosition(closing.id, form);
      setClosing(null); load();
    };

    const exposure = open.reduce((s, p) => s + (p.size_usd || 0), 0);
    const closedPnl = closed.reduce((s, p) => s + (realizedPnl(p) || 0), 0);
    const loading = rows === null && !err;

    return (
      <div>
        <window.TopBar
          title="Positions"
          subtitle={loading ? 'Loading…' : `${open.length} open · ${closed.length} closed`}
        />
        <div style={{ padding: '24px 32px' }}>
          {err && <window.ErrorBanner error={{ message: err }} onRetry={load}/>}
          {loading && <div style={{ color: 'var(--ink-500)', fontSize: 12.5 }}>Loading…</div>}
          {!loading && (
            <>
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(190px, 1fr))', gap: 10, marginBottom: 14 }}>
                <window.StatCard label="Open positions" value={String(open.length)}/>
                <window.StatCard label="Open exposure" value={fmtMoney(exposure)}/>
                <window.StatCard label="Closed positions" value={String(closed.length)}/>
                <window.StatCard label="Realized P&L" value={fmtMoney(closedPnl)} accent={closedPnl >= 0 ? 'var(--buy)' : 'var(--pass)'}/>
              </div>
              <OpenTable rows={open} onClose={setClosing} goto={goto}/>
              <ClosedTable rows={closed}/>
            </>
          )}
        </div>
        {closing && (
          <CloseModal position={closing} onClose={() => setClosing(null)} onSubmit={submitClose}/>
        )}
      </div>
    );
  };

  // ── Rerun landing (ONC-1241) ────────────────────────────────────────────
  // Reached via the `/rerun?analysisId=&token=` one-click link in a REVIEW
  // thesis digest email. Fires the token-authenticated rerun exactly once on
  // mount, then shows queued/error.
  window.RerunLanding = function RerunLanding({ analysisId, token, goto }) {
    const [state, setState] = React.useState({ status: 'busy' }); // busy | ok | error
    const fired = React.useRef(false);

    React.useEffect(() => {
      if (fired.current) return;
      fired.current = true;
      if (!analysisId || !token) {
        setState({ status: 'error', message: 'Missing analysisId or token in rerun link.' });
        return;
      }
      window.EQ_API.rerunAnalysis(analysisId, token)
        .then(res => setState({ status: 'ok', id: res.id }))
        .catch(e => setState({ status: 'error', message: e.message || String(e) }));
    }, [analysisId, token]);

    return (
      <div style={{ padding: '24px 32px', maxWidth: 480 }}>
        <window.TopBar title="Re-run analysis" subtitle="Thesis-review one-click rerun"/>
        <div className="card" style={{ padding: '20px 22px', marginTop: 16 }}>
          {state.status === 'busy' && (
            <div style={{ color: 'var(--ink-600)', fontSize: 13 }}>Queuing re-analysis…</div>
          )}
          {state.status === 'ok' && (
            <>
              <div style={{ color: 'var(--buy)', fontWeight: 600, fontSize: 13.5, marginBottom: 14 }}>
                ✓ Re-analysis queued — ID {state.id}
              </div>
              <button
                onClick={() => goto && goto('analyses')}
                style={{
                  padding: '8px 16px', fontSize: 12.5, fontWeight: 500, background: 'var(--onni-primary)',
                  color: 'white', border: 'none', borderRadius: 7, cursor: 'pointer', fontFamily: 'inherit',
                }}
              >
                View analyses
              </button>
            </>
          )}
          {state.status === 'error' && (
            <window.ErrorBanner error={{ message: state.message }}/>
          )}
        </div>
      </div>
    );
  };
})();
