import { useState, useMemo } from 'react';
import { useSearchParams, useNavigate } from 'react-router-dom';
import { useQueries } from '@tanstack/react-query';
import {
  LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend,
  ResponsiveContainer,
} from 'recharts';
import { ArrowLeft, ScanLine } from 'lucide-react';
import { backtestApi, runsApi, type BacktestTask, type DirectResult } from '../api/client';
import { Loading } from '../components/common/Loading';
import { fmt, fmtPct, fmtDate } from '../lib/utils';

// ── Color palette ─────────────────────────────────────────────────────────────

const CHART_COLORS = ['#f97316', '#22d3ee', '#4ade80'];
const CSS_COLORS = ['var(--orange)', 'var(--cyan)', 'var(--green)'];

// ── Data interfaces ───────────────────────────────────────────────────────────

interface NormalizedTrade {
  symbol: string;
  engine_id: string;
  entry_date: string;
  exit_date: string;
  entry_price: number | null;
  exit_price: number | null;
  pnl: number | null;
  exit_reason: string;
  shares: number | null;
  return_pct: number | null;
  side: string | null;
}

interface NormalizedMetrics {
  return_pct: number | null;
  max_dd_pct: number | null;
  sharpe: number | null;
  win_rate: number | null;
  trade_count: number | null;
  final_equity: number | null;
  annualized_return_pct: number | null;
  profit_factor: number | null;
  sortino_ratio: number | null;
  calmar_ratio: number | null;
  avg_holding_days: number | null;
  days_in_market_pct: number | null;
}

interface NormalizedResult {
  taskId: string;
  experimentName: string;
  mode: 'direct' | 'cli';
  period: string;
  capital: number;
  parking: string | null;
  metrics: NormalizedMetrics;
  equityCurve: { date: string; equity: number }[];
  trades: NormalizedTrade[];
}

// ── Normalization helpers ─────────────────────────────────────────────────────

function normalizeTrade(t: Record<string, unknown>, mode: 'direct' | 'cli'): NormalizedTrade {
  if (mode === 'direct') {
    return {
      symbol: String(t.symbol ?? ''),
      engine_id: String(t.engine_id ?? ''),
      entry_date: String(t.entry_date ?? ''),
      exit_date: String(t.exit_date ?? ''),
      entry_price: t.entry_price != null ? Number(t.entry_price) : null,
      exit_price: t.exit_price != null ? Number(t.exit_price) : null,
      pnl: t.pnl != null ? Number(t.pnl) : null,
      exit_reason: String(t.reason ?? t.exit_reason ?? ''),
      shares: t.shares != null ? Number(t.shares) : null,
      return_pct: null,
      side: null,
    };
  } else {
    return {
      symbol: String(t.symbol ?? ''),
      engine_id: String(t.engine_id ?? t.strategy ?? ''),
      entry_date: String(t.entry_date ?? t.open_date ?? ''),
      exit_date: String(t.exit_date ?? t.close_date ?? ''),
      entry_price: t.entry_price != null ? Number(t.entry_price) : null,
      exit_price: t.exit_price != null ? Number(t.exit_price) : null,
      pnl: t.net_pnl != null ? Number(t.net_pnl) : (t.pnl != null ? Number(t.pnl) : null),
      exit_reason: String(t.exit_reason ?? ''),
      shares: t.shares != null ? Number(t.shares) : null,
      return_pct: t.return_pct != null ? Number(t.return_pct) : (t.pct_return != null ? Number(t.pct_return) : null),
      side: String(t.side ?? t.direction ?? ''),
    };
  }
}

function getTaskPeriod(task: BacktestTask): string {
  if (task.start_date) {
    return task.end_date ? `${task.start_date} → ${task.end_date}` : task.start_date;
  }
  return task.year ?? '—';
}

function normalizeDirectResult(task: BacktestTask, result: DirectResult): NormalizedResult {
  const s = result.summary;
  const mb = result.metrics_bundle as Record<string, unknown>;
  return {
    taskId: task.task_id,
    experimentName: task.experiment_name,
    mode: 'direct',
    period: getTaskPeriod(task),
    capital: task.capital,
    parking: task.parking ?? null,
    metrics: {
      return_pct: s.return_pct ?? null,
      max_dd_pct: s.max_dd_pct ?? null,
      sharpe: s.sharpe ?? null,
      win_rate: s.win_rate ?? null,
      trade_count: s.trade_count ?? null,
      final_equity: s.final_equity ?? null,
      annualized_return_pct: mb?.annualized_return_pct != null ? Number(mb.annualized_return_pct) : null,
      profit_factor: mb?.profit_factor != null ? Number(mb.profit_factor) : null,
      sortino_ratio: mb?.sortino_ratio != null ? Number(mb.sortino_ratio) : null,
      calmar_ratio: mb?.calmar_ratio != null ? Number(mb.calmar_ratio) : null,
      avg_holding_days: mb?.avg_holding_days != null ? Number(mb.avg_holding_days) : null,
      days_in_market_pct: mb?.days_in_market_pct != null ? Number(mb.days_in_market_pct) : null,
    },
    equityCurve: result.equity_curve.map(p => ({ date: String(p.date), equity: Number(p.equity) })),
    trades: result.trades.map(t => normalizeTrade(t, 'direct')),
  };
}

