import { useState, useEffect, useRef, Fragment } from 'react'
import { BookOpen, TrendingUp, TrendingDown, Activity, AlertTriangle, RefreshCw, Zap, CheckCircle, XCircle, Brain, Trash2, Search, X, ChevronDown, ChevronUp, Terminal, Lock, ShieldAlert, PieChart, Target } from 'lucide-react'
import { TradeIdeasTab, CATEGORIES } from '../components/TradeIdeas'
import clsx from 'clsx'
import { useJournalSummary, useMacroHistory, useGeoHistory, useTradeMtm, useClosedTrades, useCloseTrade, useUpdateExitParams, useExitDefaults, useCycleHistory, useCycleStatus, useTriggerCycle, useTradePostmortem, useAnalyzePostmortem, useIvForTrade, useKellySizing, useSimPortfolioRisk, useSkippedTrades, useDeleteTrade, api } from '../hooks/useApi'
import { ASSET_CLASS_COLORS } from '../constants/assetColors'
import { useQueryClient } from '@tanstack/react-query'
import { format } from 'date-fns'
import { fr } from 'date-fns/locale'

const SCENARIO_META: Record<string, { label: string; color: string; emoji: string }> = {
  goldilocks:      { label: 'Goldilocks',      color: '#22c55e', emoji: '🌟' },
  desinflation:    { label: 'Disinflation',     color: '#06b6d4', emoji: '❄️' },
  soft_landing:    { label: 'Soft Landing',    color: '#3b82f6', emoji: '🛬' },
  reflation:       { label: 'Reflation',       color: '#f97316', emoji: '🔥' },
  stagflation:     { label: 'Stagflation',     color: '#eab308', emoji: '⚡' },
  inflation_shock: { label: 'Inflation Shock', color: '#ef4444', emoji: '💥' },
  recession:       { label: 'Recession',        color: '#8b5cf6', emoji: '📉' },
  crise_liquidite: { label: 'Liquidity Crisis', color: '#ec4899', emoji: '🚨' },
  incertain:       { label: 'Uncertain',        color: '#64748b', emoji: '❓' },
}

function ScenarioBadge({ dominant, size = 'sm' }: { dominant: string; size?: 'sm' | 'lg' }) {
  const m = SCENARIO_META[dominant] ?? SCENARIO_META.incertain
  return (
    <span
      className={clsx('inline-flex items-center gap-1 rounded font-semibold',
        size === 'lg' ? 'px-2.5 py-1 text-sm' : 'px-1.5 py-0.5 text-[11px]')}
      style={{ background: `${m.color}22`, color: m.color, border: `1px solid ${m.color}44` }}
    >
      {m.emoji} {m.label}
    </span>
  )
}

function PnlBadge({ pnl }: { pnl: number | null | undefined }) {
  if (pnl == null) return <span className="text-slate-600 text-xs">—</span>
  const pos = pnl >= 0
  return (
    <span className={clsx('inline-flex items-center gap-0.5 text-xs font-bold font-mono',
      pos ? 'text-emerald-400' : 'text-red-400')}>
      {pos ? <TrendingUp className="w-3 h-3" /> : <TrendingDown className="w-3 h-3" />}
      {pos ? '+' : ''}{pnl.toFixed(2)}%
    </span>
  )
}

function ScoreDelta({ entry, latest }: { entry: number | null; latest: number | null }) {
  if (entry == null || latest == null) return <span className="text-slate-600 text-[10px]">—</span>
  const delta = latest - entry
  return (
    <span className="flex flex-col items-end gap-0.5">
      <span className={clsx('font-bold font-mono text-xs',
        latest >= 50 ? 'text-emerald-400' : latest >= 25 ? 'text-yellow-400' : 'text-slate-500')}>
        {latest}
      </span>
      {delta !== 0 && (
        <span className={clsx('text-[10px] font-mono', delta > 0 ? 'text-emerald-600' : 'text-red-600')}>
          {delta > 0 ? '+' : ''}{delta}
        </span>
      )}
    </span>
  )
}

// ── Section 1 : Historique des régimes macro ──────────────────────────────────

function IvRankCell({ underlying }: { underlying: string }) {
  const { data, isLoading } = useIvForTrade(underlying)
  if (isLoading) return <span className="text-slate-700 text-[10px]">…</span>
  const rank = data?.iv_rank
  const iv   = data?.iv_current_pct
  if (rank == null) return <span className="text-slate-700 text-[10px]">—</span>

  const color = rank >= 80 ? 'text-red-400' : rank >= 50 ? 'text-amber-400' : rank >= 20 ? 'text-emerald-400' : 'text-blue-400'
  const signal = rank >= 80 ? '↓vol' : rank < 20 ? '↑vol' : ''

  return (
    <div className="flex flex-col items-end gap-0.5">
      <span className={clsx('text-[10px] font-bold font-mono', color)}>
        {rank}%
      </span>
      <span className="text-[8px] text-slate-600">{iv != null ? `IV ${iv}%` : ''}</span>
      {signal && <span className={clsx('text-[8px] font-semibold', color)}>{signal}</span>}
    </div>
  )
}

function KellyCell({ patternId, capital = 10000 }: { patternId: string; capital?: number }) {
  const { data, isLoading } = useKellySizing(patternId, capital)
  if (!patternId || isLoading) return <span className="text-slate-700 text-[10px]">…</span>
  if (!data || data.error) return <span className="text-slate-700 text-[10px]">—</span>
  const pct = data.suggested_capital_pct
  const eur = data.suggested_capital_eur
  const color = pct <= 0 ? 'text-slate-600' : pct < 5 ? 'text-amber-400' : 'text-emerald-400'
  const adjusted = data.cluster_adjustment_reason || data.reliability_adjustment
  return (
    <div className="flex flex-col items-end gap-0.5">
      <span className={clsx('text-[10px] font-bold font-mono', color)}>{pct?.toFixed(1)}%</span>
      <span className="text-[8px] text-slate-600">{eur != null ? `${eur}€` : ''}</span>
      {adjusted && <span className="text-[8px] text-orange-400" title={adjusted}>⚠ adjusted</span>}
    </div>
  )
}

// ── Close Trade Modal ─────────────────────────────────────────────────────────

const CLOSE_REASONS = [
  { value: 'target', label: '🎯 Target reached' },
  { value: 'stop_loss', label: '🛑 Stop-loss triggered' },
  { value: 'signal_reversal', label: '🔄 AI signal reversed' },
  { value: 'manual', label: '✍️ Manual close' },
]

function CloseTradeModal({ trade, onClose }: { trade: any; onClose: () => void }) {
  const { mutate, isPending, isError } = useCloseTrade()
  const [closePrice, setClosePrice] = useState(String(trade.current_price ?? trade.entry_price ?? ''))
  const [reason, setReason] = useState(trade.alert_type === 'target_reached' ? 'target' :
    trade.alert_type === 'stop_loss' ? 'stop_loss' : 'manual')
  const [note, setNote] = useState('')

  const ep = parseFloat(closePrice) || 0
  const isBearish = trade.direction === 'bearish'
  const pnlPreview = trade.entry_price && ep > 0
    ? (() => {
        const raw = (ep - trade.entry_price) / trade.entry_price * 100
        return round2(isBearish ? -raw : raw)
      })()
    : null

  function round2(n: number) { return Math.round(n * 100) / 100 }

  const handleSubmit = () => {
    mutate({
      id: trade.id,
      body: { close_price: ep, close_reason: reason, close_note: note }
    }, { onSuccess: onClose })
  }

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm">
      <div className="bg-dark-800 border border-slate-700/60 rounded-xl w-full max-w-md p-6 space-y-5 shadow-2xl">
        <div className="flex items-center justify-between">
          <div>
            <div className="text-sm font-bold text-white flex items-center gap-2">
              <Lock className="w-4 h-4 text-amber-400" /> Close trade
            </div>
            <div className="text-xs text-slate-500 mt-0.5">
              {trade.underlying} · {trade.strategy} · entry {trade.entry_price?.toFixed(2) ?? '—'}
            </div>
          </div>
          <button onClick={onClose} className="text-slate-600 hover:text-slate-400"><X className="w-4 h-4" /></button>
        </div>

        {trade.alert_type && (
          <div className={clsx('text-xs rounded px-3 py-2 font-semibold border',
            trade.alert_type === 'target_reached'
              ? 'bg-emerald-900/30 border-emerald-700/40 text-emerald-300'
              : 'bg-red-900/30 border-red-700/40 text-red-300')}>
            {trade.alert_type === 'target_reached' ? '🎯 Target reached!' : '🛑 Stop-loss hit'}
            {' — P&L actuel '}
            <span className="font-mono">{trade.pnl_pct >= 0 ? '+' : ''}{trade.pnl_pct?.toFixed(2)}%</span>
          </div>
        )}

        <div className="space-y-3">
          <div>
            <label className="block text-xs text-slate-500 mb-1">Close price</label>
            <input
              type="number" step="0.01"
              value={closePrice}
              onChange={e => setClosePrice(e.target.value)}
              className="w-full bg-dark-700 border border-slate-600/50 rounded px-3 py-1.5 text-sm text-white font-mono"
              placeholder="Current underlying price"
            />
            {pnlPreview !== null && (
              <div className={clsx('text-xs mt-1 font-mono font-bold',
                pnlPreview >= 0 ? 'text-emerald-400' : 'text-red-400')}>
                Realized P&L: {pnlPreview >= 0 ? '+' : ''}{pnlPreview}%
              </div>
            )}
          </div>

          <div>
            <label className="block text-xs text-slate-500 mb-1">Close reason</label>
            <select
              value={reason}
              onChange={e => setReason(e.target.value)}
              className="w-full bg-dark-700 border border-slate-600/50 rounded px-3 py-1.5 text-sm text-white"
            >
              {CLOSE_REASONS.map(r => (
                <option key={r.value} value={r.value}>{r.label}</option>
              ))}
            </select>
          </div>

          <div>
            <label className="block text-xs text-slate-500 mb-1">Note (optional)</label>
            <input
              type="text"
              value={note}
              onChange={e => setNote(e.target.value)}
              className="w-full bg-dark-700 border border-slate-600/50 rounded px-3 py-1.5 text-sm text-white"
              placeholder="Context, reason…"
              maxLength={200}
            />
          </div>
        </div>

        {isError && <div className="text-xs text-red-400">Error closing trade.</div>}

        <div className="flex gap-3 pt-1">
          <button onClick={onClose}
            className="flex-1 px-4 py-2 rounded border border-slate-700/50 text-slate-400 hover:text-slate-200 text-sm">
            Cancel
          </button>
          <button
            onClick={handleSubmit}
            disabled={isPending || ep === 0}
            className="flex-1 px-4 py-2 rounded bg-amber-600 hover:bg-amber-500 disabled:opacity-50 text-white text-sm font-semibold flex items-center justify-center gap-2"
          >
            <Lock className="w-3.5 h-3.5" />
            {isPending ? 'Closing…' : 'Confirm close'}
          </button>
        </div>
      </div>
    </div>
  )
}

// ── Shared filter bar ────────────────────────────────────────────────────────

const DIRECTIONS = [
  { key: 'all', label: 'All' },
  { key: 'bullish', label: '🐂 Bullish' },
  { key: 'bearish', label: '🐻 Bearish' },
]

function _isBearishStr(strategy: string) {
  return /put|bear|short|sell|vente|baissier/i.test(strategy ?? '')
}

