// Strategy detail — drill-down view with header, action row, schedule + rules
// summary, configuration card, and tabbed history (screen runs / recent
// analyses / errors).

window.StrategyDetail = function StrategyDetail({ strategyId, onBack, onEdited, onDeleted }) {
  const { useState, useEffect, useRef } = React;
  const [editOpen, setEditOpen] = useState(false);
  const [runOpen, setRunOpen] = useState(false);
  const [preview, setPreview] = useState(null); // {loading} | {result} | {error}
  const [tab, setTab] = useState('history'); // 'history' | 'analyses' | 'errors'
  const [actionBusy, setActionBusy] = useState(null);
  const [actionError, setActionError] = useState(null);

  const detail = window.useApi(() => window.EQ_API.getStrategy(strategyId), [strategyId]);
  const history = window.useApi(() => window.EQ_API.getStrategyScreenHistory(strategyId, 20), [strategyId]);
  const analyses = window.useApi(() => window.EQ_API.getStrategyRecentAnalyses(strategyId, 10), [strategyId]);
  const errors = window.useApi(() => window.EQ_API.getStrategyErrors(strategyId), [strategyId]);
  const active = window.useApi(() => window.EQ_API.getStrategyActiveAnalyses(strategyId), [strategyId]);

  const s = detail.data;
  const activeCount = active.data?.active ?? 0;

  const reloadAll = () => { detail.reload(); history.reload(); analyses.reload(); errors.reload(); active.reload(); };

  // Run-now schedules a deferred refresh (~5s, to let the screen queue rows).
  // Hold the timer id so we can cancel it if the user leaves the detail view
  // before it fires — otherwise it calls reloadAll() on an unmounted component.
  const reloadTimerRef = useRef(null);
  useEffect(() => () => { if (reloadTimerRef.current) clearTimeout(reloadTimerRef.current); }, []);

  const cancelAll = async () => {
    if (!activeCount) return;
    if (!window.confirm(`Cancel all ${activeCount} running/queued analyses for "${s.name}"? Running pipelines stop at their next checkpoint.`)) return;
    setActionBusy('cancel'); setActionError(null);
    try {
      await window.EQ_API.cancelStrategyAnalyses(strategyId);
      reloadAll();
    } catch (e) { setActionError(e.message || 'Cancel all failed'); }
    finally { setActionBusy(null); }
  };

  const runPreview = async () => {
    setPreview({ loading: true });
    try {
      const result = await window.EQ_API.previewStrategy(strategyId);
      setPreview({ loading: false, result });
    } catch (e) {
      setPreview({ loading: false, error: e.message });
    }
  };

  const toggleActive = async () => {
    setActionBusy('toggle'); setActionError(null);
    try {
      await window.EQ_API.updateStrategy(strategyId, { is_active: !s.is_active });
      reloadAll();
    } catch (e) { setActionError(e.message || 'Toggle failed'); }
    finally { setActionBusy(null); }
  };

  const onDelete = async () => {
    if (!window.confirm(`Delete strategy "${s.name}"? This soft-deletes (sets is_active=false). Existing analyses remain.`)) return;
    setActionBusy('delete'); setActionError(null);
    try {
      await window.EQ_API.deleteStrategy(strategyId);
      onDeleted();
    } catch (e) { setActionError(e.message || 'Delete failed'); setActionBusy(null); }
  };

  if (detail.loading || !s) {
    return (
      <div>
        <window.TopBar title="Strategy" right={<button onClick={onBack} style={linkBtn}>← All strategies</button>}/>
        <div style={{ padding: 32, color: 'var(--ink-500)', fontSize: 12.5 }}>Loading…</div>
      </div>
    );
  }
  if (detail.error) {
    return (
      <div>
        <window.TopBar title="Strategy" right={<button onClick={onBack} style={linkBtn}>← All strategies</button>}/>
        <div style={{ padding: 32 }}><window.ErrorBanner error={detail.error} onRetry={detail.reload}/></div>
      </div>
    );
  }

  return (
    <div className="page-fade">
      <window.TopBar
        title={s.name}
        subtitle={`${s.mode === 'watchlist' ? 'Watchlist' : 'Filter'} strategy · schedules at ${_cronToHuman(s.schedule_cron)} PT`}
        right={
          <>
            <button onClick={onBack} style={linkBtn}>← All strategies</button>
            <button onClick={() => setEditOpen(true)} style={btnGhost}>
              <Icon path="M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7m-1.5-9.5a2.121 2.121 0 113 3L12 19l-4 1 1-4 9.5-9.5z"/>
              Edit
            </button>
            <button onClick={toggleActive} disabled={actionBusy === 'toggle'} style={btnGhost}>
              {s.is_active
                ? <><Icon path="M10 9v6m4-6v6m-7 3h10a2 2 0 002-2V8a2 2 0 00-2-2H7a2 2 0 00-2 2v8a2 2 0 002 2z"/> Deactivate</>
                : <><Icon path="M5 3l14 9-14 9V3z" fill/> Activate</>}
            </button>
            {activeCount > 0 && (
              <button onClick={cancelAll} disabled={actionBusy === 'cancel'} title="Cancel this strategy's running and queued analyses" style={{
                ...btnGhost, color: 'var(--pass)', borderColor: 'var(--pass-soft)',
              }}>
                <Icon path="M6 18L18 6M6 6l12 12"/>
                {actionBusy === 'cancel' ? 'Cancelling…' : `Cancel all (${activeCount})`}
              </button>
            )}
            <button onClick={runPreview} disabled={preview?.loading} title="Dry-run the screen — shows matched tickers and the elimination funnel without queueing any analyses (no cost)" style={btnGhost}>
              <Icon path="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z M12 9a3 3 0 100 6 3 3 0 000-6z"/>
              {preview?.loading ? 'Previewing…' : 'Preview (dry run)'}
            </button>
            <button onClick={() => setRunOpen(true)} disabled={!s.is_active} style={{ ...btnPrimary, opacity: s.is_active ? 1 : 0.4, cursor: s.is_active ? 'pointer' : 'not-allowed' }}>
              <Icon path="M5 3l14 9-14 9V3z" fill/>
              Run now
            </button>
          </>
        }
      />

      <div style={{ padding: '24px 32px', display: 'flex', flexDirection: 'column', gap: 16 }}>
        {actionError && <window.ErrorBanner error={{ message: actionError }}/>}

        {/* Status row */}
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <div style={{ display: 'flex', gap: 6 }}>
            <span className={`badge ${s.is_active ? 'badge-buy' : 'badge-neutral'}`}><span className="dot"/>{s.is_active ? 'ACTIVE' : 'INACTIVE'}</span>
            <span className={`badge ${s.mode === 'watchlist' ? 'badge-warn' : 'badge-neutral'}`}>{(s.mode || 'filter').toUpperCase()}</span>
            {activeCount > 0 && (
              <span className="badge badge-neutral" title={`${active.data?.running ?? 0} running · ${active.data?.queued ?? 0} queued`}>{activeCount} IN FLIGHT</span>
            )}
          </div>
          <div style={{ fontSize: 12, color: 'var(--ink-500)' }}>Created {window.formatDate(s.created_at)}</div>
        </div>

        {/* Schedule + Re-run rules + Last 30 days */}
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 16 }}>
          <ChartCard title="Schedule">
            <KV label="Cadence" value={_cronToHuman(s.schedule_cron) + ' PT'}/>
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--ink-500)', marginTop: 4 }}>{s.schedule_cron}</div>
            <div style={{ fontSize: 11.5, color: 'var(--ink-500)', marginTop: 8 }}>
              Next: <b style={{ color: 'var(--ink-800)' }}>{s.next_fire_at ? new Date(s.next_fire_at).toLocaleString('en-US', { weekday: 'short', month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit', timeZone: 'America/Vancouver' }) + ' PT' : '—'}</b>
            </div>
          </ChartCard>
          <ChartCard title="Re-run rules">
            <div style={{ display: 'flex', gap: 24 }}>
              <KV label="Price Move" value={`≥${(s.rerun_price_pct * 100).toFixed(0)}%`}/>
              <KV label="Time Elapsed" value={`${s.rerun_days}d`}/>
              <KV label="Max / Screen" value={s.max_analyses_per_screen ?? '—'}/>
            </div>
            <div style={{ fontSize: 11.5, color: 'var(--ink-500)', marginTop: 8 }}>Plus: always re-run on first appearance.</div>
          </ChartCard>
          <ChartCard title="Last 30 days">
            <div style={{ display: 'flex', gap: 20 }}>
              <KV label="Screens" value={history.data?.data?.length ?? '—'}/>
              <KV label="Analyses" value={analyses.data?.data?.length ?? '—'}/>
              <KV label="BUYs" value={(analyses.data?.data || []).filter(a => a.decision === 'BUY').length} color="var(--buy)"/>
            </div>
          </ChartCard>
        </div>

        {/* Configuration */}
        <ChartCard title={`Configuration · ${s.mode === 'watchlist' ? 'Watchlist mode' : 'Filter mode'}`}>
          {s.mode === 'watchlist' ? (
            <div>
              <div style={{ fontSize: 11.5, color: 'var(--ink-500)', marginBottom: 8 }}>{(s.ticker_list || []).length} tickers</div>
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
                {(s.ticker_list || []).map(t => (
                  <span key={t} style={{
                    padding: '4px 10px', fontSize: 12, fontFamily: 'var(--font-mono)', fontWeight: 600,
                    background: 'var(--ink-100)', color: 'var(--ink-800)', borderRadius: 7,
                  }}>{t}</span>
                ))}
              </div>
            </div>
          ) : (
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 16 }}>
              <KV label="Min Market Cap" value={s.fmp_filters?.marketCapMoreThan ? `$${(s.fmp_filters.marketCapMoreThan / 1e9).toFixed(1)}B` : '—'}/>
              <KV label="% off 6-mo High" value={s.custom_filters?.pct_of_6mo_high_max != null ? `≥${((1 - s.custom_filters.pct_of_6mo_high_max) * 100).toFixed(0)}%` : '—'}/>
              <KV label="5-day Z-Score" value={s.custom_filters?.z_score_5d_max != null ? `≤ ${s.custom_filters.z_score_5d_max}` : '—'}/>
            </div>
          )}
        </ChartCard>

        {/* Tabbed history */}
        <section>
          <div style={{ display: 'flex', gap: 4, borderBottom: '1px solid var(--ink-150)', marginBottom: 12 }}>
            {[
              ['history', 'Screen history', history.data?.data?.length ?? 0],
              ['analyses', 'Recent analyses', analyses.data?.data?.length ?? 0],
              ['errors', 'Errors', errors.data?.data?.length ?? 0],
            ].map(([id, label, count]) => (
              <button key={id} onClick={() => setTab(id)} style={{
                padding: '8px 12px', fontSize: 12.5, fontWeight: 500,
                background: 'transparent',
                color: tab === id ? 'var(--ink-900)' : 'var(--ink-500)',
                border: 'none', borderBottom: '2px solid ' + (tab === id ? 'var(--onni-primary)' : 'transparent'),
                cursor: 'pointer', fontFamily: 'inherit', marginBottom: -1,
              }}>
                {label} <span style={{ fontFamily: 'var(--font-mono)', fontSize: 10.5, color: 'var(--ink-400)', marginLeft: 4 }}>{count}</span>
              </button>
            ))}
          </div>

          {tab === 'history' && <ScreenHistoryTable rows={history.data?.data || []} loading={history.loading}/>}
          {tab === 'analyses' && <RecentAnalysesTable rows={analyses.data?.data || []} loading={analyses.loading}/>}
          {tab === 'errors' && <ErrorsTable rows={errors.data?.data || []} loading={errors.loading}/>}
        </section>

        {/* Delete (least-emphasized) */}
        <div style={{ display: 'flex', justifyContent: 'flex-end', paddingTop: 12 }}>
          <button onClick={onDelete} disabled={actionBusy === 'delete'} style={{
            padding: '6px 12px', fontSize: 12, color: 'var(--pass)', background: 'transparent',
            border: '1px solid var(--pass-soft)', borderRadius: 7, cursor: 'pointer', fontFamily: 'inherit',
          }}>{actionBusy === 'delete' ? 'Deleting…' : 'Delete strategy'}</button>
        </div>
      </div>

      {editOpen && <window.StrategyEditModal existing={s} onClose={() => setEditOpen(false)}
                     onSaved={(saved) => { setEditOpen(false); detail.reload(); onEdited && onEdited(saved); }}/>}
      {runOpen && <window.RunNowModal strategy={s} onClose={() => setRunOpen(false)}
                    onFired={(result) => { setRunOpen(false); reloadTimerRef.current = setTimeout(reloadAll, 5000); }}/>}
      {preview && (
        <window.StrategyPreviewModal
          result={preview.result} loading={preview.loading} error={preview.error}
          onClose={() => setPreview(null)} />
      )}
    </div>
  );
};