function normalizeCLIResult(
  task: BacktestTask,
  metrics: Record<string, unknown>,
  equityCurveData: { data: Record<string, unknown>[] },
  tradesData: { trades: Record<string, unknown>[] },
): NormalizedResult {
  const m = metrics;
  const equityCurve = equityCurveData.data
    .map(row => ({
      date: String(row.date ?? row.Date ?? ''),
      equity: Number(row.equity ?? row.portfolio_value ?? row.Portfolio ?? 0),
    }))
    .filter(p => p.date);

  return {
    taskId: task.task_id,
    experimentName: task.experiment_name,
    mode: 'cli',
    period: getTaskPeriod(task),
    capital: task.capital,
    parking: task.parking ?? null,
    metrics: {
      return_pct: m.total_return_pct != null ? Number(m.total_return_pct) : null,
      max_dd_pct: m.max_drawdown_pct != null ? Number(m.max_drawdown_pct) : null,
      sharpe: m.sharpe_ratio != null ? Number(m.sharpe_ratio) : null,
      win_rate: m.win_rate != null ? Number(m.win_rate) : null,
      trade_count: m.trade_count != null ? Number(m.trade_count) : null,
      final_equity: m.final_equity != null ? Number(m.final_equity) : null,
      annualized_return_pct: m.annualized_return_pct != null ? Number(m.annualized_return_pct) : null,
      profit_factor: m.profit_factor != null ? Number(m.profit_factor) : null,
      sortino_ratio: m.sortino_ratio != null ? Number(m.sortino_ratio) : null,
      calmar_ratio: m.calmar_ratio != null ? Number(m.calmar_ratio) : null,
      avg_holding_days: m.avg_holding_days != null ? Number(m.avg_holding_days) : null,
      days_in_market_pct: m.days_in_market_pct != null ? Number(m.days_in_market_pct) : null,
    },
    equityCurve,
    trades: tradesData.trades.map(t => normalizeTrade(t, 'cli')),
  };
}

// ── Metrics Tab ───────────────────────────────────────────────────────────────

const METRIC_ROWS: {
  key: keyof NormalizedMetrics;
  label: string;
  format: (v: number | null) => string;
  higherIsBetter: boolean;
}[] = [
  { key: 'return_pct',            label: 'Total Return',       format: v => v != null ? `${v >= 0 ? '+' : ''}${v.toFixed(2)}%` : '—', higherIsBetter: true },
  { key: 'annualized_return_pct', label: 'Annual Return',      format: v => v != null ? `${v >= 0 ? '+' : ''}${v.toFixed(2)}%` : '—', higherIsBetter: true },
  { key: 'max_dd_pct',            label: 'Max Drawdown',       format: v => v != null ? `${v.toFixed(2)}%` : '—',                     higherIsBetter: false },
  { key: 'sharpe',                label: 'Sharpe Ratio',       format: v => fmt(v, 2),                                                 higherIsBetter: true },
  { key: 'sortino_ratio',         label: 'Sortino Ratio',      format: v => fmt(v, 2),                                                 higherIsBetter: true },
  { key: 'calmar_ratio',          label: 'Calmar Ratio',       format: v => fmt(v, 2),                                                 higherIsBetter: true },
  { key: 'win_rate',              label: 'Win Rate',           format: v => v != null ? `${(v <= 1 ? v * 100 : v).toFixed(1)}%` : '—', higherIsBetter: true },
  { key: 'profit_factor',         label: 'Profit Factor',      format: v => fmt(v, 2),                                                 higherIsBetter: true },
  { key: 'trade_count',           label: 'Trade Count',        format: v => v != null ? String(Math.round(v)) : '—',                  higherIsBetter: false },
  { key: 'avg_holding_days',      label: 'Avg Holding Days',   format: v => fmt(v, 1, 'd'),                                           higherIsBetter: false },
  { key: 'days_in_market_pct',    label: 'Days in Market',     format: v => fmtPct(v, 1),                                             higherIsBetter: false },
  { key: 'final_equity',          label: 'Final Equity',       format: v => v != null ? `$${v.toLocaleString(undefined, { maximumFractionDigits: 0 })}` : '—', higherIsBetter: true },
];