// Normalize AI-returned asset_class variants to canonical CATEGORIES keys
const _TICKER_TO_CLASS: Record<string, string> = {
  // Energy
  'CL=F': 'energy', 'BZ=F': 'energy', 'NG=F': 'energy', 'RB=F': 'energy', 'HO=F': 'energy',
  'XLE': 'energy', 'XOP': 'energy', 'USO': 'energy', 'UCO': 'energy', 'BOIL': 'energy', 'UNG': 'energy',
  // Metals
  'GC=F': 'metals', 'SI=F': 'metals', 'HG=F': 'metals', 'PA=F': 'metals', 'PL=F': 'metals',
  'GLD': 'metals', 'IAU': 'metals', 'SLV': 'metals', 'GDX': 'metals', 'GDXJ': 'metals',
  'PPLT': 'metals', 'DBP': 'metals', 'GLDM': 'metals',
  // Agriculture
  'ZC=F': 'agriculture', 'ZS=F': 'agriculture', 'ZW=F': 'agriculture',
  'CC=F': 'agriculture', 'KC=F': 'agriculture', 'CT=F': 'agriculture', 'OJ=F': 'agriculture',
  'CORN': 'agriculture', 'WEAT': 'agriculture', 'SOYB': 'agriculture', 'DBA': 'agriculture',
  // Indices
  '^GSPC': 'indices', '^NDX': 'indices', '^DJI': 'indices', '^RUT': 'indices',
  'SPY': 'indices', 'QQQ': 'indices', 'IWM': 'indices', 'DIA': 'indices', 'RSP': 'indices',
  'VGK': 'indices', 'EEM': 'indices', 'EWZ': 'indices', 'FXI': 'indices',
  'EWJ': 'indices', 'EFA': 'indices', 'ACWI': 'indices', 'INDA': 'indices',
  '^NSEI': 'indices', '^HSI': 'indices', 'EWG': 'indices', 'EWU': 'indices', 'EWI': 'indices',
  // Equities (sector ETFs)
  'XLF': 'equities', 'XLK': 'equities', 'XLV': 'equities', 'XLI': 'equities',
  'XLP': 'equities', 'XLU': 'equities', 'XLY': 'equities', 'XLRE': 'equities',
  'XLB': 'equities', 'XLC': 'equities',
  // Forex
  'DX-Y.NYB': 'forex', 'UUP': 'forex', 'FXE': 'forex', 'FXY': 'forex',
  'EUO': 'forex', 'YCS': 'forex', 'FXA': 'forex', 'FXB': 'forex', 'FXF': 'forex',
}

function _normalizeAssetClass(cls: string | null | undefined, ticker?: string | null): string {
  if (cls) {
    const c = cls.toLowerCase().trim()
    if (/energy|oil|gas|petrol|brent|wti/.test(c)) return 'energy'
    if (/metal|gold|silver|copper|mining|precious/.test(c)) return 'metals'
    if (/agri|grain|corn|wheat|soy|crop|coton|coffee|cocoa/.test(c)) return 'agriculture'
    if (/index|indic|indices|spx|nasdaq|dow|s&p|russell|cac|dax/.test(c)) return 'indices'
    if (/equit|stock|action|share|sector/.test(c)) return 'equities'
    if (/forex|currency|fx|devise|change|eur|usd|jpy|dxy/.test(c)) return 'forex'
    if (['energy', 'metals', 'agriculture', 'indices', 'equities', 'forex'].includes(c)) return c
  }
  // Fallback: infer from ticker symbol
  if (ticker) {
    const t = ticker.toUpperCase().trim()
    if (_TICKER_TO_CLASS[t]) return _TICKER_TO_CLASS[t]
    // NSE: or other exchange-prefixed equities
    if (t.includes(':')) return 'equities'
    // Remaining =F futures: crude/energy or precious/metals heuristic
    if (t.endsWith('=F')) {
      const stem = t.slice(0, 2)
      if (['CL', 'RB', 'HO', 'NG', 'BZ'].includes(stem)) return 'energy'
      if (['GC', 'SI', 'HG', 'PA', 'PL'].includes(stem)) return 'metals'
      if (['ZC', 'ZS', 'ZW', 'CC', 'KC', 'CT'].includes(stem)) return 'agriculture'
    }
    // Currency pairs
    if (t.includes('=X') || t.includes('/')) return 'forex'
  }
  return cls?.toLowerCase().trim() ?? ''
}

interface FilterBarProps {
  search: string; onSearch: (v: string) => void
  assetClass: string; onAssetClass: (v: string) => void
  direction?: string; onDirection?: (v: string) => void
  pnlFilter?: string; onPnlFilter?: (v: string) => void
}

function FilterBar({ search, onSearch, assetClass, onAssetClass, direction, onDirection, pnlFilter, onPnlFilter }: FilterBarProps) {
  return (
    <div className="flex items-center gap-2 flex-wrap">
      {/* Text search */}
      <div className="relative">
        <Search className="absolute left-2 top-1/2 -translate-y-1/2 w-3 h-3 text-slate-600 pointer-events-none" />
        <input
          type="text"
          value={search}
          onChange={e => onSearch(e.target.value)}
          placeholder="Ticker, strategy…"
          className="pl-6 pr-2 py-1 bg-dark-700 border border-slate-700/50 rounded text-xs text-slate-300 placeholder-slate-600 w-36 focus:outline-none focus:border-slate-500"
        />
        {search && (
          <button onClick={() => onSearch('')} className="absolute right-1.5 top-1/2 -translate-y-1/2 text-slate-600 hover:text-slate-400">
            <X className="w-3 h-3" />
          </button>
        )}
      </div>
      {/* Asset class */}
      <div className="flex items-center gap-0.5 bg-dark-700 rounded p-0.5">
        {CATEGORIES.map(c => (
          <button key={c.key} onClick={() => onAssetClass(c.key)}
            className={clsx('px-2 py-1 rounded text-xs transition-colors', {
              'bg-blue-600 text-white': assetClass === c.key,
              'text-slate-400 hover:text-slate-200': assetClass !== c.key,
            })}>
            {c.label}
          </button>
        ))}
      </div>
      {/* Direction */}
      {onDirection && (
        <div className="flex items-center gap-0.5 bg-dark-700 rounded p-0.5">
          {DIRECTIONS.map(d => (
            <button key={d.key} onClick={() => onDirection(d.key)}
              className={clsx('px-2 py-1 rounded text-xs transition-colors', {
                'bg-slate-600 text-white': direction === d.key,
                'text-slate-400 hover:text-slate-200': direction !== d.key,
              })}>
              {d.label}
            </button>
          ))}
        </div>
      )}
      {/* P&L filter (Fermés only) */}
      {onPnlFilter && (
        <div className="flex items-center gap-0.5 bg-dark-700 rounded p-0.5">
          {[
            { key: 'all', label: 'All' },
            { key: 'winners', label: '✓ Winners' },
            { key: 'losers', label: '✗ Losers' },
          ].map(p => (
            <button key={p.key} onClick={() => onPnlFilter(p.key)}
              className={clsx('px-2 py-1 rounded text-xs transition-colors', {
                'bg-slate-600 text-white': pnlFilter === p.key,
                'text-slate-400 hover:text-slate-200': pnlFilter !== p.key,
              })}>
              {p.label}
            </button>
          ))}
        </div>
      )}
    </div>
  )
}

// ── Closed Trades Section ─────────────────────────────────────────────────────