// ---- Helpers ------------------------------------------------------------
function ChartCard({ title, children }) {
  return (
    <div style={{ background: 'var(--paper)', border: '1px solid var(--ink-150)', borderRadius: 12, padding: '16px 20px' }}>
      <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--ink-500)', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: 14 }}>{title}</div>
      {children}
    </div>
  );
}

function KV({ label, value, color }) {
  return (
    <div>
      <div style={{ fontSize: 10, color: 'var(--ink-600)', textTransform: 'uppercase', letterSpacing: '0.08em', fontWeight: 700, marginBottom: 5 }}>{label}</div>
      <div style={{ fontSize: 18, fontWeight: 700, color: color || 'var(--ink-900)', letterSpacing: '-0.02em', fontFamily: 'var(--font-mono)' }}>{value ?? '—'}</div>
    </div>
  );
}

function Icon({ path, fill }) {
  return (
    <svg width="12" height="12" viewBox="0 0 24 24" fill="none" style={{ marginRight: 6, opacity: 0.8 }}>
      <path d={path} stroke={fill ? 'none' : 'currentColor'} fill={fill ? 'currentColor' : 'none'} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
    </svg>
  );
}

function ScreenHistoryTable({ rows, loading }) {
  if (loading) return <div style={{ padding: 16, color: 'var(--ink-500)', fontSize: 12.5 }}>Loading…</div>;
  if (!rows.length) return <window.EmptyState title="No screens yet" hint="Click Run now to fire one."/>;
  return (
    <Table headers={['Run At', 'Universe', 'Hits', 'Duration']} rows={rows.map(r => [
      <Mono key={1}>{new Date(r.ran_at).toLocaleString('en-US', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' })}</Mono>,
      <Mono key={2}>{r.universe_count?.toLocaleString() ?? '—'}</Mono>,
      <b key={3}>{r.hits_count ?? '—'}</b>,
      <Mono key={4}>{r.duration_seconds ? r.duration_seconds + 's' : '—'}</Mono>,
    ])}/>
  );
}

function RecentAnalysesTable({ rows, loading }) {
  if (loading) return <div style={{ padding: 16, color: 'var(--ink-500)', fontSize: 12.5 }}>Loading…</div>;
  if (!rows.length) return <window.EmptyState title="No analyses yet" hint="Triggered by this strategy will appear here."/>;
  return (
    <Table headers={['Ticker', 'Date', 'Trigger', 'Decision']} rows={rows.map(r => [
      <><span style={{ fontFamily: 'var(--font-mono)', fontWeight: 600, color: 'var(--ink-900)' }}>{r.ticker}</span><span style={{ color: 'var(--ink-500)', marginLeft: 6 }}>{r.company_name}</span></>,
      <Mono key={2}>{window.formatDate(r.completed_at || r.created_at)}</Mono>,
      <span key={3} style={{ fontFamily: 'var(--font-mono)', fontSize: 10.5, color: 'var(--ink-500)' }}>{r.triggered_by || '—'}</span>,
      <window.DecisionOrStatus key={4} decision={r.decision} status={r.status}/>,
    ])}/>
  );
}

function ErrorsTable({ rows, loading }) {
  if (loading) return <div style={{ padding: 16, color: 'var(--ink-500)', fontSize: 12.5 }}>Loading…</div>;
  if (!rows.length) return <window.EmptyState title="No errors in last 14d" hint="Failures triggered by this strategy will appear here."/>;
  return (
    <Table headers={['Ticker', 'Date', 'Error']} rows={rows.map(r => [
      <Mono key={1} style={{ fontWeight: 600 }}>{r.ticker}</Mono>,
      <Mono key={2}>{window.formatDate(r.completed_at || r.created_at)}</Mono>,
      <span key={3} style={{ color: 'var(--pass)' }}>{r.error_message || 'Unknown error'}</span>,
    ])}/>
  );
}

function Table({ headers, rows }) {
  return (
    <div style={{ background: 'var(--paper)', border: '1px solid var(--ink-150)', borderRadius: 12, overflow: 'hidden' }}>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr>{headers.map((h, i) => <th key={i} style={{
          padding: '10px 14px', fontSize: 10.5, color: 'var(--ink-500)',
          textTransform: 'uppercase', letterSpacing: '0.06em', fontWeight: 500,
          textAlign: 'left', borderBottom: '1px solid var(--ink-200)', background: 'var(--ink-50)',
        }}>{h}</th>)}</tr></thead>
        <tbody className="row-hover">
          {rows.map((cells, i) => (
            <tr key={i}>{cells.map((c, j) => <td key={j} style={{
              padding: '10px 14px', fontSize: 12.5, color: 'var(--ink-800)',
              borderBottom: i < rows.length - 1 ? '1px solid var(--ink-100)' : 'none',
            }}>{c}</td>)}</tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function Mono({ children, ...rest }) {
  return <span {...rest} style={{ fontFamily: 'var(--font-mono)', color: 'var(--ink-700)', ...rest.style }}>{children}</span>;
}

function _cronToHuman(cron) {
  if (!cron) return '—';
  const p = cron.split(/\s+/);
  if (p.length !== 5) return cron;
  const [mn, hr, dom, , dow] = p;
  const h = Number(hr), m = Number(mn);
  const time = `${((h + 11) % 12 + 1)}:${m.toString().padStart(2, '0')} ${h < 12 ? 'AM' : 'PM'}`;
  if (dom === '*' && dow === '*') return `daily at ${time}`;
  if (dom === '*' && dow === '1-5') return `weekdays at ${time}`;
  if (dom === '*' && /^[0-6]$/.test(dow)) return `${['Sun','Mon','Tue','Wed','Thu','Fri','Sat'][Number(dow)]}s at ${time}`;
  if (dow === '*' && /^\d+$/.test(dom)) return `${dom}${_ordSuffix(Number(dom))} of month at ${time}`;
  return cron;
}

function _ordSuffix(n) { return (n%10===1&&n%100!==11)?'st':(n%10===2&&n%100!==12)?'nd':(n%10===3&&n%100!==13)?'rd':'th'; }

const linkBtn = { background: 'transparent', border: 'none', color: 'var(--ink-600)', fontSize: 12, cursor: 'pointer', fontFamily: 'inherit' };
const btnPrimary = {
  padding: '8px 14px', fontSize: 12.5, fontWeight: 500,
  background: 'var(--ink-900)', color: 'white',
  border: 'none', borderRadius: 7, cursor: 'pointer',
  fontFamily: 'inherit',
  display: 'inline-flex', alignItems: 'center', gap: 0,
};
const btnGhost = {
  padding: '6px 10px', fontSize: 12,
  background: 'transparent', color: 'var(--ink-700)',
  border: '1px solid var(--ink-200)', borderRadius: 7, cursor: 'pointer',
  fontFamily: 'inherit',
  display: 'inline-flex', alignItems: 'center', gap: 0,
};