function MetricsTab({ results }: { results: NormalizedResult[] }) {
  const n = results.length;
  // Determine best value index per metric row
  function bestIdx(key: keyof NormalizedMetrics, higherIsBetter: boolean): number {
    const vals = results.map(r => r.metrics[key]);
    const numbers = vals.map((v, i) => ({ v: v as number | null, i })).filter(x => x.v != null);
    if (numbers.length < 2) return -1;
    if (higherIsBetter) {
      return numbers.reduce((a, b) => (b.v! > a.v! ? b : a)).i;
    } else {
      // For DD: closest to 0 (max = least negative) is best
      if (key === 'max_dd_pct') return numbers.reduce((a, b) => (b.v! > a.v! ? b : a)).i;
      // For count/duration: not highlighted
      return -1;
    }
  }

  const thStyle: React.CSSProperties = {
    padding: '10px 16px',
    fontFamily: 'var(--font-mono)', fontSize: 12, fontWeight: 500,
    letterSpacing: '0.07em', textTransform: 'uppercase', color: 'var(--text3)',
    textAlign: 'left', whiteSpace: 'nowrap',
  };
  const tdLabelStyle: React.CSSProperties = {
    padding: '10px 16px',
    fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text2)',
    whiteSpace: 'nowrap',
  };

  return (
    <div style={{ overflowX: 'auto' }}>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead>
          <tr style={{ borderBottom: '2px solid var(--border-md)', background: 'var(--bg2)' }}>
            <th style={thStyle}>Metric</th>
            {results.map((r, i) => (
              <th key={r.taskId} style={{ ...thStyle, color: CSS_COLORS[i] }}>
                <div style={{ fontWeight: 700, fontSize: 13 }}>{r.experimentName}</div>
                <div style={{ fontSize: 11, color: 'var(--text3)', fontWeight: 400, marginTop: 2 }}>
                  {r.period}
                  {r.parking && ` · 🅿 ${r.parking}`}
                </div>
              </th>
            ))}
          </tr>
        </thead>
        <tbody>
          {METRIC_ROWS.map((row, rowIdx) => {
            const best = bestIdx(row.key, row.higherIsBetter);
            const hasAnyValue = results.some(r => r.metrics[row.key] != null);
            if (!hasAnyValue) return null;
            return (
              <tr
                key={row.key}
                style={{ borderBottom: '1px solid var(--border)', background: rowIdx % 2 === 0 ? 'transparent' : 'rgba(255,255,255,0.015)' }}
              >
                <td style={tdLabelStyle}>{row.label}</td>
                {results.map((r, i) => {
                  const val = r.metrics[row.key] as number | null;
                  const isBest = i === best;
                  const isReturn = row.key === 'return_pct' || row.key === 'annualized_return_pct';
                  const isDD = row.key === 'max_dd_pct';
                  let color = 'var(--text1)';
                  if (isBest) color = 'var(--gold)';
                  else if (isReturn && val != null) color = val >= 0 ? 'var(--green)' : 'var(--red)';
                  else if (isDD && val != null) color = val < -15 ? 'var(--red)' : val < -10 ? 'var(--gold)' : 'var(--text1)';
                  return (
                    <td key={r.taskId} style={{
                      padding: '10px 16px',
                      fontFamily: 'var(--font-mono)', fontSize: 13,
                      color, fontWeight: isBest ? 700 : 400,
                    }}>
                      {row.format(val)}
                      {isBest && n > 1 && <span style={{ marginLeft: 5, fontSize: 10, opacity: 0.7 }}>▲</span>}
                    </td>
                  );
                })}
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

// ── Equity Curves Tab ─────────────────────────────────────────────────────────

function EquityCurvesTab({ results }: { results: NormalizedResult[] }) {
  const [normalized, setNormalized] = useState(false);

  const chartData = useMemo(() => {
    const allDates = Array.from(new Set(
      results.flatMap(r => r.equityCurve.map(p => p.date))
    )).sort();

    return allDates.map(date => {
      const row: Record<string, unknown> = { date };
      results.forEach((r, i) => {
        const point = r.equityCurve.find(p => p.date === date);
        if (normalized) {
          const firstEquity = r.equityCurve[0]?.equity ?? r.capital;
          row[`equity_${i}`] = point != null ? ((point.equity - firstEquity) / firstEquity * 100) : null;
        } else {
          row[`equity_${i}`] = point?.equity ?? null;
        }
      });
      return row;
    });
  }, [results, normalized]);

  const haveDifferentPeriods = useMemo(() => {
    const periods = results.map(r => r.period);
    return new Set(periods).size > 1;
  }, [results]);

  const haveDifferentCapitals = useMemo(() => {
    const capitals = results.map(r => r.capital);
    return new Set(capitals).size > 1;
  }, [results]);

  const yTickFormatter = (v: number) =>
    normalized ? `${v.toFixed(1)}%` : `$${(v / 1000).toFixed(0)}k`;

  return (
    <div>
      {/* Warning banners */}
      {haveDifferentPeriods && (
        <div style={{
          background: 'color-mix(in srgb, var(--gold) 10%, transparent)',
          border: '1px solid color-mix(in srgb, var(--gold) 25%, transparent)',
          borderRadius: 8, padding: '8px 14px', marginBottom: 14,
          fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--gold)',
        }}>
          ⚠ Different date ranges — curves may not cover the same period
        </div>
      )}

      {/* Controls */}
      <div style={{ display: 'flex', gap: 12, marginBottom: 16, alignItems: 'center' }}>
        <label style={{ display: 'flex', alignItems: 'center', gap: 6, fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text2)', cursor: 'pointer' }}>
          <input
            type="checkbox"
            checked={normalized}
            onChange={e => setNormalized(e.target.checked)}
            style={{ width: 13, height: 13 }}
          />
          Normalize to % return
        </label>
        {haveDifferentCapitals && !normalized && (
          <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text3)' }}>
            (different capitals — enable normalize for fair comparison)
          </span>
        )}
      </div>

      <ResponsiveContainer width="100%" height={380}>
        <LineChart data={chartData} margin={{ top: 5, right: 20, bottom: 20, left: 60 }}>
          <CartesianGrid strokeDasharray="3 3" stroke="rgba(255,255,255,0.06)" />
          <XAxis
            dataKey="date"
            tick={{ fontFamily: 'var(--font-mono)', fontSize: 11, fill: 'var(--text3)' }}
            tickLine={false}
            tickFormatter={v => {
              const d = new Date(v);
              return `${d.toLocaleString('en', { month: 'short' })} '${String(d.getFullYear()).slice(2)}`;
            }}
            interval="preserveStartEnd"
          />
          <YAxis
            tick={{ fontFamily: 'var(--font-mono)', fontSize: 11, fill: 'var(--text3)' }}
            tickLine={false}
            tickFormatter={yTickFormatter}
            width={60}
          />
          <Tooltip
            contentStyle={{ background: 'var(--bg2)', border: '1px solid var(--border-md)', borderRadius: 8, fontFamily: 'var(--font-mono)', fontSize: 12 }}
            labelStyle={{ color: 'var(--text3)', marginBottom: 4 }}
            formatter={(value: unknown, name: unknown) => {
              const nameStr = String(name ?? '');
              const idx = parseInt(nameStr.replace('equity_', ''));
              const label = results[idx]?.experimentName ?? nameStr;
              const formatted = normalized
                ? `${Number(value).toFixed(2)}%`
                : `$${Number(value).toLocaleString(undefined, { maximumFractionDigits: 0 })}`;
              return [formatted, label];
            }}
          />
          <Legend
            formatter={(value: string) => {
              const idx = parseInt(value.replace('equity_', ''));
              return results[idx]?.experimentName ?? value;
            }}
            wrapperStyle={{ fontFamily: 'var(--font-mono)', fontSize: 12 }}
          />
          {results.map((_, i) => (
            <Line
              key={i}
              type="monotone"
              dataKey={`equity_${i}`}
              stroke={CHART_COLORS[i]}
              dot={false}
              strokeWidth={2}
              connectNulls
            />
          ))}
        </LineChart>
      </ResponsiveContainer>
    </div>
  );
}

// ── Trade List Tab ────────────────────────────────────────────────────────────

type TradeFilter = 'all' | 'shared' | 'divergent';
type TradeSort = 'date' | 'symbol' | 'delta';

function TradeListTab({ results }: { results: NormalizedResult[] }) {
  const [filter, setFilter] = useState<TradeFilter>('all');
  const [sort, setSort] = useState<TradeSort>('date');
  const [page, setPage] = useState(0);
  const PAGE_SIZE = 50;

  // Group all trades by symbol + entry_date → one row per unique position
  const allRows = useMemo(() => {
    const map = new Map<string, (NormalizedTrade | null)[]>();
    results.forEach((r, i) => {
      r.trades.forEach(t => {
        const key = `${t.symbol}::${t.entry_date}`;
        if (!map.has(key)) map.set(key, Array(results.length).fill(null));
        map.get(key)![i] = t;
      });
    });
    return Array.from(map.values());
  }, [results]);

  const sharedCount = allRows.filter(r => r.every(t => t != null)).length;
  const divergentCount = allRows.filter(r => r.some(t => t != null) && !r.every(t => t != null)).length;

  const filteredRows = useMemo(() => {
    let rows = allRows;
    if (filter === 'shared') rows = allRows.filter(r => r.every(t => t != null));
    else if (filter === 'divergent') rows = allRows.filter(r => r.some(t => t != null) && !r.every(t => t != null));

    return [...rows].sort((a, b) => {
      if (sort === 'symbol') {
        const sa = a.find(t => t != null)?.symbol ?? '';
        const sb = b.find(t => t != null)?.symbol ?? '';
        return sa.localeCompare(sb);
      }
      if (sort === 'delta' && results.length >= 2) {
        // Sort by |Δ PnL| descending — biggest differences first
        const da = Math.abs((a[0]?.pnl ?? 0) - (a[1]?.pnl ?? 0));
        const db = Math.abs((b[0]?.pnl ?? 0) - (b[1]?.pnl ?? 0));
        return db - da;
      }
      // Default: date
      const dateA = a.find(t => t != null)?.entry_date ?? '';
      const dateB = b.find(t => t != null)?.entry_date ?? '';
      return dateA.localeCompare(dateB);
    });
  }, [allRows, filter, sort, results.length]);

  // PnL totals for visible rows (per backtest)
  const pnlTotals = results.map((_, i) =>
    filteredRows.reduce((s, row) => s + (row[i]?.pnl ?? 0), 0)
  );

  const totalPages = Math.ceil(filteredRows.length / PAGE_SIZE);
  const pageItems = filteredRows.slice(page * PAGE_SIZE, (page + 1) * PAGE_SIZE);

  const thStyle: React.CSSProperties = {
    padding: '10px 14px',
    fontFamily: 'var(--font-mono)', fontSize: 11, fontWeight: 500,
    letterSpacing: '0.07em', textTransform: 'uppercase', color: 'var(--text3)',
    textAlign: 'left', whiteSpace: 'nowrap',
  };

  // A compact per-backtest trade cell
  const renderCell = (t: NormalizedTrade | null, idx: number) => {
    if (!t) {
      return (
        <td key={idx} style={{ padding: '10px 14px', verticalAlign: 'top', borderLeft: '1px solid var(--border)' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
            <span style={{ fontFamily: 'var(--font-mono)', fontSize: 22, color: 'var(--border-md)', lineHeight: 1 }}>—</span>
            <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text3)', opacity: 0.5 }}>skipped</span>
          </div>
        </td>
      );
    }

    const win = t.pnl != null && t.pnl >= 0;
    return (
      <td key={idx} style={{
        padding: '10px 14px', verticalAlign: 'top',
        borderLeft: `3px solid ${CHART_COLORS[idx]}55`,
        background: `color-mix(in srgb, ${CHART_COLORS[idx]} 3%, transparent)`,
      }}>
        {/* Row 1: shares + PnL */}
        <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: 12, marginBottom: 4 }}>
          <span style={{ fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text1)', fontWeight: 600 }}>
            {t.shares != null ? `${Math.round(t.shares)} sh` : '—'}
          </span>
          <span style={{ fontFamily: 'var(--font-mono)', fontSize: 14, fontWeight: 700, color: win ? 'var(--green)' : 'var(--red)' }}>
            {t.pnl != null ? `${win ? '+' : ''}$${t.pnl.toFixed(0)}` : '—'}
          </span>
        </div>
        {/* Row 2: entry → exit prices */}
        {t.entry_price != null && (
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text3)', marginBottom: 3 }}>
            ${t.entry_price.toFixed(2)}
            {t.exit_price != null && <> → ${t.exit_price.toFixed(2)}</>}
            {t.return_pct != null && (
              <span style={{ marginLeft: 6, color: t.return_pct >= 0 ? 'var(--green)' : 'var(--red)' }}>
                ({t.return_pct >= 0 ? '+' : ''}{t.return_pct.toFixed(1)}%)
              </span>
            )}
          </div>
        )}
        {/* Row 3: exit date + reason */}
        <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
          <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text3)' }}>
            ↳ {fmtDate(t.exit_date)}
          </span>
          {t.exit_reason && (
            <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text3)', opacity: 0.6 }}>
              · {t.exit_reason}
            </span>
          )}
          {t.engine_id && (
            <span style={{ fontFamily: 'var(--font-mono)', fontSize: 10, color: CSS_COLORS[idx], opacity: 0.7 }}>
              [{t.engine_id}]
            </span>
          )}
        </div>
      </td>
    );
  };

  return (
    <div>
      {/* Controls bar */}
      <div style={{ display: 'flex', gap: 16, marginBottom: 16, alignItems: 'center', flexWrap: 'wrap' }}>
        {/* Filter chips */}
        <div style={{ display: 'flex', gap: 5, alignItems: 'center' }}>
          {([
            { key: 'all' as TradeFilter, label: `All`, count: allRows.length },
            { key: 'shared' as TradeFilter, label: 'Shared', count: sharedCount, title: 'All backtests took this trade' },
            { key: 'divergent' as TradeFilter, label: 'Divergent', count: divergentCount, title: 'Some backtests skipped this trade' },
          ]).map(({ key, label, count, title }) => (
            <button
              key={key}
              title={title}
              onClick={() => { setFilter(key); setPage(0); }}
              style={{
                padding: '4px 11px', fontSize: 12, borderRadius: 6, cursor: 'pointer',
                fontFamily: 'var(--font-mono)',
                background: filter === key ? 'color-mix(in srgb, var(--orange) 15%, transparent)' : 'var(--bg2)',
                border: filter === key ? '1px solid color-mix(in srgb, var(--orange) 30%, transparent)' : '1px solid var(--border)',
                color: filter === key ? 'var(--orange)' : 'var(--text3)',
              }}
            >
              {label} <span style={{ opacity: 0.6 }}>({count})</span>
            </button>
          ))}
        </div>

        {/* Sort */}
        <div style={{ display: 'flex', gap: 4, alignItems: 'center', marginLeft: 'auto' }}>
          <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text3)' }}>Sort:</span>
          {([
            { key: 'date' as TradeSort, label: 'Date' },
            { key: 'symbol' as TradeSort, label: 'Symbol' },
            ...(results.length >= 2 ? [{ key: 'delta' as TradeSort, label: '|Δ PnL|' }] : []),
          ]).map(({ key, label }) => (
            <button
              key={key}
              onClick={() => { setSort(key); setPage(0); }}
              style={{
                padding: '3px 9px', fontSize: 12, borderRadius: 5, cursor: 'pointer',
                fontFamily: 'var(--font-mono)',
                background: sort === key ? 'var(--bg2)' : 'none',
                border: sort === key ? '1px solid var(--border-md)' : '1px solid transparent',
                color: sort === key ? 'var(--text1)' : 'var(--text3)',
              }}
            >
              {label}
            </button>
          ))}
        </div>
      </div>

      {/* Table */}
      <div style={{ overflowX: 'auto' }}>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead>
            <tr style={{ borderBottom: '2px solid var(--border-md)', background: 'var(--bg2)' }}>
              <th style={thStyle}>Symbol</th>
              <th style={thStyle}>Entry</th>
              {results.map((r, i) => (
                <th key={r.taskId} style={{ ...thStyle, color: CSS_COLORS[i], minWidth: 200 }}>
                  <div>{r.experimentName.length > 24 ? r.experimentName.slice(0, 22) + '…' : r.experimentName}</div>
                  <div style={{ fontSize: 10, fontWeight: 400, color: 'var(--text3)', marginTop: 1 }}>
                    Shares · Prices · PnL · Exit
                  </div>
                </th>
              ))}
              {results.length === 2 && (
                <th style={{ ...thStyle, textAlign: 'right', minWidth: 80 }}>Δ PnL</th>
              )}
            </tr>
          </thead>
          <tbody>
            {pageItems.map((row, rowIdx) => {
              const anchor = row.find(t => t != null)!;
              const allTook = row.every(t => t != null);
              const noneTook = row.every(t => t == null);
              if (noneTook) return null;

              const delta = results.length === 2 && row[0] != null && row[1] != null
                ? (row[0].pnl ?? 0) - (row[1].pnl ?? 0) : null;

              // Row tint: divergent = subtle gold
              const rowBg = !allTook
                ? 'color-mix(in srgb, var(--gold) 4%, transparent)'
                : rowIdx % 2 === 0 ? 'transparent' : 'rgba(255,255,255,0.012)';

              return (
                <tr key={`${anchor.symbol}::${anchor.entry_date}`}
                  style={{ borderBottom: '1px solid var(--border)', background: rowBg }}
                >
                  {/* Symbol */}
                  <td style={{ padding: '10px 14px', verticalAlign: 'top' }}>
                    <div style={{ fontFamily: 'var(--font-mono)', fontSize: 14, fontWeight: 700, color: 'var(--text1)' }}>
                      {anchor.symbol}
                    </div>
                    {!allTook && (
                      <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--gold)', marginTop: 3 }}>
                        ⚡ divergent
                      </div>
                    )}
                  </td>
                  {/* Entry date */}
                  <td style={{ padding: '10px 14px', verticalAlign: 'top', fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)', whiteSpace: 'nowrap' }}>
                    {fmtDate(anchor.entry_date)}
                  </td>
                  {/* Per-backtest cells */}
                  {row.map((t, i) => renderCell(t, i))}
                  {/* Δ PnL */}
                  {results.length === 2 && (
                    <td style={{ padding: '10px 14px', verticalAlign: 'top', textAlign: 'right', fontFamily: 'var(--font-mono)' }}>
                      {delta != null ? (
                        <span style={{ fontSize: 14, fontWeight: 700, color: Math.abs(delta) < 10 ? 'var(--text3)' : delta > 0 ? 'var(--green)' : 'var(--red)' }}>
                          {delta >= 0 ? '+' : ''}${delta.toFixed(0)}
                        </span>
                      ) : (
                        // One side missing: show opportunity cost
                        <span style={{ fontSize: 12, color: 'var(--text3)', fontStyle: 'italic' }}>
                          {row[0] ? `+$${(row[0].pnl ?? 0).toFixed(0)} missed` : `-$${Math.abs(row[1]?.pnl ?? 0).toFixed(0)} avoided`}
                        </span>
                      )}
                    </td>
                  )}
                </tr>
              );
            })}
          </tbody>

          {/* Footer totals */}
          <tfoot>
            <tr style={{ borderTop: '2px solid var(--border-md)', background: 'var(--bg2)' }}>
              <td colSpan={2} style={{ padding: '10px 14px', fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)', fontWeight: 500 }}>
                TOTAL ({filteredRows.length})
              </td>
              {pnlTotals.map((total, i) => (
                <td key={i} style={{
                  padding: '10px 14px', fontFamily: 'var(--font-mono)', fontSize: 14, fontWeight: 700,
                  color: total >= 0 ? 'var(--green)' : 'var(--red)',
                  borderLeft: `3px solid ${CHART_COLORS[i]}55`,
                }}>
                  {total >= 0 ? '+' : ''}${total.toFixed(0)}
                </td>
              ))}
              {results.length === 2 && (
                <td style={{ padding: '10px 14px', textAlign: 'right', fontFamily: 'var(--font-mono)', fontSize: 14, fontWeight: 700 }}>
                  {(() => {
                    const d = pnlTotals[0] - pnlTotals[1];
                    return <span style={{ color: d >= 0 ? 'var(--green)' : 'var(--red)' }}>{d >= 0 ? '+' : ''}${d.toFixed(0)}</span>;
                  })()}
                </td>
              )}
            </tr>
          </tfoot>
        </table>
      </div>

      {/* Pagination */}
      {totalPages > 1 && (
        <div style={{ display: 'flex', gap: 6, marginTop: 14, alignItems: 'center', justifyContent: 'center' }}>
          <button disabled={page === 0} onClick={() => setPage(p => p - 1)}
            style={{ padding: '4px 12px', fontSize: 12, borderRadius: 6, cursor: page === 0 ? 'default' : 'pointer', background: 'var(--bg2)', border: '1px solid var(--border)', color: page === 0 ? 'var(--text3)' : 'var(--text1)', fontFamily: 'var(--font-mono)' }}>
            ← Prev
          </button>
          <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)' }}>{page + 1} / {totalPages}</span>
          <button disabled={page >= totalPages - 1} onClick={() => setPage(p => p + 1)}
            style={{ padding: '4px 12px', fontSize: 12, borderRadius: 6, cursor: page >= totalPages - 1 ? 'default' : 'pointer', background: 'var(--bg2)', border: '1px solid var(--border)', color: page >= totalPages - 1 ? 'var(--text3)' : 'var(--text1)', fontFamily: 'var(--font-mono)' }}>
            Next →
          </button>
        </div>
      )}
    </div>
  );
}