function ClosedTradesSection({ days }: { days: number }) {
  const { data, isLoading, refetch, isFetching } = useClosedTrades(days)
  const { mutate: deleteTrade, isPending: deleting } = useDeleteTrade()
  const allTrades: any[] = (data as any)?.trades ?? []
  const stats: any = (data as any)?.stats ?? {}

  const [search, setSearch] = useState('')
  const [assetClass, setAssetClass] = useState('all')
  const [direction, setDirection] = useState('all')
  const [pnlFilter, setPnlFilter] = useState('all')
  const [confirmDeleteId, setConfirmDeleteId] = useState<number | null>(null)

  const trades = allTrades.filter((t: any) => {
    const q = search.toLowerCase()
    if (q && !`${t.underlying} ${t.strategy ?? ''} ${t.pattern_name ?? ''}`.toLowerCase().includes(q)) return false
    if (assetClass !== 'all' && _normalizeAssetClass(t.asset_class, t.underlying) !== assetClass) return false
    const bearish = _isBearishStr(t.strategy ?? '')
    if (direction === 'bullish' && bearish) return false
    if (direction === 'bearish' && !bearish) return false
    if (pnlFilter === 'winners' && (t.pnl_realized ?? 0) < 0) return false
    if (pnlFilter === 'losers' && (t.pnl_realized ?? 0) >= 0) return false
    return true
  })

  const REASON_META: Record<string, { label: string; color: string }> = {
    target:          { label: '🎯 Target', color: 'text-emerald-400' },
    stop_loss:       { label: '🛑 Stop-loss', color: 'text-red-400' },
    signal_reversal: { label: '🔄 AI Signal', color: 'text-blue-400' },
    manual:          { label: '✍️ Manual', color: 'text-slate-400' },
  }

  return (
    <div className="space-y-4">
      {/* Stats banner */}
      {allTrades.length > 0 && (
        <div className="grid grid-cols-4 gap-3">
          {[
            { label: 'Closed trades', value: stats.total ?? 0, sub: '', color: 'text-white' },
            { label: 'Win rate', value: stats.win_rate != null ? `${stats.win_rate}%` : '—', sub: '', color: stats.win_rate >= 50 ? 'text-emerald-400' : 'text-red-400' },
            { label: 'Avg P&L', value: stats.avg_pnl != null ? `${stats.avg_pnl >= 0 ? '+' : ''}${stats.avg_pnl?.toFixed(1)}%` : '—', sub: '', color: (stats.avg_pnl ?? 0) >= 0 ? 'text-emerald-400' : 'text-red-400' },
            { label: 'Total P&L', value: stats.total_pnl != null ? `${stats.total_pnl >= 0 ? '+' : ''}${stats.total_pnl?.toFixed(1)}%` : '—', sub: `best ${stats.best?.toFixed(1) ?? '—'}%`, color: (stats.total_pnl ?? 0) >= 0 ? 'text-emerald-400' : 'text-red-400' },
          ].map(s => (
            <div key={s.label} className="card text-center py-3">
              <div className={clsx('text-lg font-bold font-mono', s.color)}>{s.value}</div>
              <div className="text-[11px] text-slate-600">{s.label}</div>
              {s.sub && <div className="text-[10px] text-slate-700 mt-0.5">{s.sub}</div>}
            </div>
          ))}
        </div>
      )}

      <div className="flex items-center justify-between flex-wrap gap-2">
        <div className="text-xs font-semibold text-slate-500 uppercase tracking-wide">
          {trades.length}/{allTrades.length} closed trades · last {days} days
        </div>
        <button onClick={() => refetch()} disabled={isFetching}
          className="text-slate-600 hover:text-slate-400 disabled:opacity-40">
          <RefreshCw className={clsx('w-3.5 h-3.5', isFetching && 'animate-spin')} />
        </button>
      </div>

      <FilterBar
        search={search} onSearch={setSearch}
        assetClass={assetClass} onAssetClass={setAssetClass}
        direction={direction} onDirection={setDirection}
        pnlFilter={pnlFilter} onPnlFilter={setPnlFilter}
      />

      {isLoading ? (
        <div className="card h-32 animate-pulse bg-dark-700" />
      ) : allTrades.length === 0 ? (
        <div className="card text-center py-12 text-slate-600 text-sm">
          <Lock className="w-8 h-8 mx-auto mb-2 opacity-20" />
          No closed trades in the last {days} days
        </div>
      ) : trades.length === 0 ? (
        <div className="card text-center py-8 text-slate-600 text-sm">
          No results for these filters
        </div>
      ) : (
        <div className="overflow-x-auto rounded-lg border border-slate-700/40">
          <table className="w-full text-xs">
            <thead>
              <tr className="text-slate-600 border-b border-slate-700/40">
                <th className="text-left px-3 py-2 font-medium">Pattern</th>
                <th className="text-left px-3 py-2 font-medium">Strategy</th>
                <th className="text-left px-3 py-2 font-medium">Ticker</th>
                <th className="text-right px-3 py-2 font-medium">Entry</th>
                <th className="text-right px-3 py-2 font-medium">Exit</th>
                <th className="text-right px-3 py-2 font-medium">Entry date</th>
                <th className="text-right px-3 py-2 font-medium">Close date</th>
                <th className="text-right px-3 py-2 font-medium">Duration</th>
                <th className="text-right px-3 py-2 font-medium">Realized P&L</th>
                <th className="text-left px-3 py-2 font-medium">Reason</th>
                <th className="text-left px-3 py-2 font-medium">Note</th>
                <th className="px-2 py-2 w-8"></th>
              </tr>
            </thead>
            <tbody className="divide-y divide-slate-800/60">
              {trades.map((t: any) => {
                const meta = REASON_META[t.close_reason] ?? REASON_META.manual
                const daysHeld = t.entry_date && t.closed_at
                  ? Math.round((new Date(t.closed_at).getTime() - new Date(t.entry_date).getTime()) / 86400000)
                  : null
                const isConfirming = confirmDeleteId === t.id
                return (
                  <tr key={t.id} className="hover:bg-dark-700/30 transition-colors">
                    <td className="px-3 py-2 text-slate-300 max-w-[100px] truncate">{t.pattern_name || t.pattern_id}</td>
                    <td className="px-3 py-2">
                      <span className={clsx('badge text-[10px]',
                        _isBearishStr(t.strategy ?? '') ? 'badge-red' : 'badge-green')}>
                        {t.strategy || '—'}
                      </span>
                    </td>
                    <td className="px-3 py-2 font-mono text-slate-300">{t.underlying}</td>
                    <td className="px-3 py-2 text-right font-mono text-slate-500 text-[11px]">
                      {t.entry_price != null ? t.entry_price.toFixed(2) : '—'}
                    </td>
                    <td className="px-3 py-2 text-right font-mono text-slate-400 text-[11px]">
                      {t.close_price != null ? t.close_price.toFixed(2) : '—'}
                    </td>
                    <td className="px-3 py-2 text-right text-slate-600 text-[11px]">{t.entry_date ?? '—'}</td>
                    <td className="px-3 py-2 text-right text-slate-600 text-[11px]">
                      {t.closed_at ? t.closed_at.slice(0, 10) : '—'}
                    </td>
                    <td className="px-3 py-2 text-right text-slate-600 text-[11px] font-mono">
                      {daysHeld != null ? `${daysHeld}j` : '—'}
                    </td>
                    <td className="px-3 py-2 text-right">
                      {t.pnl_realized != null ? (
                        <span className={clsx('font-bold font-mono text-xs',
                          t.pnl_realized >= 0 ? 'text-emerald-400' : 'text-red-400')}>
                          {t.pnl_realized >= 0 ? '+' : ''}{t.pnl_realized.toFixed(2)}%
                        </span>
                      ) : <span className="text-slate-600">—</span>}
                    </td>
                    <td className="px-3 py-2">
                      <span className={clsx('text-[10px] font-medium', meta.color)}>{meta.label}</span>
                    </td>
                    <td className="px-3 py-2 text-slate-600 text-[10px] max-w-[120px] truncate" title={t.close_note}>
                      {t.close_note || '—'}
                    </td>
                    <td className="px-2 py-2">
                      {isConfirming ? (
                        <div className="flex items-center gap-1">
                          <button
                            onClick={() => { deleteTrade(t.id, { onSuccess: () => setConfirmDeleteId(null) }) }}
                            disabled={deleting}
                            className="text-[10px] font-semibold text-red-400 hover:text-red-300 bg-red-900/30 border border-red-700/40 rounded px-1.5 py-0.5 disabled:opacity-40"
                          >
                            {deleting ? '…' : 'Delete'}
                          </button>
                          <button onClick={() => setConfirmDeleteId(null)} className="text-slate-600 hover:text-slate-400">
                            <X className="w-3 h-3" />
                          </button>
                        </div>
                      ) : (
                        <button
                          onClick={() => setConfirmDeleteId(t.id)}
                          className="p-1 rounded text-slate-700 hover:text-red-400 hover:bg-red-900/20 transition-colors"
                          title="Delete this trade"
                        >
                          <Trash2 className="w-3.5 h-3.5" />
                        </button>
                      )}
                    </td>
                  </tr>
                )
              })}
            </tbody>
          </table>
        </div>
      )}
    </div>
  )
}

// ── IBKR Ticket helpers ───────────────────────────────────────────────────────

function computeStrikeDollars(price: number, guidance: string, strategy: string): number {
  const g = guidance.toUpperCase()
  const match = g.match(/(\d+)\s*%\s*OTM/)
  if (!match) return price
  const pct = parseInt(match[1]) / 100
  const isBearish = /put|bear/i.test(strategy)
  const raw = isBearish ? price * (1 - pct) : price * (1 + pct)
  const inc = price > 1000 ? 10 : price > 200 ? 5 : price > 50 ? 1 : 0.5
  return Math.round(raw / inc) * inc
}

function estimateExpiryDate(horizonDays: number): Date {
  const d = new Date()
  d.setDate(d.getDate() + horizonDays)
  const dow = d.getDay()
  if (dow !== 5) d.setDate(d.getDate() + ((5 - dow + 7) % 7))
  return d
}

function buildLegs(strategy: string, strike: number | null, price: number | null) {
  const s = strategy.toLowerCase()
  const atm = price ? (() => {
    const inc = price > 1000 ? 10 : price > 200 ? 5 : price > 50 ? 1 : 0.5
    return Math.round(price / inc) * inc
  })() : null
  if (s.includes('bull call spread')) return [
    { action: 'BUY',  type: 'CALL', strike: atm },
    { action: 'SELL', type: 'CALL', strike },
  ]
  if (s.includes('bear put spread')) return [
    { action: 'BUY',  type: 'PUT', strike: atm },
    { action: 'SELL', type: 'PUT', strike },
  ]
  if (s.includes('straddle')) return [
    { action: 'BUY', type: 'CALL', strike: atm ?? strike },
    { action: 'BUY', type: 'PUT',  strike: atm ?? strike },
  ]
  if (s.includes('strangle')) return [
    { action: 'BUY', type: 'CALL', strike: price ? Math.round(price * 1.05) : strike },
    { action: 'BUY', type: 'PUT',  strike: price ? Math.round(price * 0.95) : strike },
  ]
  if (s.includes('call')) return [{ action: 'BUY', type: 'CALL', strike }]
  if (s.includes('put'))  return [{ action: 'BUY', type: 'PUT',  strike }]
  return [{ action: 'BUY', type: strategy.toUpperCase(), strike }]
}

function IBKRTicket({ strategy, underlying, strikeGuidance, expiryDays, entryPrice, maxLoss, targetGain }: {
  strategy: string
  underlying: string
  strikeGuidance?: string | null
  expiryDays?: number | null
  entryPrice?: number | null
  maxLoss?: number | null
  targetGain?: number | null
}) {
  const strike = entryPrice && strikeGuidance
    ? computeStrikeDollars(entryPrice, strikeGuidance, strategy)
    : (entryPrice ?? null)
  const expiryDate = expiryDays ? estimateExpiryDate(expiryDays) : null
  const legs = buildLegs(strategy, strike, entryPrice ?? null)
  const fmtStrike = (s: number | null | undefined) =>
    s == null ? '—' : s >= 100 ? `$${s.toFixed(0)}` : `$${s.toFixed(2)}`

  return (
    <div className="bg-blue-950/20 border border-blue-700/30 rounded p-3 space-y-2.5">
      <div className="text-[10px] font-bold text-blue-300 uppercase tracking-wide flex items-center gap-1.5">
        <Terminal className="w-3 h-3" /> IBKR Ticket
        {!entryPrice && <span className="ml-auto text-slate-600 font-normal normal-case">Price unavailable — check in IBKR</span>}
      </div>

      <div className="grid grid-cols-3 gap-3 text-[10px]">
        <div>
          <div className="text-slate-600 mb-0.5">Underlying</div>
          <div className="text-white font-mono font-bold text-sm">{underlying}</div>
          <div className="text-slate-600 text-[9px]">Security Type: OPT</div>
        </div>
        <div>
          <div className="text-slate-600 mb-0.5">Strategy</div>
          <div className="text-slate-200 font-semibold">{strategy}</div>
          {entryPrice && <div className="text-slate-600 text-[9px]">Underlying: ${entryPrice.toFixed(2)}</div>}
        </div>
        <div>
          <div className="text-slate-600 mb-0.5">Expiry</div>
          <div className="text-slate-200 font-mono">
            {expiryDate ? format(expiryDate, 'd MMM yyyy', { locale: fr }) : expiryDays ? `~${expiryDays}d` : '—'}
          </div>
          <div className="text-slate-600 text-[9px]">{expiryDays ? `${expiryDays}d DTE` : ''}</div>
        </div>
      </div>

      <div className="space-y-1">
        {legs.map((leg, i) => (
          <div key={i} className="flex items-center gap-2 bg-slate-900/70 rounded px-2.5 py-1.5 font-mono text-[10px]">
            <span className={clsx('w-8 font-bold', leg.action === 'BUY' ? 'text-emerald-400' : 'text-red-400')}>{leg.action}</span>
            <span className="text-slate-400">1 contract</span>
            <span className={clsx('font-bold w-10 text-center', leg.type === 'CALL' ? 'text-blue-300' : leg.type === 'PUT' ? 'text-orange-300' : 'text-slate-300')}>{leg.type}</span>
            <span className="text-slate-600">Strike</span>
            <span className="text-yellow-300 font-bold">{fmtStrike(leg.strike)}</span>
            {leg.strike === null && strikeGuidance && (
              <span className="text-slate-500">({strikeGuidance})</span>
            )}
          </div>
        ))}
      </div>

      <div className="grid grid-cols-3 gap-3 text-[10px]">
        <div>
          <div className="text-slate-600 mb-0.5">Order type</div>
          <div className="text-slate-300 font-semibold">LIMIT</div>
          <div className="text-slate-600 text-[9px]">Price = premium in IBKR</div>
        </div>
        <div>
          <div className="text-slate-600 mb-0.5">Max budget</div>
          <div className="text-slate-300 font-mono">{maxLoss ? `${Math.abs(maxLoss).toFixed(0)}€` : '~1 000€'}</div>
          <div className="text-slate-600 text-[9px]">Estimated max loss</div>
        </div>
        <div>
          <div className="text-slate-600 mb-0.5">Target</div>
          <div className="text-emerald-400 font-mono">{targetGain ? `+${targetGain.toFixed(0)}€` : '—'}</div>
        </div>
      </div>
    </div>
  )
}

function MacroHistorySection({ days }: { days: number }) {
  const { data, isLoading, refetch, isFetching } = useMacroHistory(days)
  const history: any[] = (data as any)?.history ?? []

  return (
    <div className="space-y-3">
      <div className="flex items-center justify-between">
        <div className="text-xs font-semibold text-slate-500 uppercase tracking-wide">
          {history.length} snapshots · last {days} days
        </div>
        <button onClick={() => refetch()} disabled={isFetching}
          className="text-slate-600 hover:text-slate-400 disabled:opacity-40">
          <RefreshCw className={clsx('w-3.5 h-3.5', isFetching && 'animate-spin')} />
        </button>
      </div>

      {isLoading ? (
        <div className="space-y-2">{[1,2,3].map(i => <div key={i} className="card h-14 animate-pulse bg-dark-700" />)}</div>
      ) : history.length === 0 ? (
        <div className="card text-center py-10 text-slate-600 text-sm">
          <Activity className="w-8 h-8 mx-auto mb-2 opacity-20" />
          No snapshots — click "Re-analyze" in Macro Regime to start logging
        </div>
      ) : (
        <div className="space-y-2">
          {history.map((entry: any, i: number) => {
            const scores: Record<string, number> = entry.scores ?? {}
            const maxScore = Math.max(...Object.values(scores), 1)
            const ts = entry.timestamp?.slice(0, 16).replace('T', ' ') ?? ''
            const reasons: string[] = entry.reasons?.[entry.dominant] ?? []
            const isTransition = i > 0 && history[i - 1].dominant !== entry.dominant

            return (
              <div key={entry.id} className={clsx('card', isTransition && 'border-amber-700/30')}>
                <div className="flex items-center gap-3 mb-2">
                  {isTransition && (
                    <span className="text-[10px] bg-amber-900/30 text-amber-400 border border-amber-700/30 rounded px-1.5 py-0.5 shrink-0">
                      ↕ Transition (regime change)
                    </span>
                  )}
                  <ScenarioBadge dominant={entry.dominant} size="lg" />
                  <span className="text-xs text-slate-600 ml-auto shrink-0">{ts} UTC</span>
                </div>

                <div className="grid grid-cols-4 gap-x-3 gap-y-1 mb-2">
                  {Object.entries(scores)
                    .sort(([, a], [, b]) => (b as number) - (a as number))
                    .slice(0, 8)
                    .map(([key, score]) => {
                      const m = SCENARIO_META[key] ?? SCENARIO_META.incertain
                      return (
                        <div key={key} className="flex items-center gap-1">
                          <div className="w-16 text-[10px] text-slate-600 truncate">{m.label}</div>
                          <div className="flex-1 h-1.5 bg-dark-700 rounded-full overflow-hidden">
                            <div className="h-full rounded-full transition-all"
                              style={{ width: `${((score as number) / maxScore) * 100}%`, background: m.color }} />
                          </div>
                          <span className="text-[10px] font-mono text-slate-500 w-6 text-right">{score}</span>
                        </div>
                      )
                    })}
                </div>

                {reasons.length > 0 && (
                  <div className="flex flex-wrap gap-1">
                    {reasons.slice(0, 4).map((r: string, ri: number) => (
                      <span key={ri} className="text-[10px] text-slate-500 bg-dark-700 px-1.5 py-0.5 rounded">{r}</span>
                    ))}
                  </div>
                )}
              </div>
            )
          })}
        </div>
      )}
    </div>
  )
}

// ── Post-mortem panel ─────────────────────────────────────────────────────────

function PostmortemPanel({ tradeId, onClose }: { tradeId: number; onClose: () => void }) {
  const { data, isLoading } = useTradePostmortem(tradeId)
  const { mutate: analyze, isPending: analyzing, data: analysisData } = useAnalyzePostmortem()
  const [showScoring, setShowScoring] = useState(true)
  const [showSuggestion, setShowSuggestion] = useState(false)

  if (isLoading) {
    return (
      <div className="card mt-3 p-4 border border-blue-700/30 animate-pulse">
        <div className="h-4 bg-dark-700 rounded w-48 mb-3" />
        <div className="h-3 bg-dark-700 rounded w-full mb-2" />
        <div className="h-3 bg-dark-700 rounded w-3/4" />
      </div>
    )
  }
  if (!data) return null

  const { trade, scoring_context: sc, suggestion_context: sg, score_history } = data as any
  const scOut = sc?.output ?? {}
  const sgOut = sg?.output ?? {}
  const scCtx = sc?.input_context ?? {}
  const buckets: any[] = scOut.buckets ?? []
  const analysis: any = analysisData?.analysis ?? null

  return (
    <div className="mt-3 rounded-lg border border-blue-700/30 bg-dark-900/80 p-4 space-y-4 text-xs">
      {/* Header */}
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-2">
          <Brain className="w-4 h-4 text-blue-400" />
          <span className="font-semibold text-blue-300">Post-mortem — {trade?.pattern_name}</span>
          <span className="text-slate-500">|</span>
          <span className="font-mono text-slate-400">{trade?.underlying} {trade?.strategy}</span>
        </div>
        <button onClick={onClose} className="text-slate-600 hover:text-slate-400">
          <X className="w-4 h-4" />
        </button>
      </div>

      {/* Score history sparkline */}
      {score_history?.length > 0 && (
        <div className="flex items-center gap-3">
          <span className="text-slate-600 shrink-0">History:</span>
          <div className="flex items-center gap-1.5 flex-wrap">
            {[...score_history].reverse().map((h: any, i: number) => (
              <div key={i} className="flex flex-col items-center gap-0.5">
                <div
                  className="w-6 rounded-sm"
                  style={{
                    height: `${Math.max(4, (h.score ?? 0) / 2)}px`,
                    background: (h.score ?? 0) >= 60 ? '#22c55e' : (h.score ?? 0) >= 40 ? '#eab308' : '#64748b',
                  }}
                />
                <span className="text-[9px] font-mono text-slate-600">{h.score ?? '?'}</span>
              </div>
            ))}
          </div>
          {score_history.length > 0 && (
            <span className="text-slate-600 ml-auto shrink-0">
              {score_history[0]?.macro_dominant ?? ''} — geo {score_history[0]?.geo_score ?? '?'}
            </span>
          )}
        </div>
      )}

      {/* Scoring context */}
      <div>
        <button
          className="flex items-center gap-1.5 text-slate-400 hover:text-slate-200 font-semibold mb-2"
          onClick={() => setShowScoring(v => !v)}
        >
          {showScoring ? <ChevronUp className="w-3.5 h-3.5" /> : <ChevronDown className="w-3.5 h-3.5" />}
          Why scored {scOut.score ?? '?'}/100
          {scOut.key_catalyst && <span className="text-slate-600 font-normal ml-1">· {scOut.key_catalyst}</span>}
        </button>
        {showScoring && (
          <div className="pl-5 space-y-2">
            {/* Regime / bias */}
            <div className="flex flex-wrap gap-3 text-[11px] text-slate-500">
              {sc?.macro_dominant && (
                <span>Regime: <ScenarioBadge dominant={sc.macro_dominant} /></span>
              )}
              {scCtx.asset_bias && (
                <span>Asset bias: <span className="text-slate-300">{scCtx.asset_bias}</span></span>
              )}
              {sc?.geo_score != null && (
                <span>Geo: <span className="font-mono text-slate-300">{sc.geo_score}/100</span></span>
              )}
            </div>
            {/* Buckets */}
            {buckets.length > 0 && (
              <div className="grid grid-cols-2 gap-1.5">
                {buckets.map((b: any, i: number) => {
                  const pct = b.max ? Math.round((b.score / b.max) * 100) : 0
                  const color = pct >= 66 ? '#22c55e' : pct >= 33 ? '#eab308' : '#ef4444'
                  return (
                    <div key={i} className="flex flex-col gap-0.5 bg-dark-800 rounded p-2">
                      <div className="flex items-center justify-between">
                        <span className="text-slate-400 font-medium truncate mr-2">{b.label ?? b.id}</span>
                        <span className="font-mono shrink-0" style={{ color }}>{b.score}/{b.max}</span>
                      </div>
                      <div className="h-1 bg-dark-700 rounded-full overflow-hidden">
                        <div className="h-full rounded-full" style={{ width: `${pct}%`, background: color }} />
                      </div>
                      {b.comment && (
                        <span className="text-[10px] text-slate-600 line-clamp-2">{b.comment}</span>
                      )}
                    </div>
                  )
                })}
              </div>
            )}
            {scOut.summary && (
              <p className="text-slate-500 italic">{scOut.summary}</p>
            )}
          </div>
        )}
      </div>

      {/* Suggestion context */}
      {sg && (
        <div>
          <button
            className="flex items-center gap-1.5 text-slate-400 hover:text-slate-200 font-semibold mb-2"
            onClick={() => setShowSuggestion(v => !v)}
          >
            {showSuggestion ? <ChevronUp className="w-3.5 h-3.5" /> : <ChevronDown className="w-3.5 h-3.5" />}
            Why this pattern was created
          </button>
          {showSuggestion && (
            <div className="pl-5 space-y-1.5 text-[11px] text-slate-400">
              {sgOut.macro_fit && <p className="italic">{sgOut.macro_fit}</p>}
              {sgOut.description && <p className="text-slate-500">{sgOut.description}</p>}
              {sg.macro_dominant && (
                <div className="flex gap-3 mt-1">
                  <span>Created under: <ScenarioBadge dominant={sg.macro_dominant} /></span>
                  {sg.geo_score != null && <span>Geo: <span className="font-mono text-slate-300">{sg.geo_score}/100</span></span>}
                </div>
              )}
            </div>
          )}
        </div>
      )}

      {/* GPT-4o analysis */}
      <div className="border-t border-slate-800 pt-3">
        {!analysis ? (
          <button
            onClick={() => analyze(tradeId)}
            disabled={analyzing}
            className="flex items-center gap-2 px-3 py-1.5 rounded bg-blue-900/30 border border-blue-700/40 text-blue-300 hover:bg-blue-900/50 disabled:opacity-50 text-xs font-medium"
          >
            <Brain className={clsx('w-3.5 h-3.5', analyzing && 'animate-pulse')} />
            {analyzing ? 'GPT-4o analysis running…' : 'Analyze with GPT-4o'}
          </button>
        ) : (
          <div className="space-y-3">
            <div className="flex items-center gap-2 text-blue-400 font-semibold">
              <Brain className="w-3.5 h-3.5" />
              GPT-4o Analysis
            </div>
            {[
              { key: 'diagnostic', label: 'Diagnostic', color: 'text-slate-200' },
              { key: 'what_worked', label: 'What worked', color: 'text-emerald-400' },
              { key: 'what_missed', label: 'What was missed', color: 'text-red-400' },
              { key: 'regime_alignment', label: 'Regime alignment', color: 'text-yellow-400' },
              { key: 'contra_assessment', label: 'Contra-signals', color: 'text-orange-400' },
              { key: 'lesson', label: 'Lesson', color: 'text-blue-300' },
              { key: 'next_cycle', label: 'Next cycle', color: 'text-purple-400' },
            ].map(({ key, label, color }) =>
              analysis[key] ? (
                <div key={key}>
                  <span className={clsx('font-semibold', color)}>{label} : </span>
                  <span className="text-slate-400">{analysis[key]}</span>
                </div>
              ) : null
            )}
          </div>
        )}
      </div>
    </div>
  )
}

// ── Section 2 : Mark-to-Market des trades ─────────────────────────────────────