// ── Main Page ─────────────────────────────────────────────────────────────────

export function BacktestComparePage() {
  const [searchParams] = useSearchParams();
  const navigate = useNavigate();
  const [activeTab, setActiveTab] = useState<'metrics' | 'equity' | 'trades'>('metrics');

  // Parse task IDs from URL (up to 3)
  const taskIds = useMemo(
    () => (searchParams.get('tasks') ?? '').split(',').filter(Boolean).slice(0, 3),
    [searchParams]
  );

  // ── Phase 1: Fetch task metadata ──
  const taskQueries = useQueries({
    queries: taskIds.map(id => ({
      queryKey: ['backtest-task', id],
      queryFn: () => backtestApi.task(id),
      enabled: !!id,
    })),
  });
  const tasks = taskQueries.map(q => q.data ?? null);
  const tasksLoaded = taskQueries.every(q => !q.isLoading);
  const tasksError = taskQueries.some(q => q.isError);

  // ── Phase 2: Fetch results per task ──
  const directResultQueries = useQueries({
    queries: taskIds.map((id, i) => {
      const task = tasks[i];
      return {
        queryKey: ['direct-result', id],
        queryFn: () => backtestApi.directResult(id),
        enabled: tasksLoaded && task?.mode === 'direct' && !!task?.has_direct_result,
      };
    }),
  });

  const cliMetricsQueries = useQueries({
    queries: taskIds.map((_, i) => {
      const task = tasks[i];
      const runId = task?.run_id ?? '';
      return {
        queryKey: ['run-metrics', runId],
        queryFn: () => runsApi.metrics(runId),
        enabled: tasksLoaded && (task?.mode === 'cli' || !task?.mode) && !!runId,
      };
    }),
  });

  const cliEquityQueries = useQueries({
    queries: taskIds.map((_, i) => {
      const task = tasks[i];
      const runId = task?.run_id ?? '';
      return {
        queryKey: ['run-equity', runId],
        queryFn: () => runsApi.equityCurve(runId),
        enabled: tasksLoaded && (task?.mode === 'cli' || !task?.mode) && !!runId,
      };
    }),
  });

  const cliTradesQueries = useQueries({
    queries: taskIds.map((_, i) => {
      const task = tasks[i];
      const runId = task?.run_id ?? '';
      return {
        queryKey: ['run-trades-all', runId],
        queryFn: () => runsApi.tradeBlotter(runId, { limit: 2000, offset: 0 }),
        enabled: tasksLoaded && (task?.mode === 'cli' || !task?.mode) && !!runId,
      };
    }),
  });

  // ── Normalize results once all data is loaded ──
  const results = useMemo<NormalizedResult[]>(() => {
    const out: NormalizedResult[] = [];
    for (let i = 0; i < taskIds.length; i++) {
      const task = tasks[i];
      if (!task) continue;

      if (task.mode === 'direct') {
        const dr = directResultQueries[i].data;
        if (!dr) continue;
        out.push(normalizeDirectResult(task, dr));
      } else {
        const m = cliMetricsQueries[i].data;
        const ec = cliEquityQueries[i].data;
        const tr = cliTradesQueries[i].data;
        if (!m || !ec || !tr) continue;
        out.push(normalizeCLIResult(task, m, ec, tr));
      }
    }
    return out;
  }, [tasks, directResultQueries, cliMetricsQueries, cliEquityQueries, cliTradesQueries, taskIds]);

  const isLoading = !tasksLoaded ||
    results.length < taskIds.length;

  if (taskIds.length === 0) {
    return (
      <div style={{ padding: '36px 40px' }}>
        <div style={{ fontFamily: 'var(--font-mono)', fontSize: 14, color: 'var(--text3)', textAlign: 'center', marginTop: 60 }}>
          No tasks selected. Go back and select 2–3 completed backtests to compare.
        </div>
      </div>
    );
  }

  const TABS = [
    { key: 'metrics' as const, label: 'Metrics' },
    { key: 'equity' as const, label: 'Equity Curves' },
    { key: 'trades' as const, label: 'Trade List' },
  ];

  return (
    <div style={{ padding: '36px 40px' }} className="fade-up">
      <style>{`@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }`}</style>

      {/* Breadcrumb */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 20, fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)' }}>
        <button
          onClick={() => navigate('/backtest')}
          style={{ display: 'flex', alignItems: 'center', gap: 4, background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text3)', fontFamily: 'var(--font-mono)', fontSize: 12, padding: 0 }}
        >
          <ArrowLeft size={12} /> backtest
        </button>
        <span>/</span>
        <span style={{ color: 'var(--text2)' }}>compare</span>
      </div>

      {/* Header */}
      <div style={{ marginBottom: 28 }}>
        <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, letterSpacing: '0.10em', color: 'var(--text3)', textTransform: 'uppercase', marginBottom: 6 }}>
          {taskIds.length} backtests
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 12 }}>
          <ScanLine size={17} style={{ color: 'var(--orange)' }} />
          <h1 style={{ fontSize: 26, fontWeight: 700, color: 'var(--text1)', letterSpacing: '-0.02em' }}>
            Backtest Comparison
          </h1>
        </div>
        {/* Experiment badges */}
        {tasks.filter(Boolean).map((task, i) => (
          task && (
            <span
              key={task.task_id}
              style={{
                display: 'inline-flex', alignItems: 'center', gap: 5,
                fontFamily: 'var(--font-mono)', fontSize: 12,
                color: CSS_COLORS[i],
                background: `color-mix(in srgb, ${CSS_COLORS[i]} 12%, transparent)`,
                border: `1px solid color-mix(in srgb, ${CSS_COLORS[i]} 25%, transparent)`,
                borderRadius: 5, padding: '3px 10px', marginRight: 6,
              }}
            >
              <span style={{ width: 8, height: 8, borderRadius: '50%', background: CHART_COLORS[i], display: 'inline-block' }} />
              {task.experiment_name}
              <span style={{ color: 'var(--text3)', fontSize: 10 }}>{getTaskPeriod(task)}</span>
            </span>
          )
        ))}
      </div>

      {tasksError && (
        <div style={{ fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--red)', marginBottom: 16 }}>
          One or more tasks could not be loaded.
        </div>
      )}

      {isLoading ? (
        <div style={{ padding: 40 }}><Loading /></div>
      ) : results.length < 2 ? (
        <div style={{ fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text3)', padding: 40, textAlign: 'center' }}>
          Waiting for result data… (tasks may still be loading or have no results)
        </div>
      ) : (
        <div style={{ background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 14, overflow: 'hidden', boxShadow: '0 1px 3px rgba(0,0,0,0.04)' }}>
          {/* Tab bar */}
          <div style={{ display: 'flex', borderBottom: '1px solid var(--border)', background: 'var(--bg2)', padding: '0 20px' }}>
            {TABS.map(tab => (
              <button
                key={tab.key}
                onClick={() => setActiveTab(tab.key)}
                style={{
                  padding: '13px 18px',
                  fontFamily: 'var(--font-mono)', fontSize: 13, fontWeight: activeTab === tab.key ? 600 : 400,
                  background: 'none', border: 'none', cursor: 'pointer',
                  color: activeTab === tab.key ? 'var(--orange)' : 'var(--text3)',
                  borderBottom: activeTab === tab.key ? '2px solid var(--orange)' : '2px solid transparent',
                  transition: 'color 0.12s',
                  marginBottom: -1,
                }}
              >
                {tab.label}
              </button>
            ))}
          </div>

          {/* Tab content */}
          <div style={{ padding: '24px 28px' }}>
            {activeTab === 'metrics' && <MetricsTab results={results} />}
            {activeTab === 'equity' && <EquityCurvesTab results={results} />}
            {activeTab === 'trades' && <TradeListTab results={results} />}
          </div>
        </div>
      )}
    </div>
  );
}