function TradeMtmSection({ days }: { days: number }) {
  const { data, isLoading, refetch, isFetching } = useTradeMtm(days)
  const [minScoreFilter, setMinScoreFilter] = useState(0)
  const [selectedTradeId, setSelectedTradeId] = useState<number | null>(null)
  const [closingTrade, setClosingTrade] = useState<any | null>(null)
  const [search, setSearch] = useState('')
  const [assetClass, setAssetClass] = useState('all')
  const [direction, setDirection] = useState('all')

  const allTrades: any[] = ((data as any)?.trades ?? []).filter((t: any) => t.status !== 'closed')
  const trades = allTrades.filter((t: any) => {
    if ((t.latest_score ?? t.score_at_entry ?? 0) < minScoreFilter) return false
    const q = search.toLowerCase()
    if (q && !`${t.underlying} ${t.strategy ?? ''} ${t.pattern_name ?? ''}`.toLowerCase().includes(q)) return false
    if (assetClass !== 'all' && _normalizeAssetClass(t.asset_class, t.underlying) !== assetClass) return false
    const bearish = _isBearishStr(t.strategy ?? '')
    if (direction === 'bullish' && bearish) return false
    if (direction === 'bearish' && !bearish) return false
    return true
  })

  const withPnl = trades.filter((t: any) => t.pnl_pct != null)
  const avgPnl = withPnl.length
    ? withPnl.reduce((s: number, t: any) => s + t.pnl_pct, 0) / withPnl.length
    : null

  return (
    <div className="space-y-3">
      <div className="flex items-center justify-between gap-4 flex-wrap">
        <div className="text-xs font-semibold text-slate-500 uppercase tracking-wide">
          {trades.length}/{allTrades.length} trades · {withPnl.length} priced
          {avgPnl != null && (
            <span className={clsx('ml-2 font-bold', avgPnl >= 0 ? 'text-emerald-400' : 'text-red-400')}>
              · avg {avgPnl >= 0 ? '+' : ''}{avgPnl.toFixed(1)}%
            </span>
          )}
        </div>

        <div className="flex items-center gap-3">
          {/* Score filter */}
          <div className="flex items-center gap-2 text-xs text-slate-500">
            <span className="shrink-0">Score ≥</span>
            <input type="range" min="0" max="80" step="5"
              value={minScoreFilter}
              onChange={e => setMinScoreFilter(parseInt(e.target.value))}
              className="w-24 accent-blue-500" />
            <span className="w-5 font-mono text-blue-400">{minScoreFilter}</span>
          </div>
          <button onClick={() => refetch()} disabled={isFetching}
            className="text-slate-600 hover:text-slate-400 disabled:opacity-40">
            <RefreshCw className={clsx('w-3.5 h-3.5', isFetching && 'animate-spin')} />
          </button>
        </div>
      </div>

      <FilterBar
        search={search} onSearch={setSearch}
        assetClass={assetClass} onAssetClass={setAssetClass}
        direction={direction} onDirection={setDirection}
      />

      {closingTrade && (
        <CloseTradeModal trade={closingTrade} onClose={() => setClosingTrade(null)} />
      )}

      {isLoading ? (
        <div className="card h-32 animate-pulse bg-dark-700" />
      ) : trades.length === 0 ? (
        <div className="card text-center py-10 text-slate-600 text-sm">
          <TrendingUp className="w-8 h-8 mx-auto mb-2 opacity-20" />
          {allTrades.length === 0
            ? 'No open trades — score patterns to start tracking'
            : 'No results for these filters'}
        </div>
      ) : (
        <div className="overflow-x-auto rounded-lg border border-slate-700/40">
          <table className="w-full text-xs">
            <thead>
              <tr className="text-slate-600 border-b border-slate-700/40">
                <th className="text-left px-3 py-2 font-medium">Pattern</th>
                <th className="text-left px-3 py-2 font-medium">Profile</th>
                <th className="text-left px-3 py-2 font-medium">Strategy</th>
                <th className="text-right px-3 py-2 font-medium">Strike</th>
                <th className="text-right px-3 py-2 font-medium">DTE</th>
                <th className="text-left px-3 py-2 font-medium">Ticker</th>
                <th className="text-right px-3 py-2 font-medium">Score</th>
                <th className="text-right px-3 py-2 font-medium">Trade Score</th>
                <th className="text-right px-3 py-2 font-medium">Net EV</th>
                <th className="text-right px-3 py-2 font-medium">Expected move</th>
                <th className="text-right px-3 py-2 font-medium">Date</th>
                <th className="text-right px-3 py-2 font-medium">Entry price</th>
                <th className="text-right px-3 py-2 font-medium">Current price</th>
                <th className="text-right px-3 py-2 font-medium">Target/Stop</th>
                <th className="text-right px-3 py-2 font-medium">Maturity</th>
                <th className="text-right px-3 py-2 font-medium">IV Rank</th>
                <th className="text-right px-3 py-2 font-medium">Kelly</th>
                <th className="text-right px-3 py-2 font-medium">P&L</th>
                <th className="px-3 py-2 font-medium w-8"></th>
                <th className="px-3 py-2 font-medium w-8"></th>
              </tr>
            </thead>
            <tbody className="divide-y divide-slate-800/60">
              {trades.map((t: any) => {
                const evNet = t.ev_net ?? null
                const tradeScore = t.trade_score ?? null
                const isExpanded = selectedTradeId === t.id
                return (
                <Fragment key={t.id}>
                <tr
                  className={clsx('hover:bg-dark-700/30 transition-colors cursor-pointer', isExpanded && 'bg-dark-700/40 border-b-0')}
                  onClick={() => setSelectedTradeId(isExpanded ? null : t.id)}
                >
                  <td className="px-3 py-2 text-slate-300 max-w-[110px] truncate">{t.pattern_name || t.pattern_id}</td>
                  <td className="px-3 py-2">
                    {t.matched_profile ? (
                      <span className="text-[10px] font-semibold text-slate-400 bg-dark-700 px-1.5 py-0.5 rounded border border-slate-700/50">
                        {t.matched_profile}
                      </span>
                    ) : <span className="text-slate-700 text-[10px]">—</span>}
                  </td>
                  <td className="px-3 py-2">
                    <span className={clsx('badge text-[10px]',
                      t.direction === 'bearish' ? 'badge-red' : 'badge-green')}>
                      {t.direction === 'bearish' ? '🐻' : '🐂'} {t.strategy || '—'}
                    </span>
                  </td>
                  <td className="px-3 py-2 text-right font-mono text-[11px] text-slate-400">
                    {t.strike_guidance ?? '—'}
                  </td>
                  <td className="px-3 py-2 text-right font-mono text-[11px] text-slate-400">
                    {t.expiry_days_at_entry != null ? `${t.expiry_days_at_entry}d` : t.horizon_days != null ? `${t.horizon_days}d` : '—'}
                  </td>
                  <td className="px-3 py-2 font-mono">
                    <div className="flex items-center gap-1">
                      <span className={clsx(t.price_warning ? 'text-amber-300' : 'text-slate-300')}>{t.underlying}</span>
                      {t.price_warning && (
                        <span
                          className="text-[8px] font-bold bg-amber-900/40 border border-amber-600/40 text-amber-400 rounded px-1 py-0.5 leading-none shrink-0"
                          title={t.price_warning === 'no_price_data' ? 'No price data — monitoring unavailable' : t.price_warning === 'no_entry_price' ? 'Missing entry price' : 'Live price unavailable'}
                        >
                          ⚠ {t.price_warning === 'no_price_data' ? 'NO DATA' : t.price_warning === 'no_entry_price' ? 'NO ENTRY' : 'NO LIVE'}
                        </span>
                      )}
                    </div>
                  </td>
                  <td className="px-3 py-2 text-right">
                    <ScoreDelta entry={t.score_at_entry} latest={t.latest_score ?? t.score_at_entry} />
                  </td>
                  <td className="px-3 py-2 text-right">
                    {tradeScore != null ? (
                      <span className={clsx('font-bold font-mono text-xs',
                        tradeScore >= 55 ? 'text-emerald-400' : tradeScore >= 45 ? 'text-yellow-400' : 'text-slate-500')}>
                        {tradeScore.toFixed(1)}
                      </span>
                    ) : <span className="text-slate-700 text-xs">—</span>}
                  </td>
                  <td className="px-3 py-2 text-right">
                    {evNet != null ? (
                      <span className={clsx('font-mono text-[11px]',
                        evNet > 0.05 ? 'text-emerald-400' : evNet >= -0.01 ? 'text-yellow-400' : 'text-slate-600')}>
                        {evNet > 0 ? '+' : ''}{(evNet * 100).toFixed(0)}%
                      </span>
                    ) : <span className="text-slate-700 text-xs">—</span>}
                  </td>
                  <td className="px-3 py-2 text-right">
                    {t.expected_move_pct != null ? (
                      <span className="font-mono text-[11px] text-slate-500">{t.expected_move_pct.toFixed(0)}%</span>
                    ) : <span className="text-slate-700 text-xs">—</span>}
                  </td>
                  <td className="px-3 py-2 text-right text-slate-600 whitespace-nowrap text-[11px]">{t.entry_date}</td>
                  <td className={clsx('px-3 py-2 text-right font-mono text-[11px]', t.price_warning === 'no_entry_price' || t.price_warning === 'no_price_data' ? 'text-amber-600' : 'text-slate-400')}>
                    {t.entry_price != null ? t.entry_price.toFixed(2) : '—'}
                  </td>
                  <td className={clsx('px-3 py-2 text-right font-mono text-[11px]', t.price_warning === 'no_live_price' || t.price_warning === 'no_price_data' ? 'text-amber-600' : 'text-slate-300')}>
                    {t.current_price != null ? t.current_price.toFixed(2) : '—'}
                  </td>
                  <td className="px-3 py-2 text-right">
                    {t.pnl_pct != null ? (
                      <div className="flex flex-col items-end gap-1">
                        <div className="flex items-center gap-1.5">
                          {t.alert_type === 'target_reached' && (
                            <span className="text-[9px] font-bold text-emerald-400 bg-emerald-900/30 border border-emerald-700/30 rounded px-1">🎯</span>
                          )}
                          {t.alert_type === 'stop_loss' && (
                            <span className="text-[9px] font-bold text-red-400 bg-red-900/30 border border-red-700/30 rounded px-1">🛑</span>
                          )}
                        </div>
                        {/* progress bar: stop_loss (negative) to target (positive) */}
                        <div className="w-16 relative">
                          <div className="h-1.5 bg-slate-700 rounded-full overflow-hidden">
                            <div
                              className={clsx('h-full rounded-full',
                                t.pnl_pct >= 0 ? 'bg-emerald-500' : 'bg-red-500')}
                              style={{
                                width: `${Math.min(
                                  100,
                                  t.pnl_pct >= 0
                                    ? (t.pnl_pct / (t.target_pct || 30)) * 100
                                    : (Math.abs(t.pnl_pct) / Math.abs(t.stop_loss_pct || 50)) * 100
                                )}%`
                              }}
                            />
                          </div>
                          <div className="flex justify-between text-[8px] text-slate-700 mt-0.5 font-mono">
                            <span>{t.stop_loss_pct ?? -50}%</span>
                            <span>+{t.target_pct ?? 30}%</span>
                          </div>
                        </div>
                      </div>
                    ) : <span className="text-slate-700 text-[10px]">—</span>}
                  </td>
                  <td className="px-3 py-2 text-right">
                    {t.maturity ? (
                      <div className="flex flex-col items-end gap-0.5">
                        <span className={clsx('text-[10px] font-semibold',
                          t.maturity.status === 'trop_tot'   ? 'text-slate-500' :
                          t.maturity.status === 'debut'       ? 'text-yellow-400' :
                          t.maturity.status === 'mature'      ? 'text-emerald-400' :
                          'text-orange-400'
                        )}>
                          {t.maturity.emoji} {t.maturity.label}
                        </span>
                        <span className="text-[9px] text-slate-600 font-mono">
                          {t.days_held ?? 0}d / {t.horizon_days ?? 90}d ({t.maturity.ratio_pct}%)
                        </span>
                        <div className="w-16 h-1 bg-slate-700 rounded-full overflow-hidden">
                          <div
                            className={clsx('h-full rounded-full',
                              t.maturity.status === 'trop_tot'   ? 'bg-slate-600' :
                              t.maturity.status === 'debut'       ? 'bg-yellow-500' :
                              t.maturity.status === 'mature'      ? 'bg-emerald-500' :
                              'bg-orange-500'
                            )}
                            style={{ width: `${Math.min(t.maturity.ratio_pct, 100)}%` }}
                          />
                        </div>
                      </div>
                    ) : (
                      <span className="text-slate-700 text-[11px]">
                        {t.days_held != null ? `${t.days_held}d` : '—'}
                      </span>
                    )}
                  </td>
                  <td className="px-3 py-2 text-right">
                    <IvRankCell underlying={t.underlying} />
                  </td>
                  <td className="px-3 py-2 text-right">
                    <KellyCell patternId={t.pattern_id} />
                  </td>
                  <td className="px-3 py-2 text-right">
                    <PnlBadge pnl={t.pnl_pct} />
                  </td>
                  <td className="px-2 py-2" onClick={e => e.stopPropagation()}>
                    <button
                      onClick={() => setSelectedTradeId(isExpanded ? null : t.id)}
                      className={clsx(
                        'p-1 rounded transition-colors',
                        isExpanded
                          ? 'text-blue-400 bg-blue-900/30'
                          : 'text-slate-600 hover:text-blue-400 hover:bg-blue-900/20'
                      )}
                      title="Post-mortem IA"
                    >
                      {isExpanded ? <ChevronUp className="w-3.5 h-3.5" /> : <Search className="w-3.5 h-3.5" />}
                    </button>
                  </td>
                  <td className="px-2 py-2" onClick={e => e.stopPropagation()}>
                    <button
                      onClick={() => setClosingTrade(t)}
                      className={clsx(
                        'p-1 rounded transition-colors',
                        t.alert_type
                          ? 'text-amber-400 bg-amber-900/30 hover:bg-amber-900/50'
                          : 'text-slate-700 hover:text-amber-400 hover:bg-amber-900/20'
                      )}
                      title="Close trade"
                    >
                      <Lock className="w-3.5 h-3.5" />
                    </button>
                  </td>
                </tr>
                {isExpanded && (
                  <tr className="bg-dark-900/60">
                    <td colSpan={20} className="px-4 py-3 border-b border-blue-700/20 space-y-3">
                      <IBKRTicket
                        strategy={t.strategy ?? ''}
                        underlying={t.underlying}
                        strikeGuidance={t.strike_guidance}
                        expiryDays={t.expiry_days_at_entry ?? t.horizon_days}
                        entryPrice={t.entry_price}
                        maxLoss={t.max_loss_eur}
                        targetGain={t.target_gain_eur}
                      />
                      <PostmortemPanel tradeId={t.id} onClose={() => setSelectedTradeId(null)} />
                    </td>
                  </tr>
                )}
                </Fragment>
                )
              })}
            </tbody>
          </table>
        </div>
      )}

    </div>
  )
}

// ── Section 3 : Historique du score géopolitique ──────────────────────────────

function GeoHistorySection({ days }: { days: number }) {
  const { data, isLoading, refetch, isFetching } = useGeoHistory(days)
  const history: any[] = (data as any)?.history ?? []

  const maxScore = Math.max(...history.map((h: any) => h.geo_score), 1)

  return (
    <div className="space-y-3">
      <div className="flex items-center justify-between">
        <div className="text-xs font-semibold text-slate-500 uppercase tracking-wide">
          {history.length} alerts · last {days} days
        </div>
        <button onClick={() => refetch()} disabled={isFetching}
          className="text-slate-600 hover:text-slate-400 disabled:opacity-40">
          <RefreshCw className={clsx('w-3.5 h-3.5', isFetching && 'animate-spin')} />
        </button>
      </div>

      {isLoading ? (
        <div className="space-y-2">{[1,2].map(i => <div key={i} className="card h-12 animate-pulse bg-dark-700" />)}</div>
      ) : history.length === 0 ? (
        <div className="card text-center py-10 text-slate-600 text-sm">
          <AlertTriangle className="w-8 h-8 mx-auto mb-2 opacity-20" />
          No alerts — score patterns to start tracking
        </div>
      ) : (
        <div className="space-y-2">
          {history.map((entry: any) => {
            const score = entry.geo_score ?? 0
            const level = score >= 70 ? 'extreme' : score >= 50 ? 'high' : score >= 30 ? 'medium' : 'low'
            const barColor = { low: '#22c55e', medium: '#eab308', high: '#f97316', extreme: '#ef4444' }[level]
            const ts = entry.timestamp?.slice(0, 16).replace('T', ' ') ?? ''
            const patterns: any[] = entry.top_patterns ?? []

            return (
              <div key={entry.id} className="card">
                <div className="flex items-center gap-3 mb-2">
                  <div className="flex items-center gap-2 shrink-0">
                    <div className="w-10 h-10 rounded-lg flex items-center justify-center text-sm font-bold"
                      style={{ background: `${barColor}22`, color: barColor, border: `1px solid ${barColor}44` }}>
                      {score}
                    </div>
                    <div>
                      <div className="text-[10px] text-slate-600 uppercase">{level}</div>
                      <div className="text-[10px] text-slate-700">{ts}</div>
                    </div>
                  </div>
                  <div className="flex-1">
                    <div className="h-2 bg-dark-700 rounded-full overflow-hidden">
                      <div className="h-full rounded-full" style={{ width: `${(score / 100) * 100}%`, background: barColor }} />
                    </div>
                  </div>
                  <span className="text-[10px] text-slate-700 shrink-0">{entry.news_count} news</span>
                </div>
                {patterns.length > 0 && (
                  <div className="flex flex-wrap gap-1">
                    {patterns.slice(0, 5).map((p: any, i: number) => (
                      <span key={i} className="inline-flex items-center gap-1 text-[10px] bg-dark-700 text-slate-400 rounded px-1.5 py-0.5">
                        <span className="font-mono text-slate-500">{p.score}</span>
                        <span className="max-w-[120px] truncate">{p.name || p.pattern_id}</span>
                      </span>
                    ))}
                  </div>
                )}
              </div>
            )
          })}
        </div>
      )}
    </div>
  )
}

// ── Section 4 : Cycles d'intelligence ────────────────────────────────────────

function CyclesSection() {
  const { data: histData, isLoading, refetch, isFetching } = useCycleHistory(20)
  const { data: statusData } = useCycleStatus()
  const { mutate: triggerCycle, isPending: triggering } = useTriggerCycle()
  const runs: any[] = (histData as any)?.runs ?? []
  const cs = statusData as any

  // Auto-refetch history list when the running cycle finishes
  const wasRunning = useRef(false)
  useEffect(() => {
    if (cs?.running) { wasRunning.current = true }
    else if (wasRunning.current) { wasRunning.current = false; refetch() }
  }, [cs?.running])

  return (
    <div className="space-y-3">
      <div className="flex items-center justify-between">
        <div className="text-xs font-semibold text-slate-500 uppercase tracking-wide">
          {runs.length} cycles · {cs?.enabled ? `auto ${cs.interval_hours}h` : 'manual only'}
        </div>
        <div className="flex gap-2">
          <button
            onClick={() => triggerCycle(undefined, { onSuccess: () => setTimeout(() => refetch(), 3000) })}
            disabled={triggering}
            className="flex items-center gap-1 text-xs border border-blue-500/40 text-blue-400 hover:bg-blue-900/20 px-2.5 py-1 rounded disabled:opacity-40">
            <Zap className={clsx('w-3 h-3', triggering && 'animate-pulse')} />
            {triggering ? 'Launching...' : 'Run a cycle'}
          </button>
          <button onClick={() => refetch()} disabled={isFetching}
            className="text-slate-600 hover:text-slate-400 disabled:opacity-40">
            <RefreshCw className={clsx('w-3.5 h-3.5', isFetching && 'animate-spin')} />
          </button>
        </div>
      </div>

      {isLoading ? (
        <div className="space-y-2">{[1,2,3].map(i => <div key={i} className="card h-20 animate-pulse bg-dark-700" />)}</div>
      ) : runs.length === 0 ? (
        <div className="card text-center py-10 text-slate-600 text-sm">
          <Zap className="w-8 h-8 mx-auto mb-2 opacity-20" />
          No cycles — enable auto-cycle in Configuration or run manually
        </div>
      ) : (
        <div className="space-y-3">
          {runs.map((run: any) => {
            const commentary = run.commentary_parsed
            const ok = run.status === 'completed'
            const ts = run.started_at?.slice(0, 16).replace('T', ' ') ?? ''
            const duration = run.completed_at
              ? Math.round((new Date(run.completed_at).getTime() - new Date(run.started_at).getTime()) / 1000)
              : null

            return (
              <div key={run.id} className={clsx('card', ok ? 'border-slate-700/40' : 'border-red-800/30')}>
                <div className="flex items-start gap-3 mb-2">
                  {ok
                    ? <CheckCircle className="w-4 h-4 text-emerald-400 shrink-0 mt-0.5" />
                    : <XCircle className="w-4 h-4 text-red-400 shrink-0 mt-0.5" />}
                  <div className="flex-1 min-w-0">
                    <div className="flex items-center gap-2 flex-wrap">
                      <span className="text-xs text-slate-300 font-semibold">{ts} UTC</span>
                      <span className={clsx('badge text-[10px]', run.trigger === 'manual' ? 'badge-blue' : 'badge-purple')}>
                        {run.trigger === 'manual' ? 'Manual' : `Auto ${cs?.interval_hours ?? ''}h`}
                      </span>
                      {run.dominant_regime && <ScenarioBadge dominant={run.dominant_regime} />}
                      {duration != null && <span className="text-[10px] text-slate-600">{duration}s</span>}
                    </div>
                    <div className="flex gap-3 mt-1 text-[11px] text-slate-500 flex-wrap">
                      <span>💡 {run.patterns_suggested} suggested</span>
                      <span>✚ {run.patterns_added} added</span>
                      <span>🎯 {run.patterns_scored} scored</span>
                      {run.geo_score != null && <span>🌐 Geo {run.geo_score}/100</span>}
                    </div>
                  </div>
                </div>

                {commentary && (
                  <div className="bg-blue-900/10 border border-blue-700/20 rounded p-3 space-y-2">
                    <div className="flex items-center gap-1.5 text-[10px] text-blue-400 font-semibold uppercase tracking-wide">
                      <Brain className="w-3 h-3" /> AI Comment
                    </div>
                    <p className="text-xs text-slate-300 leading-relaxed">{commentary.commentary}</p>
                    {commentary.key_risk && (
                      <div className="flex items-start gap-1.5 text-[11px] text-orange-400/80 bg-orange-900/10 border border-orange-700/20 rounded px-2 py-1">
                        <span className="shrink-0">⚠</span> {commentary.key_risk}
                      </div>
                    )}
                    {commentary.top_pattern && (
                      <div className="text-[11px] text-emerald-400/80">
                        🎯 Key pattern: <span className="font-semibold">{commentary.top_pattern}</span>
                      </div>
                    )}
                    {commentary.lessons_from_report ? (
                      <div className="flex items-center gap-1.5 text-[10px] text-purple-400/80 bg-purple-900/10 border border-purple-700/20 rounded px-2 py-1">
                        <BookOpen className="w-3 h-3 shrink-0" />
                        Lessons from the {commentary.lessons_from_report} report integrated in this cycle
                        {commentary.lessons_headline && (
                          <span className="text-slate-600 ml-1">· {commentary.lessons_headline}</span>
                        )}
                      </div>
                    ) : (
                      <div className="flex items-center gap-1.5 text-[10px] text-slate-700 italic">
                        <BookOpen className="w-3 h-3 shrink-0" />
                        No performance report available — generate a report in "AI Report"
                      </div>
                    )}
                  </div>
                )}

                {!commentary && ok && (
                  <div className="text-[11px] text-slate-700 italic">No AI comment generated for this cycle</div>
                )}
              </div>
            )
          })}
        </div>
      )}
    </div>
  )
}

// ── Page principale ────────────────────────────────────────────────────────────

function SimPortfolioRiskPanel() {
  const { data, isLoading, refetch } = useSimPortfolioRisk()
  const risk = data as any

  if (isLoading) {
    return (
      <div className="card animate-pulse">
        <div className="h-5 bg-dark-700 rounded w-48 mb-4" />
        <div className="space-y-2">{[1, 2, 3].map(i => <div key={i} className="h-8 bg-dark-700 rounded" />)}</div>
      </div>
    )
  }

  if (!risk || risk.open_count === 0) {
    return (
      <div className="card text-center py-8 text-slate-500">
        <PieChart className="w-8 h-8 mx-auto mb-2 opacity-20" />
        <div className="text-sm">No open positions in the simulated portfolio</div>
        <div className="text-xs mt-1">Logged trades will appear here after the next cycle</div>
      </div>
    )
  }

  const concentration: Record<string, any> = risk.concentration ?? {}
  const alerts: any[] = risk.alerts ?? []
  const conflicts: any[] = risk.conflicts ?? []
  const aiMonitor: any = risk.ai_monitor
  const aiTs: string = risk.ai_monitor_ts

  const dangers = alerts.filter((a: any) => a.level === 'danger')
  const warnings = alerts.filter((a: any) => a.level === 'warning')

  return (
    <div className="space-y-3">
      {/* Header */}
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-2">
          <PieChart className="w-4 h-4 text-blue-400" />
          <span className="text-sm font-semibold text-white">Simulated Portfolio — Risk Analysis</span>
          <span className="text-xs text-slate-500">{risk.open_count} open positions</span>
          {dangers.length > 0 && (
            <span className="inline-flex items-center gap-1 text-[10px] font-bold bg-red-900/30 border border-red-600/40 text-red-400 rounded px-1.5 py-0.5">
              <ShieldAlert className="w-3 h-3" /> {dangers.length} CONFLICT{dangers.length > 1 ? 'S' : ''}
            </span>
          )}
        </div>
        <button onClick={() => refetch()} className="text-slate-600 hover:text-slate-400 transition-colors">
          <RefreshCw className="w-3.5 h-3.5" />
        </button>
      </div>

      {/* Asset class concentration bars */}
      <div className="card">
        <div className="text-xs text-slate-500 mb-3 font-semibold uppercase tracking-wide">Breakdown by asset class</div>
        <div className="space-y-2">
          {Object.entries(concentration)
            .sort(([, a]: any, [, b]: any) => b.pct - a.pct)
            .map(([ac, data]: [string, any]) => {
              const color = ASSET_CLASS_COLORS[ac] ?? ASSET_CLASS_COLORS.unknown
              const exposure = risk.direction_exposure?.[ac] ?? {}
              return (
                <div key={ac}>
                  <div className="flex items-center justify-between mb-1">
                    <div className="flex items-center gap-2">
                      <span className="text-xs font-semibold w-20 capitalize" style={{ color }}>{ac}</span>
                      <span className="text-[10px] text-slate-500">{data.tickers?.slice(0, 3).join(', ')}{data.tickers?.length > 3 ? '…' : ''}</span>
                    </div>
                    <div className="flex items-center gap-2 text-[10px]">
                      {exposure.bullish > 0 && (
                        <span className="text-emerald-400 flex items-center gap-0.5">
                          <TrendingUp className="w-2.5 h-2.5" /> {exposure.bullish}
                        </span>
                      )}
                      {exposure.bearish > 0 && (
                        <span className="text-red-400 flex items-center gap-0.5">
                          <TrendingDown className="w-2.5 h-2.5" /> {exposure.bearish}
                        </span>
                      )}
                      <span className="text-slate-400 font-mono font-bold">{data.pct}%</span>
                      <span className="text-slate-600">({data.count})</span>
                    </div>
                  </div>
                  <div className="h-1.5 bg-dark-700 rounded-full overflow-hidden">
                    <div
                      className="h-full rounded-full transition-all"
                      style={{ width: `${data.pct}%`, background: `${color}cc` }}
                    />
                  </div>
                </div>
              )
            })}
        </div>
      </div>

      {/* Alerts */}
      {alerts.length > 0 && (
        <div className="space-y-2">
          {/* Conflicts */}
          {conflicts.map((c: any, i: number) => (
            <div key={i} className="card border-red-700/40 bg-red-900/10">
              <div className="flex items-start gap-2">
                <ShieldAlert className="w-4 h-4 text-red-400 shrink-0 mt-0.5" />
                <div className="flex-1 min-w-0">
                  <div className="text-xs font-semibold text-red-300 mb-1">
                    Directional conflict — {c.underlying}
                  </div>
                  <div className="space-y-0.5">
                    {c.trades.map((t: any) => (
                      <div key={t.id} className="flex items-center gap-2 text-[11px]">
                        <span className={clsx('font-bold font-mono',
                          t.direction === 'bullish' ? 'text-emerald-400' : 'text-red-400')}>
                          {t.direction === 'bullish' ? '▲' : '▼'} #{t.id}
                        </span>
                        <span className="text-slate-400">{t.strategy}</span>
                        <span className="text-slate-600">{t.entry_date}</span>
                        {t.pattern_name && (
                          <span className="text-slate-600 truncate max-w-[180px]">{t.pattern_name}</span>
                        )}
                      </div>
                    ))}
                  </div>
                </div>
              </div>
            </div>
          ))}

          {/* Concentration & overweight warnings */}
          {warnings.length > 0 && (
            <div className="card border-amber-700/30 bg-amber-900/10">
              <div className="text-xs font-semibold text-amber-300 mb-1.5 flex items-center gap-1">
                <AlertTriangle className="w-3.5 h-3.5" /> Concentration alerts
              </div>
              <div className="space-y-1">
                {warnings.map((a: any, i: number) => (
                  <div key={i} className="text-[11px] text-amber-200/80 flex items-start gap-1.5">
                    <span className="text-amber-500 shrink-0">•</span>
                    {a.message}
                  </div>
                ))}
              </div>
            </div>
          )}
        </div>
      )}

      {/* AI Monitor recommendations */}
      {aiMonitor && (
        <div className="card border-blue-700/30 bg-blue-900/10">
          <div className="flex items-center justify-between mb-2">
            <div className="text-xs font-semibold text-blue-300 flex items-center gap-1.5">
              <Brain className="w-3.5 h-3.5" /> AI Recommendations — Portfolio Monitor
            </div>
            {aiTs && (
              <span className="text-[10px] text-slate-600">{aiTs.slice(0, 16).replace('T', ' ')}</span>
            )}
          </div>
          {aiMonitor.assessment && (
            <p className="text-xs text-slate-300 mb-2">{aiMonitor.assessment}</p>
          )}
          {aiMonitor.actions?.length > 0 && (
            <div className="space-y-1 mb-2">
              {aiMonitor.actions.map((action: any, i: number) => (
                <div key={i} className={clsx(
                  'flex items-start gap-2 text-[11px] rounded px-2 py-1',
                  action.priority === 'high'
                    ? 'bg-red-900/20 border border-red-700/20 text-red-300'
                    : 'bg-slate-800/40 border border-slate-700/20 text-slate-300'
                )}>
                  <span className="shrink-0 font-bold">
                    {action.type === 'close_trade' ? '🔒' : action.type === 'rebalance' ? '⚖️' : '👁'}
                  </span>
                  <div>
                    {action.underlying && <span className="font-mono font-bold mr-1">{action.underlying}</span>}
                    {action.trade_id && <span className="text-slate-500 mr-1">#{action.trade_id}</span>}
                    {action.reason}
                  </div>
                </div>
              ))}
            </div>
          )}
          {aiMonitor.rebalance_suggestion && (
            <div className="text-[11px] text-blue-300/70 border-t border-blue-700/20 pt-2 mt-1">
              ⚖️ {aiMonitor.rebalance_suggestion}
            </div>
          )}
        </div>
      )}

      {alerts.length === 0 && (
        <div className="card border-emerald-700/30 bg-emerald-900/10 text-center py-3">
          <CheckCircle className="w-5 h-5 text-emerald-400 mx-auto mb-1" />
          <div className="text-xs text-emerald-300">Balanced portfolio — no conflicts or over-concentration detected</div>
        </div>
      )}
    </div>
  )
}

const TABS = [
  { key: 'cycles', label: 'AI Cycles', icon: Zap },
  { key: 'macro', label: 'Macro Regimes', icon: Activity },
  { key: 'ideas', label: 'Trade Ideas', icon: Target },
  { key: 'mtm', label: 'Open', icon: TrendingUp },
  { key: 'closed', label: 'Closed', icon: Lock },
  { key: 'geo', label: 'Geo Alerts', icon: AlertTriangle },
  { key: 'skipped', label: 'Not logged', icon: XCircle },
] as const

function SkippedTradesSection({ days }: { days: number }) {
  const { data, isLoading } = useSkippedTrades(days)
  const allTrades: any[] = (data as any)?.trades ?? []

  const [search, setSearch] = useState('')
  const [assetClass, setAssetClass] = useState('all')
  const [reasonFilter, setReasonFilter] = useState('all')

  const ASSET_CLASS_BADGE: Record<string, string> = {
    energy: 'bg-orange-900/30 text-orange-300 border-orange-700/30',
    metals: 'bg-yellow-900/30 text-yellow-300 border-yellow-700/30',
    agriculture: 'bg-green-900/30 text-green-300 border-green-700/30',
    indices: 'bg-blue-900/30 text-blue-300 border-blue-700/30',
    forex: 'bg-purple-900/30 text-purple-300 border-purple-700/30',
    rates: 'bg-slate-800/60 text-slate-300 border-slate-600/30',
    equities: 'bg-cyan-900/30 text-cyan-300 border-cyan-700/30',
  }

  const allReasons = Array.from(new Set(allTrades.map((t: any) => t.skip_reason).filter(Boolean)))

  const trades = allTrades.filter((t: any) => {
    const q = search.toLowerCase()
    if (q && !`${t.underlying} ${t.strategy ?? ''} ${t.pattern_name ?? ''}`.toLowerCase().includes(q)) return false
    if (assetClass !== 'all' && _normalizeAssetClass(t.asset_class, t.underlying) !== assetClass) return false
    if (reasonFilter !== 'all' && t.skip_reason !== reasonFilter) return false
    return true
  })

  const byReason = allTrades.reduce((acc: Record<string, number>, t: any) => {
    acc[t.skip_reason] = (acc[t.skip_reason] ?? 0) + 1
    return acc
  }, {})

  if (isLoading) return <div className="card animate-pulse h-24" />

  if (allTrades.length === 0) {
    return (
      <div className="card text-center py-8 text-slate-500 text-sm">
        <XCircle className="w-6 h-6 mx-auto mb-2 text-slate-600" />
        No unlogged suggestions in the last {days}d — all scored trades match at least one risk profile.
      </div>
    )
  }

  return (
    <div className="space-y-4">
      <div className="card">
        <div className="section-title flex items-center gap-1 mb-3">
          <XCircle className="w-3 h-3 text-amber-400" />
          Suggested trades not logged — {trades.length}/{allTrades.length} over {days}d
          <span className="ml-2 text-slate-600 font-normal text-xs">
            (score or gain insufficient for any active profile)
          </span>
        </div>

        {/* Reason summary chips */}
        <div className="flex gap-3 mb-4 flex-wrap">
          {Object.entries(byReason).map(([reason, count]) => (
            <div key={reason} className="badge badge-yellow text-[10px]">
              {reason}: {count}
            </div>
          ))}
        </div>

        {/* Filters */}
        <div className="flex items-center gap-2 flex-wrap mb-4">
          <FilterBar
            search={search} onSearch={setSearch}
            assetClass={assetClass} onAssetClass={setAssetClass}
          />
          {/* Reason filter */}
          {allReasons.length > 1 && (
            <div className="flex items-center gap-0.5 bg-dark-700 rounded p-0.5">
              <button onClick={() => setReasonFilter('all')}
                className={clsx('px-2 py-1 rounded text-xs transition-colors',
                  reasonFilter === 'all' ? 'bg-slate-600 text-white' : 'text-slate-400 hover:text-slate-200')}>
                All
              </button>
              {allReasons.map(r => (
                <button key={r} onClick={() => setReasonFilter(r)}
                  className={clsx('px-2 py-1 rounded text-xs transition-colors',
                    reasonFilter === r ? 'bg-slate-600 text-white' : 'text-slate-400 hover:text-slate-200')}>
                  {r}
                </button>
              ))}
            </div>
          )}
        </div>

        {trades.length === 0 ? (
          <div className="text-center py-6 text-slate-600 text-sm">No results for these filters</div>
        ) : (
          <div className="overflow-x-auto rounded-lg border border-slate-700/40">
            <table className="w-full text-xs">
              <thead>
                <tr className="border-b border-slate-700/60 text-slate-600 text-[10px] uppercase tracking-wide">
                  <th className="pl-3 py-2 text-left">Pattern</th>
                  <th className="px-2 py-2 text-left">Ticker</th>
                  <th className="px-2 py-2 text-left">Strategy</th>
                  <th className="px-2 py-2 text-right">Score</th>
                  <th className="px-2 py-2 text-right">Expected gain</th>
                  <th className="px-2 py-2 text-left">Class</th>
                  <th className="pr-3 py-2 text-left">Skip reason</th>
                </tr>
              </thead>
              <tbody className="divide-y divide-slate-800/40">
                {trades.map((t: any) => (
                  <tr key={t.id} className="hover:bg-dark-700/30">
                    <td className="pl-3 py-2 text-slate-300 max-w-[140px] truncate">{t.pattern_name || '—'}</td>
                    <td className="px-2 py-2 font-mono text-slate-400">{t.underlying}</td>
                    <td className="px-2 py-2 text-slate-400">{t.strategy || '—'}</td>
                    <td className={clsx('px-2 py-2 text-right font-bold font-mono',
                      t.score >= 50 ? 'text-emerald-400' : t.score >= 25 ? 'text-yellow-400' : 'text-slate-600')}>
                      {t.score ?? '—'}
                    </td>
                    <td className="px-2 py-2 text-right text-slate-400">
                      {t.expected_move_pct != null ? `${t.expected_move_pct.toFixed(0)}%` : '—'}
                    </td>
                    <td className="px-2 py-2">
                      {t.asset_class ? (
                        <span className={clsx('badge text-[10px] border', ASSET_CLASS_BADGE[t.asset_class] ?? 'badge-blue')}>
                          {t.asset_class}
                        </span>
                      ) : <span className="text-slate-600">—</span>}
                    </td>
                    <td className="pr-3 py-2 text-slate-600 max-w-[200px] truncate" title={t.skip_detail}>
                      {t.skip_detail || t.skip_reason}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </div>
    </div>
  )
}

export default function JournalDeBord() {
  const [tab, setTab] = useState<'cycles' | 'macro' | 'ideas' | 'mtm' | 'closed' | 'geo' | 'skipped'>('cycles')
  const [days, setDays] = useState(15)
  const [confirmReset, setConfirmReset] = useState(false)
  const [resetting, setResetting] = useState(false)
  const [resetMsg, setResetMsg] = useState('')
  const { data: summary, refetch: refetchSummary } = useJournalSummary()
  const { data: riskData } = useSimPortfolioRisk()
  const riskAlertCount = (riskData as any)?.alerts?.filter((a: any) => a.level === 'danger').length ?? 0
  const qc = useQueryClient()

  const s = summary as any

  const handleReset = async () => {
    if (!confirmReset) {
      setConfirmReset(true)
      return
    }
    setResetting(true)
    try {
      await api.delete('/journal/reset')
      setResetMsg('Journal reset')
      setConfirmReset(false)
      // Invalidate all journal queries
      await qc.invalidateQueries({ queryKey: ['journal-summary'] })
      await qc.invalidateQueries({ queryKey: ['macro-history'] })
      await qc.invalidateQueries({ queryKey: ['geo-history'] })
      await qc.invalidateQueries({ queryKey: ['trade-mtm'] })
      await qc.invalidateQueries({ queryKey: ['cycle-history'] })
      setTimeout(() => setResetMsg(''), 3000)
    } catch {
      setResetMsg('Reset error')
      setTimeout(() => setResetMsg(''), 3000)
    } finally {
      setResetting(false)
    }
  }

  return (
    <div className="p-6 space-y-5">
      {/* Header */}
      <div className="flex items-start justify-between">
        <div>
          <h1 className="text-xl font-bold text-white flex items-center gap-2">
            <BookOpen className="w-5 h-5 text-blue-400" /> Trading Journal
          </h1>
          <p className="text-xs text-slate-500 mt-0.5">
            Macro regime history · Trade mark-to-market · Geopolitical risk evolution
          </p>
        </div>

        <div className="flex items-center gap-3">
          {/* Reset button */}
          <div className="flex items-center gap-2">
            {resetMsg && (
              <span className={clsx('text-xs', resetMsg.includes('Erreur') ? 'text-red-400' : 'text-emerald-400')}>
                {resetMsg}
              </span>
            )}
            {confirmReset && !resetting && (
              <span className="text-xs text-amber-400">Confirm?</span>
            )}
            <button
              onClick={confirmReset ? handleReset : () => setConfirmReset(true)}
              disabled={resetting}
              onBlur={() => setTimeout(() => setConfirmReset(false), 300)}
              className={clsx(
                'flex items-center gap-1.5 px-3 py-1.5 rounded text-xs font-semibold border transition-all disabled:opacity-40',
                confirmReset
                  ? 'bg-red-900/30 border-red-600/50 text-red-400 hover:bg-red-900/50'
                  : 'border-slate-700/40 text-slate-600 hover:text-slate-400 hover:border-slate-600'
              )}>
              <Trash2 className="w-3.5 h-3.5" />
              {resetting ? 'Resetting...' : confirmReset ? 'Clear all' : 'Reset journal'}
            </button>
          </div>

          {/* Period selector */}
          <div className="flex gap-1 bg-dark-700 p-1 rounded text-xs">
            {[15, 30, 60, 90].map(d => (
              <button key={d} onClick={() => setDays(d)}
                className={clsx('px-2.5 py-1 rounded transition-colors', {
                  'bg-blue-600 text-white': days === d,
                  'text-slate-400 hover:text-slate-200': days !== d,
                })}>
                {d}d
              </button>
            ))}
          </div>
        </div>
      </div>

      {/* Summary cards */}
      {s && (
        <div className="grid grid-cols-4 gap-3">
          <div className="card text-center">
            <div className="text-2xl font-bold text-white">{s.macro_snapshots ?? 0}</div>
            <div className="text-xs text-slate-600 mt-0.5">macro snapshots</div>
            {s.current_dominant && (
              <div className="mt-1"><ScenarioBadge dominant={s.current_dominant} /></div>
            )}
          </div>
          <div className="card text-center">
            <div className="text-2xl font-bold text-white">{s.regime_transitions?.length ?? 0}</div>
            <div className="text-xs text-slate-600 mt-0.5">regime transitions</div>
            {s.regime_transitions?.length > 0 && (
              <div className="text-[10px] text-amber-400 mt-1">
                ↕ {s.regime_transitions[0].from} → {s.regime_transitions[0].to}
              </div>
            )}
          </div>
          <div className="card text-center">
            <div className={clsx('text-2xl font-bold',
              (s.avg_geo_score ?? 0) >= 70 ? 'text-red-400' : (s.avg_geo_score ?? 0) >= 40 ? 'text-orange-400' : 'text-emerald-400')}>
              {s.avg_geo_score != null ? s.avg_geo_score.toFixed(0) : '—'}
            </div>
            <div className="text-xs text-slate-600 mt-0.5">avg geo score</div>
            {s.max_geo_score != null && (
              <div className="text-[10px] text-slate-600 mt-1">max {s.max_geo_score}</div>
            )}
          </div>
          <div className="card text-center">
            <div className="text-2xl font-bold text-white">{s.trade_entries_logged ?? 0}</div>
            <div className="text-xs text-slate-600 mt-0.5">logged trades</div>
          </div>
          {riskAlertCount > 0 && (
            <div className="card text-center border-red-700/40 bg-red-900/10 col-span-full">
              <div className="flex items-center justify-center gap-2">
                <ShieldAlert className="w-4 h-4 text-red-400" />
                <span className="text-sm font-semibold text-red-300">
                  {riskAlertCount} directional conflict{riskAlertCount > 1 ? 's' : ''} detected
                </span>
                <span className="text-xs text-slate-500">— see Risk Dashboard → Simulated</span>
              </div>
            </div>
          )}
        </div>
      )}

      {/* Tabs */}
      <div className="flex gap-1 bg-dark-700 p-1 rounded w-fit">
        {TABS.map(({ key, label, icon: Icon }) => (
          <button key={key} onClick={() => setTab(key as any)}
            className={clsx('flex items-center gap-1.5 px-3 py-1.5 rounded text-sm transition-colors', {
              'bg-blue-600 text-white': tab === key,
              'text-slate-400 hover:text-slate-200': tab !== key,
            })}>
            <Icon className="w-3.5 h-3.5" />
            {label}
          </button>
        ))}
      </div>

      {/* Content */}
      {tab === 'cycles' && <CyclesSection />}
      {tab === 'macro' && <MacroHistorySection days={days} />}
      {tab === 'ideas' && <TradeIdeasTab />}
      {tab === 'mtm' && <TradeMtmSection days={days} />}
      {tab === 'closed' && <ClosedTradesSection days={days} />}
      {tab === 'geo' && <GeoHistorySection days={days} />}
      {tab === 'skipped' && <SkippedTradesSection days={days} />}
    </div>
  )
}
