import { useMemo, useState } from 'react'
import { useQuery } from '@tanstack/react-query'
import {
  useGeoRiskScore, useAllQuotes,
  useEcoCalendar, usePortfolioSummary, useLastScores, useAllPatterns, useMacroRegime,
  useTradeMtm, useRiskDashboard, useGeoNews,
  useSimPortfolioRisk, useCycleStatus, useClosedTrades,
  useInstrumentsWatchlist, useInstrumentsWatchlistQuotes, useIvBatch, useLatestCycleReport,
} from '../hooks/useApi'
import { Clock, Globe, ShieldAlert, ArrowUpRight, Newspaper } from 'lucide-react'
import { Link } from 'react-router-dom'
import clsx from 'clsx'
import type { Quote } from '../types'
import { format } from 'date-fns'
import { fr } from 'date-fns/locale'
import {
  RadarChart, PolarGrid, PolarAngleAxis, Radar, ResponsiveContainer,
  AreaChart, Area, XAxis, YAxis, Tooltip, CartesianGrid,
  PieChart, Pie, Cell, BarChart, Bar, ReferenceLine,
} from 'recharts'
import { scoreColor } from '../components/TradeIdeas'
import { ASSET_CLASS_COLORS } from '../constants/assetColors'
import TradeRankList from '../components/TradeRankList'

const riskGauge = (score: number) => {
  if (score < 25) return { color: 'text-emerald-400', bg: 'bg-emerald-500', label: 'LOW' }
  if (score < 50) return { color: 'text-yellow-400', bg: 'bg-yellow-500', label: 'MODERATE' }
  if (score < 75) return { color: 'text-orange-400', bg: 'bg-orange-500', label: 'HIGH' }
  return { color: 'text-red-400', bg: 'bg-red-500', label: 'EXTREME' }
}

const assetEmoji: Record<string, string> = {
  energy: '⛽', metals: '🥇', agriculture: '🌾', equities: '📈',
  indices: '📊', forex: '💱', crypto: '₿', rates: '📉',
}

const REGIME_LABELS: Record<string, string> = {
  goldilocks: 'Goldilocks', desinflation: 'Disinflation', stagflation: 'Stagflation',
  recession: 'Recession', crise_liquidite: 'Liq. Crisis', reflation: 'Reflation',
  soft_landing: 'Soft Landing', inflation_shock: 'Infl. Shock', incertain: 'Uncertain',
}

const CURRENCY_FLAGS: Record<string, string> = {
  USD: '🇺🇸', EUR: '🇪🇺', GBP: '🇬🇧', JPY: '🇯🇵',
  AUD: '🇦🇺', CAD: '🇨🇦', NZD: '🇳🇿', CHF: '🇨🇭', CNY: '🇨🇳',
}

const IMPACT_DOT: Record<string, string> = {
  high: 'bg-red-500', medium: 'bg-yellow-400', low: 'bg-slate-400',
}

const isTodayISO = (dateStr: string) => {
  const t = new Date()
  const utc = `${t.getUTCFullYear()}-${String(t.getUTCMonth() + 1).padStart(2, '0')}-${String(t.getUTCDate()).padStart(2, '0')}`
  return dateStr === utc
}

const formatDateShort = (dateStr: string) => {
  const d = new Date(dateStr + 'T00:00:00Z')
  return d.toLocaleDateString('fr-FR', { weekday: 'short', day: 'numeric', month: 'short', timeZone: 'UTC' })
}

function ViewToggle({ value, onChange }: { value: 'simulated' | 'portfolio'; onChange: (v: 'simulated' | 'portfolio') => void }) {
  const click = (v: 'simulated' | 'portfolio') => (e: React.MouseEvent) => {
    e.preventDefault(); e.stopPropagation(); onChange(v)
  }
  return (
    <div className="flex gap-0.5 bg-dark-800 rounded p-0.5 text-[9px]">
      <button onClick={click('simulated')}
        className={clsx('px-1.5 py-0.5 rounded transition-colors',
          value === 'simulated' ? 'bg-blue-600 text-white' : 'text-slate-600 hover:text-slate-400')}>
        Simulated
      </button>
      <button onClick={click('portfolio')}
        className={clsx('px-1.5 py-0.5 rounded transition-colors',
          value === 'portfolio' ? 'bg-blue-600 text-white' : 'text-slate-600 hover:text-slate-400')}>
        Portfolio
      </button>
    </div>
  )
}

function QuoteRow({ q }: { q: Quote }) {
  if (!q.price) return null
  const pos = q.change_pct >= 0
  return (
    <div className="flex items-center justify-between py-1.5 border-b border-slate-700/20 last:border-0">
      <span className="text-xs text-white truncate max-w-[140px]">{q.name || q.symbol}</span>
      <div className="text-right ml-2">
        <div className="text-xs text-white font-mono">{q.price.toFixed(2)}</div>
        <div className={clsx('text-xs font-mono', pos ? 'positive' : 'negative')}>
          {pos ? '+' : ''}{q.change_pct.toFixed(2)}%
        </div>
      </div>
    </div>
  )
}

export default function Dashboard() {
  const { data: riskScore, isLoading: riskLoading } = useGeoRiskScore()
  const { data: allQuotes } = useAllQuotes()
  const { data: ecoCalendarData } = useEcoCalendar({ period: 'recent', limit: 30 })
  const { data: portfolio } = usePortfolioSummary()
  const { data: lastScoresData } = useLastScores()
  const { data: allPatternsData } = useAllPatterns()
  const { data: macroData } = useMacroRegime()
  const { data: tradeMtmData } = useTradeMtm(30)
  const { data: closedTradesData } = useClosedTrades(90)
  const { data: riskDashboard } = useRiskDashboard()
  const { data: simRisk } = useSimPortfolioRisk()
  const { data: cycleStatusData } = useCycleStatus()
  const { data: geoNews } = useGeoNews()
  const { data: watchlistItems } = useInstrumentsWatchlist()
  const { data: watchlistQuotesData } = useInstrumentsWatchlistQuotes()
  const { data: latestCycleReportData } = useLatestCycleReport()
  const watchlistTickers: string[] = (watchlistItems ?? []).map((w: any) => w.ticker)
  const { data: ivBatchData } = useIvBatch(watchlistTickers.join(','))

  // Historical PnL curve + latest VaR snapshot
  const { data: pnlHistoryData } = useQuery({
    queryKey: ['dash-pnl-history'],
    queryFn: () => fetch('/api/var/pnl/snapshots?limit=200').then(r => r.ok ? r.json() : { snapshots: [] }),
    staleTime: 120_000,
    retry: 1,
  })
  const { data: latestVarData } = useQuery({
    queryKey: ['dash-var-latest'],
    queryFn: () => fetch('/api/var/latest').then(r => r.ok ? r.json() : { snapshot: null }),
    staleTime: 120_000,
    retry: 1,
  })

  const [pnlView, setPnlView] = useState<'simulated' | 'portfolio'>(() =>
    (localStorage.getItem('dash_pnl_view') as any) ?? 'simulated'
  )
  const [riskView, setRiskView] = useState<'simulated' | 'portfolio'>(() =>
    (localStorage.getItem('dash_risk_view') as any) ?? 'simulated'
  )

  const setPnlViewPersist = (v: 'simulated' | 'portfolio') => {
    setPnlView(v); localStorage.setItem('dash_pnl_view', v)
  }
  const setRiskViewPersist = (v: 'simulated' | 'portfolio') => {
    setRiskView(v); localStorage.setItem('dash_risk_view', v)
  }

  const allPatterns: any[] = allPatternsData ?? []

  const scoreMap = useMemo(() => {
    const map: Record<string, any> = {}
    for (const sp of (lastScoresData?.scored_patterns ?? [])) {
      if (sp.pattern_id) map[sp.pattern_id] = sp
    }
    return map
  }, [lastScoresData])

  const macroInfo = useMemo(() => {
    if (!macroData?.scenarios) return null
    const sc = macroData.scenarios
    const dom = sc.dominant ?? 'incertain'
    const m = sc.meta?.[dom] ?? { label: dom, color: '#94a3b8', emoji: '?' }
    const assetBias: Record<string, string> = sc.asset_bias?.[dom] ?? {}
    // Top 3 scenario scores (excluding dominant, sorted desc)
    const ranked: [string, number][] = (sc.ranked ?? []).slice(0, 4)
    return { dominant: dom, label: m.label, color: m.color, emoji: m.emoji, assetBias, ranked }
  }, [macroData])

  const gauge = riskScore ? riskGauge(riskScore.score) : null

  const lastCycle = (cycleStatusData as any)?.last_cycle ?? null
  const mtmTrades: any[] = (tradeMtmData as any)?.trades ?? []

  // Patterns from the last cycle only (filter by created_at >= cycle started_at)
  const cyclePatterns = useMemo(() => {
    const started = lastCycle?.started_at ?? null
    if (!started) return []
    return [...allPatterns]
      .filter(p => p.created_at && p.created_at >= started)
      .sort((a, b) => (scoreMap[b.id]?.score ?? -1) - (scoreMap[a.id]?.score ?? -1))
      .slice(0, 4)
  }, [allPatterns, scoreMap, lastCycle])

  // Top impactful news (fills the Geopolitical Risk card's available height, no fixed cap)
  const topNews = useMemo(() =>
    [...(geoNews ?? [])]
      .sort((a, b) => b.impact_score - a.impact_score)
      .slice(0, 30)
  , [geoNews])

  // Watchlist radar: change_pct normalized to a 0-100 scale (50 = flat)
  const watchlistRadarData = useMemo(() => {
    const items: any[] = (watchlistQuotesData as any)?.items ?? []
    return items.slice(0, 8).map((it: any) => {
      const chg = Math.max(-5, Math.min(5, it.change_pct ?? 0))
      return { subject: it.ticker, value: 50 + chg * 10, ref: 50 }
    })
  }, [watchlistQuotesData])

  // Upcoming FF economic events, chronological, grouped by date (fills available height, no fixed cap)
  const upcomingEventsGrouped = useMemo(() => {
    const events: any[] = (ecoCalendarData as any)?.events ?? []
    const todayISO = new Date().toISOString().slice(0, 10)
    const sorted = [...events]
      .filter((ev: any) => ev.event_date >= todayISO)
      .sort((a: any, b: any) => `${a.event_date}${a.event_time ?? ''}`.localeCompare(`${b.event_date}${b.event_time ?? ''}`))
    const groups: { date: string; events: any[] }[] = []
    for (const ev of sorted) {
      const last = groups[groups.length - 1]
      if (!last || last.date !== ev.event_date) groups.push({ date: ev.event_date, events: [ev] })
      else last.events.push(ev)
    }
    return groups
  }, [ecoCalendarData])

  return (
    <div className="p-6 space-y-6">
      {/* Header */}
      <div className="flex items-center justify-between">
        <div>
          <h1 className="text-xl font-bold text-white">OpenFin Cockpit</h1>
          <p className="text-xs text-slate-500 mt-0.5">
            {format(new Date(), "EEEE d MMMM yyyy · HH:mm", { locale: fr })}
          </p>
        </div>
        <div className="flex items-center gap-3">
          {portfolio && portfolio.open_positions > 0 && (
            <div className={clsx('text-sm font-bold', portfolio.unrealized_pnl >= 0 ? 'text-emerald-400' : 'text-red-400')}>
              Portfolio: {portfolio.unrealized_pnl >= 0 ? '+' : ''}{portfolio.unrealized_pnl?.toFixed(0)}€
            </div>
          )}
          <div className="flex items-center gap-2 text-xs text-slate-500">
            <div className="w-2 h-2 rounded-full bg-emerald-400 animate-pulse"></div>
            Live
          </div>
        </div>
      </div>

      {/* Risk concentration banner */}
      {(riskDashboard as any)?.concentration_alerts?.length > 0 && (
        <div className="space-y-1.5">
          {((riskDashboard as any).concentration_alerts as any[]).slice(0, 2).map((alert: any, i: number) => (
            <div key={i} className={clsx('flex items-center gap-2 text-xs px-3 py-2 rounded border', {
              'bg-red-900/20 border-red-700/30 text-red-300': alert.level === 'high',
              'bg-amber-900/20 border-amber-700/30 text-amber-300': alert.level === 'warning',
            })}>
              <ShieldAlert className="w-3 h-3 shrink-0" />
              {alert.message}
              <a href="/risk" className="ml-auto text-slate-500 hover:text-slate-300 underline">Risk Dashboard →</a>
            </div>
          ))}
        </div>
      )}

      {/* Top row */}
      <div className="grid grid-cols-4 gap-4">
        {/* Geo Risk */}
        <div className="card col-span-1 flex flex-col">
          <div className="flex items-center justify-between mb-2 shrink-0">
            <div className="section-title flex items-center gap-1 mb-0">
              <Globe className="w-3 h-3" /> Geopolitical Risk
            </div>
            <Link to="/geo" className="flex items-center gap-0.5 text-[10px] text-slate-600 hover:text-slate-300 transition-colors">
              Geo news <ArrowUpRight className="w-2.5 h-2.5" />
            </Link>
          </div>
          {riskLoading ? (
            <div className="animate-pulse h-16 bg-dark-600 rounded"></div>
          ) : riskScore && gauge ? (
            <div className="flex flex-col flex-1 min-h-0">
              <div className="flex items-start justify-between gap-3 shrink-0">
                <div>
                  <div className={clsx('text-5xl font-bold', gauge.color)}>{riskScore.score}</div>
                  <div className={clsx('text-sm font-semibold mt-1', gauge.color)}>{gauge.label}</div>
                </div>
                <div className="text-right space-y-0.5 mt-1 shrink-0">
                  {riskScore.top_risks?.map(([cat, val]) => (
                    <div key={cat} className="flex items-center justify-end gap-1.5 text-[9px]">
                      <span className="text-slate-500 capitalize truncate max-w-[86px]">{(cat as string).replace('_', ' ')}</span>
                      <span className="text-slate-400 font-mono w-7 text-right">{Math.round((val as number) * 100)}%</span>
                    </div>
                  ))}
                </div>
              </div>
              <div className="mt-3 bg-dark-700 rounded-full h-2 shrink-0">
                <div className={clsx('h-2 rounded-full', gauge.bg)} style={{ width: `${riskScore.score}%` }} />
              </div>
              {topNews.length > 0 && (
                <div className="mt-2.5 pt-2 border-t border-slate-700/30 flex flex-col flex-1 min-h-0">
                  <div className="flex items-center gap-1 text-[9px] text-slate-600 mb-1 shrink-0">
                    <Newspaper className="w-2.5 h-2.5" /> Top news
                  </div>
                  <div className="space-y-1.5 overflow-y-auto flex-1 min-h-0">
                    {topNews.map((n, i) => {
                      const impact = Math.round(n.impact_score * 100)
                      const impactColor = impact >= 75 ? 'text-red-400' : impact >= 50 ? 'text-orange-400' : impact >= 25 ? 'text-yellow-400' : 'text-emerald-400'
                      const dotColor = impact >= 75 ? 'bg-red-500' : impact >= 50 ? 'bg-orange-500' : impact >= 25 ? 'bg-yellow-500' : 'bg-emerald-500'
                      return (
                        <div key={i} className="flex items-center gap-1.5 text-[10px]">
                          <span className={clsx('w-1.5 h-1.5 rounded-full shrink-0', dotColor)} />
                          <span className="text-slate-300 truncate flex-1 line-clamp-1">{n.title}</span>
                          <span className={clsx('font-mono font-bold shrink-0', impactColor)}>{impact}</span>
                        </div>
                      )
                    })}
                  </div>
                </div>
              )}
            </div>
          ) : <div className="text-slate-500 text-xs">Backend required</div>}
        </div>

        {/* Watchlist Radar — its natural height (no cap) drives row 1's height */}
        <div className="card col-span-1">
          <div className="flex items-center justify-between mb-2">
            <div className="section-title mb-0">📡 Watchlist Radar</div>
            <Link to="/config" className="flex items-center gap-0.5 text-[10px] text-slate-600 hover:text-slate-300 transition-colors">
              Manage <ArrowUpRight className="w-2.5 h-2.5" />
            </Link>
          </div>
          {watchlistRadarData.length > 0 ? (
            <>
              <ResponsiveContainer width="100%" height={130}>
                <RadarChart data={watchlistRadarData}>
                  <PolarGrid stroke="#1e2d4d" />
                  <PolarAngleAxis dataKey="subject" tick={{ fill: '#64748b', fontSize: 9 }} />
                  <Radar dataKey="ref" stroke="#334155" strokeDasharray="3 3" fill="transparent" isAnimationActive={false} />
                  <Radar dataKey="value" stroke="#3b82f6" fill="#3b82f6" fillOpacity={0.25} />
                </RadarChart>
              </ResponsiveContainer>
              <div className="mt-1.5 pt-1.5 border-t border-slate-700/30 space-y-1">
                {((watchlistQuotesData as any)?.items ?? []).map((it: any) => (
                  <div key={it.ticker} className="flex items-center justify-between text-[10px]">
                    <span className="text-slate-400 font-mono">{it.ticker}</span>
                    <div className="flex items-center gap-2">
                      <span className="text-slate-500 font-mono">{it.price != null ? it.price.toFixed(2) : '—'}</span>
                      <span className={clsx('font-mono font-bold w-12 text-right', (it.change_pct ?? 0) >= 0 ? 'text-emerald-400' : 'text-red-400')}>
                        {it.change_pct != null ? `${it.change_pct >= 0 ? '+' : ''}${it.change_pct.toFixed(2)}%` : '—'}
                      </span>
                    </div>
                  </div>
                ))}
              </div>
            </>
          ) : (
            <div className="h-40 flex flex-col items-center justify-center text-slate-600 text-xs gap-1.5">
              <span>No instruments watched</span>
              <Link to="/config" className="text-blue-400 hover:text-blue-300 underline">Add instruments →</Link>
            </div>
          )}
        </div>

        {/* Régime Macro */}
        {(() => {
          const dom = macroInfo?.dominant
          const colorClass = dom === 'growth' || dom === 'goldilocks' || dom === 'soft_landing' ? 'text-emerald-400'
            : dom === 'stagflation' || dom === 'recession' || dom === 'crise_liquidite' ? 'text-red-400'
            : dom === 'deflation' || dom === 'desinflation' ? 'text-blue-300'
            : dom === 'inflation_shock' ? 'text-orange-400'
            : 'text-slate-400'
          const ranked = macroInfo?.ranked ?? []

          // Key gauges from macroData
          const gauges = (macroData as any)?.gauges ?? {}
          const reasons: string[] = dom ? ((macroData as any)?.scenarios?.reasons?.[dom] ?? []) : []

          // 5 key indicators that explain the regime
          const KEY_GAUGES = [
            {
              key: 'vix', label: 'VIX',
              color: (v: number) => v < 18 ? 'text-emerald-400' : v < 25 ? 'text-yellow-400' : 'text-red-400',
              fmt: (v: number) => v.toFixed(1),
              hint: (v: number) => v < 18 ? '↓ low risk' : v < 25 ? '↑ alert' : '↑ crisis',
            },
            {
              key: 'spx_vs_200d', label: 'S&P/200d',
              color: (v: number) => v >= 0 ? 'text-emerald-400' : 'text-red-400',
              fmt: (v: number) => `${v >= 0 ? '+' : ''}${v.toFixed(1)}%`,
              hint: (v: number) => v >= 5 ? 'strong bull' : v >= 0 ? 'mod. bull' : 'bear',
            },
            {
              key: 'slope_10y3m', label: 'Slope 10Y-3M',
              color: (v: number) => v >= 0.5 ? 'text-emerald-400' : v >= 0 ? 'text-yellow-400' : 'text-red-400',
              fmt: (v: number) => `${v >= 0 ? '+' : ''}${v.toFixed(2)}`,
              hint: (v: number) => v >= 0.5 ? 'normal' : v >= 0 ? 'flat' : 'inverted',
            },
            {
              key: 'copper', label: 'Copper',
              color: (v: number, chg: number) => chg >= 0 ? 'text-emerald-400' : 'text-red-400',
              fmt: (v: number, chg: number) => `${chg >= 0 ? '+' : ''}${chg.toFixed(2)}%`,
              hint: (v: number, chg: number) => chg >= 0 ? '↑ growth' : '↓ slowing',
            },
            {
              key: 'gold', label: 'Gold',
              color: (v: number, chg: number) => chg >= 1 ? 'text-amber-400' : chg <= -1 ? 'text-emerald-400' : 'text-slate-400',
              fmt: (v: number, chg: number) => `${chg >= 0 ? '+' : ''}${chg.toFixed(2)}%`,
              hint: (v: number, chg: number) => chg >= 1 ? '↑ safe haven' : chg <= -1 ? '↓ risk-on' : '≈ neutral',
            },
          ]

          return (
            <Link to="/macro" className="card col-span-1 flex flex-col hover:border-slate-600/60 transition-all cursor-pointer">
              <div className="flex items-center justify-between mb-1">
                <span className="section-title mb-0 text-[10px]">🌐 Macro Regime</span>
                <ArrowUpRight className="w-3 h-3 text-slate-600" />
              </div>
              <div className={clsx('text-base font-bold mt-1', colorClass)}>
                {macroInfo ? `${macroInfo.emoji} ${macroInfo.label}` : '—'}
              </div>
              {ranked.length > 0 && (
                <div className="mt-1.5 space-y-1">
                  {ranked.slice(0, 4).map(([key, score]: [string, number]) => {
                    const maxScore = ranked[0]?.[1] ?? 1
                    const pct = Math.round((score / Math.max(maxScore, 1)) * 100)
                    const isDom = key === dom
                    return (
                      <div key={key} className="flex items-center gap-1.5">
                        <span className={clsx('text-[9px] w-16 truncate', isDom ? 'text-slate-200 font-semibold' : 'text-slate-500')}>
                          {REGIME_LABELS[key] ?? key}
                        </span>
                        <div className="flex-1 h-1.5 bg-dark-700 rounded-full overflow-hidden">
                          <div
                            className={clsx('h-full rounded-full transition-all', isDom ? 'bg-blue-500' : 'bg-slate-600')}
                            style={{ width: `${pct}%` }}
                          />
                        </div>
                        <span className={clsx('text-[9px] font-mono w-5 text-right', isDom ? 'text-blue-400' : 'text-slate-600')}>
                          {score}
                        </span>
                      </div>
                    )
                  })}
                </div>
              )}

              {/* Key macro gauges */}
              {Object.keys(gauges).length > 0 && (
                <div className="mt-1.5 pt-1.5 border-t border-slate-700/30 space-y-0.5">
                  {KEY_GAUGES.map(({ key, label, color, fmt, hint }) => {
                    const g = gauges[key]
                    if (!g) return null
                    const val: number = g.value ?? 0
                    const chg: number = g.change_pct ?? 0
                    const c = color(val, chg)
                    const h = hint(val, chg)
                    return (
                      <div key={key} className="flex items-center gap-1.5">
                        <span className="text-[9px] text-slate-600 w-16 shrink-0">{label}</span>
                        <span className={clsx('text-[9px] font-mono font-semibold shrink-0', c)}>
                          {fmt(val, chg)}
                        </span>
                        <span className="text-[8px] text-slate-700 truncate">{h}</span>
                      </div>
                    )
                  })}
                </div>
              )}

              {/* Trigger signals for dominant regime */}
              {reasons.length > 0 && (
                <div className="mt-1 flex flex-wrap gap-1">
                  {reasons.slice(0, 4).map((r: string, i: number) => (
                    <span key={i} className="text-[8px] bg-blue-900/20 text-blue-400/80 border border-blue-800/30 px-1.5 py-0.5 rounded">
                      {r}
                    </span>
                  ))}
                </div>
              )}
            </Link>
          )
        })()}

        {/* Economic Events — real Forex Factory feed, grouped by date */}
        <div className="card col-span-1 flex flex-col">
          <div className="section-title flex items-center gap-1 shrink-0"><Clock className="w-3 h-3" /> Economic Events</div>
          {upcomingEventsGrouped.length > 0 ? (
            <div className="mt-2 space-y-2 overflow-y-auto flex-1 min-h-0">
              {upcomingEventsGrouped.map(group => (
                <div key={group.date}>
                  <div className="flex items-center gap-1.5 text-[9px] font-semibold text-slate-300 bg-dark-700/50 rounded px-1.5 py-0.5 mb-1">
                    {formatDateShort(group.date)}
                    {isTodayISO(group.date) && <span className="badge-blue text-[8px] px-1 py-0">TODAY</span>}
                  </div>
                  <div className="space-y-1 pl-0.5">
                    {group.events.map((ev: any, i: number) => (
                      <div key={i} className="flex items-center gap-1.5 text-[10px]">
                        <span className="shrink-0">{CURRENCY_FLAGS[ev.currency] ?? ev.currency}</span>
                        <span className={clsx('w-1.5 h-1.5 rounded-full shrink-0', IMPACT_DOT[ev.impact] ?? 'bg-slate-400')} />
                        <span className="text-white truncate flex-1 line-clamp-1">{ev.event_name}</span>
                        {ev.event_time && <span className="text-slate-700 text-[9px] shrink-0 font-mono">{ev.event_time}</span>}
                      </div>
                    ))}
                  </div>
                </div>
              ))}
            </div>
          ) : <div className="text-slate-600 text-xs mt-2">No upcoming events</div>}
        </div>
      </div>

      {/* ── Command Center: Résumé Opérationnel ── */}
      <div className="grid grid-cols-4 gap-3">

        {/* PnL */}
        {(() => {
          // Unrealized — open trades only (get_trade_entry_prices excludes closed)
          const openTrades    = mtmTrades
          const openWithPnl   = openTrades.filter((t: any) => t.pnl_pct != null)
          const openCapital   = openTrades.reduce((s: number, t: any) => s + (t.capital_invested ?? t.entry_price ?? 0), 0)
          const openProfit    = openWithPnl.reduce((s: number, t: any) => s + ((t.capital_invested ?? t.entry_price ?? 0) * t.pnl_pct / 100), 0)
          const openPnlPct    = openCapital > 0 ? openProfit / openCapital * 100 : null
          const openWinners   = openWithPnl.filter((t: any) => t.pnl_pct > 0).length
          const openLosers    = openWithPnl.filter((t: any) => t.pnl_pct < 0).length
          const targetHit     = openTrades.filter((t: any) => t.alert_type === 'target_reached').length
          const stopHit       = openTrades.filter((t: any) => t.alert_type === 'stop_loss').length

          // Realized — from dedicated closed-trades endpoint (pnl_realized in %, capital for EUR)
          const closedTrades   = (closedTradesData as any)?.trades ?? []
          const closedCapital  = closedTrades.reduce((s: number, t: any) => s + (t.capital_invested ?? t.entry_price ?? 0), 0)
          const closedProfitEur = closedTrades.reduce((s: number, t: any) => {
            const cap = t.capital_invested ?? t.entry_price ?? 0
            return s + (cap * (t.pnl_realized ?? 0) / 100)
          }, 0)
          const closedWithPnl  = closedTrades.filter((t: any) => t.pnl_realized != null)
          const avgClosedPct   = closedWithPnl.length > 0
            ? closedWithPnl.reduce((s: number, t: any) => s + t.pnl_realized, 0) / closedWithPnl.length
            : null
          const closedWinners  = closedTrades.filter((t: any) => (t.pnl_realized ?? 0) > 0).length
          const closedLosers   = closedTrades.filter((t: any) => (t.pnl_realized ?? 0) < 0).length

          const isEstimated = openTrades.some((t: any) => t.capital_invested == null && t.entry_price != null)
          const totalCapital = openCapital + closedCapital
          const totalProfit  = openProfit + closedProfitEur

          const pf = portfolio as any
          const pfPnlPct = pf?.unrealized_pnl_pct ?? null
          const pfPnl    = pf?.unrealized_pnl ?? null
          const pfInvest = pf?.total_invested ?? null
          const pfReal   = pf?.realized_pnl ?? null
          const pfNet    = pf?.net_pnl ?? null

          return (
            <Link to="/journal" className="card flex flex-col hover:border-slate-600/60 transition-all cursor-pointer">
              <div className="flex items-center justify-between mb-1.5">
                <span className="section-title mb-0 text-[10px]">📊 P&L</span>
                <div className="flex items-center gap-1.5">
                  <ViewToggle value={pnlView} onChange={setPnlViewPersist} />
                  <ArrowUpRight className="w-3 h-3 text-slate-600" />
                </div>
              </div>

              {/* ── Side-by-side: Unrealized | Realized ── */}
              <div className="grid grid-cols-2 gap-2 flex-shrink-0">
                {/* Left: Unrealized */}
                <div className="bg-dark-700/40 rounded px-2.5 py-2 border border-slate-700/30">
                  <div className="text-[9px] text-slate-600 uppercase tracking-wide mb-1">Open</div>
                  {pnlView === 'simulated' ? (
                    <>
                      <div className={clsx('text-xl font-bold font-mono leading-none',
                        openPnlPct === null ? 'text-slate-600' : openPnlPct >= 0 ? 'text-emerald-400' : 'text-red-400')}>
                        {openPnlPct !== null ? `${openPnlPct >= 0 ? '+' : ''}${openPnlPct.toFixed(1)}%` : '—'}
                      </div>
                      <div className={clsx('text-xs font-mono mt-0.5',
                        openProfit >= 0 ? 'text-emerald-500' : 'text-red-400')}>
                        {openCapital > 0 ? `${openProfit >= 0 ? '+' : ''}${openProfit.toFixed(0)}€` : '—'}
                      </div>
                      <div className="text-[10px] text-slate-500 mt-1">
                        {openTrades.length} trades · <span className="text-emerald-500">{openWinners}✓</span>{' '}
                        <span className="text-red-400">{openLosers}✗</span>
                      </div>
                    </>
                  ) : (
                    <>
                      <div className={clsx('text-xl font-bold font-mono leading-none',
                        pfPnlPct === null ? 'text-slate-600' : pfPnlPct >= 0 ? 'text-emerald-400' : 'text-red-400')}>
                        {pfPnlPct !== null ? `${pfPnlPct >= 0 ? '+' : ''}${pfPnlPct.toFixed(1)}%` : '—'}
                      </div>
                      <div className={clsx('text-xs font-mono mt-0.5', (pfPnl ?? 0) >= 0 ? 'text-emerald-500' : 'text-red-400')}>
                        {pfPnl != null ? `${pfPnl >= 0 ? '+' : ''}${pfPnl.toFixed(0)}€` : '—'}
                      </div>
                      <div className="text-[10px] text-slate-500 mt-1">
                        {pf?.open_positions ?? 0} positions
                      </div>
                    </>
                  )}
                  {(targetHit > 0 || stopHit > 0) && (
                    <div className="mt-1 text-[9px] space-x-1">
                      {targetHit > 0 && <span className="text-emerald-400">🎯{targetHit}</span>}
                      {stopHit   > 0 && <span className="text-red-400">⛔{stopHit}</span>}
                    </div>
                  )}
                </div>

                {/* Right: Realized */}
                <div className="bg-dark-700/40 rounded px-2.5 py-2 border border-slate-700/30">
                  <div className="text-[9px] text-slate-600 uppercase tracking-wide mb-1">Realized</div>
                  {pnlView === 'simulated' ? (
                    <>
                      <div className={clsx('text-xl font-bold font-mono leading-none',
                        avgClosedPct === null ? 'text-slate-600'
                        : avgClosedPct >= 0 ? 'text-emerald-400' : 'text-red-400')}>
                        {avgClosedPct !== null
                          ? `${avgClosedPct >= 0 ? '+' : ''}${avgClosedPct.toFixed(2)}%`
                          : closedTrades.length === 0 ? '—' : '+0.00%'}
                      </div>
                      <div className={clsx('text-xs font-mono mt-0.5',
                        closedProfitEur >= 0 ? 'text-emerald-500' : 'text-red-400')}>
                        {closedCapital > 0
                          ? `${closedProfitEur >= 0 ? '+' : ''}${closedProfitEur.toFixed(0)}€`
                          : closedTrades.length > 0 ? 'no capital' : ''}
                      </div>
                      <div className="text-[10px] text-slate-500 mt-1">
                        {closedTrades.length} closed · <span className="text-emerald-500">{closedWinners}✓</span>{' '}
                        <span className="text-red-400">{closedLosers}✗</span>
                      </div>
                    </>
                  ) : (
                    <>
                      <div className={clsx('text-xl font-bold font-mono leading-none',
                        pfReal == null || pfReal === 0 ? 'text-slate-600'
                        : pfReal > 0 ? 'text-emerald-400' : 'text-red-400')}>
                        {pfReal != null && pfReal !== 0
                          ? `${pfReal >= 0 ? '+' : ''}${pfReal.toFixed(0)}€`
                          : '—'}
                      </div>
                      {pfNet != null && (
                        <div className={clsx('text-xs font-mono mt-0.5', pfNet >= 0 ? 'text-emerald-500/70' : 'text-red-400/70')}>
                          net {pfNet >= 0 ? '+' : ''}{pfNet.toFixed(0)}€
                        </div>
                      )}
                      <div className="text-[10px] text-slate-500 mt-1">
                        {pf?.closed_positions ?? 0} closed
                      </div>
                    </>
                  )}
                </div>
              </div>

              {/* Total line */}
              <div className="mt-1.5 flex items-center justify-between text-[10px] flex-shrink-0">
                <span className="text-slate-600">
                  Invested{isEstimated ? ' ~' : ''} {pnlView === 'simulated'
                    ? (totalCapital > 0 ? `${totalCapital.toFixed(0)}€` : '—')
                    : (pfInvest != null ? `${pfInvest.toFixed(0)}€` : '—')}
                </span>
                <span className={clsx('font-mono font-bold',
                  (pnlView === 'simulated' ? totalProfit : (pfNet ?? 0)) >= 0 ? 'text-emerald-400' : 'text-red-400')}>
                  Total {pnlView === 'simulated'
                    ? (totalCapital > 0 ? `${totalProfit >= 0 ? '+' : ''}${totalProfit.toFixed(0)}€` : '—')
                    : (pfNet != null ? `${pfNet >= 0 ? '+' : ''}${pfNet.toFixed(0)}€` : '—')}
                </span>
              </div>
              {/* PnL historical sparkline */}
              {(() => {
                const snaps: any[] = [...(pnlHistoryData?.snapshots ?? [])].reverse()
                if (snaps.length < 2) return null
                const chartData = snaps.map(s => ({
                  date: s.snapped_at?.slice(5, 10),
                  pnl: s.total_pnl_pct ?? 0,
                }))
                const minVal = Math.min(...chartData.map(d => d.pnl))
                const maxVal = Math.max(...chartData.map(d => d.pnl))
                const isPositive = chartData[chartData.length - 1]?.pnl >= 0
                const strokeColor = isPositive ? '#34d399' : '#f87171'
                const gradId = 'pnlGrad'
                return (
                  <div className="mt-1.5 pt-1.5 border-t border-slate-700/30">
                    <div className="text-[9px] text-slate-600 mb-0.5">Historical PnL curve ({snaps.length} pts)</div>
                    <ResponsiveContainer width="100%" height={58}>
                      <AreaChart data={chartData} margin={{ top: 2, right: 0, left: -38, bottom: 0 }}>
                        <defs>
                          <linearGradient id={gradId} x1="0" y1="0" x2="0" y2="1">
                            <stop offset="5%" stopColor={strokeColor} stopOpacity={0.25} />
                            <stop offset="95%" stopColor={strokeColor} stopOpacity={0} />
                          </linearGradient>
                        </defs>
                        <CartesianGrid strokeDasharray="3 3" stroke="#1e293b" vertical={false} />
                        <XAxis dataKey="date" tick={{ fontSize: 8, fill: '#475569' }}
                          interval={Math.max(0, Math.floor(chartData.length / 5) - 1)} />
                        <YAxis domain={[minVal - 0.1, maxVal + 0.1]} tick={{ fontSize: 8, fill: '#475569' }} unit="%" />
                        <Tooltip
                          contentStyle={{ background: '#0f172a', border: '1px solid #334155', borderRadius: 6, fontSize: 10, padding: '4px 8px' }}
                          labelStyle={{ color: '#64748b' }}
                          formatter={(v: any) => [`${v >= 0 ? '+' : ''}${Number(v).toFixed(3)}%`, 'PnL']}
                        />
                        <Area type="monotone" dataKey="pnl" stroke={strokeColor} strokeWidth={1.5}
                          fill={`url(#${gradId})`} dot={false} />
                      </AreaChart>
                    </ResponsiveContainer>
                  </div>
                )
              })()}
            </Link>
          )
        })()}

        {/* Risk — donut chart of asset allocation */}
        {(() => {
          const risk = simRisk as any
          const alertCount: number = risk?.alerts?.length ?? 0
          const conflictCount: number = risk?.conflicts?.length ?? 0
          const openCount: number = risk?.open_count ?? 0
          const concentration: Record<string, any> = risk?.concentration ?? {}
          const pieData = Object.entries(concentration)
            .map(([cls, data]: [string, any]) => ({ name: cls, value: data.pct, bullish: data.bullish, bearish: data.bearish }))
            .filter(d => d.value > 0)
            .sort((a, b) => b.value - a.value)

          return (
            <Link to="/risk" className="card flex flex-col hover:border-slate-600/60 transition-all cursor-pointer">
              <div className="flex items-center justify-between mb-1">
                <span className="section-title mb-0 text-[10px]">🛡️ Risk</span>
                <ArrowUpRight className="w-3 h-3 text-slate-600" />
              </div>
              <div className={clsx('text-lg font-bold mt-0.5 flex items-center gap-2', alertCount > 0 ? 'text-red-400' : 'text-emerald-400')}>
                {alertCount > 0 ? `${alertCount} alert${alertCount > 1 ? 's' : ''}` : 'OK'}
                {conflictCount > 0 && <span className="text-[10px] text-red-400 font-normal">{conflictCount} conflict{conflictCount > 1 ? 's' : ''}</span>}
              </div>
              {pieData.length > 0 ? (
                <>
                  <ResponsiveContainer width="100%" height={100}>
                    <PieChart>
                      <Pie data={pieData} dataKey="value" nameKey="name" innerRadius={30} outerRadius={48} paddingAngle={2}>
                        {pieData.map((d, i) => (
                          <Cell key={i} fill={ASSET_CLASS_COLORS[d.name] ?? ASSET_CLASS_COLORS.unknown} />
                        ))}
                      </Pie>
                      <Tooltip
                        contentStyle={{ background: '#0f172a', border: '1px solid #334155', borderRadius: 6, fontSize: 10, padding: '4px 8px' }}
                        formatter={(value: any, name: any, props: any) => [`${value}% (${props.payload.bullish}↑ ${props.payload.bearish}↓)`, name]}
                      />
                    </PieChart>
                  </ResponsiveContainer>
                  <div className="mt-1 space-y-0.5">
                    {pieData.map(d => {
                      const bias = d.bullish > d.bearish ? 'bullish' : d.bearish > d.bullish ? 'bearish' : 'neutral'
                      return (
                        <div key={d.name} className="flex items-center gap-1.5 text-[9px]">
                          <span className="w-2 h-2 rounded-full shrink-0" style={{ background: ASSET_CLASS_COLORS[d.name] ?? ASSET_CLASS_COLORS.unknown }} />
                          <span className="text-slate-500 capitalize flex-1 truncate">{d.name}</span>
                          <span className={clsx('text-[8px] w-3', bias === 'bullish' ? 'text-emerald-500' : bias === 'bearish' ? 'text-red-400' : 'text-slate-700')}>
                            {bias === 'bullish' ? '↑' : bias === 'bearish' ? '↓' : '—'}
                          </span>
                          <span className="text-slate-600 font-mono w-9 text-right">{d.value}%</span>
                        </div>
                      )
                    })}
                  </div>
                  {(risk?.alerts ?? []).length > 0 && (
                    <div className="mt-2 pt-2 border-t border-slate-700/30 space-y-1">
                      {(risk.alerts as any[]).map((a: any, i: number) => (
                        <div key={i} className={clsx('flex items-start gap-1 text-[9px] leading-snug', a.level === 'danger' ? 'text-red-400' : 'text-amber-400')}>
                          <span className="shrink-0 mt-[3px]">{a.level === 'danger' ? '●' : '▲'}</span>
                          <span className="line-clamp-2">{a.message}</span>
                        </div>
                      ))}
                    </div>
                  )}
                </>
              ) : (
                <div className="text-[10px] text-slate-600 mt-1">
                  {openCount > 0 ? `${openCount} positions` : 'No positions'}
                </div>
              )}
            </Link>
          )
        })()}

        {/* VaR — histogram + rolling trend */}
        {(() => {
          const snap = latestVarData?.snapshot
          const hv = snap?.hist_var_1d_pct
          const cv = snap?.hist_cvar_pct
          const mv = snap?.mc_var_1d_pct
          const ts = snap?.computed_at?.slice(0, 16).replace('T', ' ')
          const histogram: any[] = snap?.full_result?.histogram ?? []
          const rollingVar: any[] = (snap?.full_result?.rolling_var ?? []).slice(-30)

          return (
            <Link to="/var" className="card flex flex-col hover:border-slate-600/60 transition-all cursor-pointer">
              <div className="flex items-center justify-between mb-1">
                <span className="section-title mb-0 text-[10px]">📉 VaR</span>
                <ArrowUpRight className="w-3 h-3 text-slate-600" />
              </div>
              {snap ? (
                <>
                  <div className="text-[9px] text-slate-600 mb-1">VaR 95% · {ts} UTC</div>
                  <div className="grid grid-cols-3 gap-1 flex-shrink-0">
                    {[
                      { label: 'Hist.', val: hv, color: 'text-blue-400' },
                      { label: 'CVaR', val: cv, color: 'text-orange-400' },
                      { label: 'MC×1.5', val: mv, color: 'text-red-400' },
                    ].map(({ label, val, color }) => (
                      <div key={label} className="bg-dark-700/60 rounded px-2 py-1 text-center">
                        <div className="text-[8px] text-slate-600 mb-0.5">{label}</div>
                        <div className={clsx('text-xs font-bold font-mono', color)}>
                          {val != null ? `${val >= 0 ? '+' : ''}${val.toFixed(2)}%` : '—'}
                        </div>
                      </div>
                    ))}
                  </div>
                  {histogram.length > 0 && (
                    <div className="mt-1.5 pt-1.5 border-t border-slate-700/30">
                      <div className="text-[9px] text-slate-600 mb-0.5">P&L distribution</div>
                      <ResponsiveContainer width="100%" height={80}>
                        <BarChart data={histogram}>
                          <CartesianGrid strokeDasharray="3 3" stroke="#334155" vertical={false} />
                          <XAxis dataKey="x" tick={{ fontSize: 7, fill: '#475569' }}
                            interval={Math.max(0, Math.floor(histogram.length / 4) - 1)} />
                          <Tooltip
                            contentStyle={{ background: '#0f172a', border: '1px solid #334155', borderRadius: 6, fontSize: 10, padding: '4px 8px' }}
                            formatter={(v: any) => [v, 'count']}
                            labelFormatter={(l: any) => `${l}%`}
                          />
                          {hv != null && <ReferenceLine x={hv} stroke="#f87171" strokeDasharray="4 2" strokeWidth={1.5} />}
                          <Bar dataKey="count" radius={[2, 2, 0, 0]}>
                            {histogram.map((h: any, i: number) => (
                              <Cell key={i} fill={hv != null && h.x < hv ? '#ef4444' : '#3b82f6'} fillOpacity={0.7} />
                            ))}
                          </Bar>
                        </BarChart>
                      </ResponsiveContainer>
                    </div>
                  )}
                  {rollingVar.length > 1 && (
                    <div className="mt-1 flex-1 min-h-0">
                      <ResponsiveContainer width="100%" height={36}>
                        <AreaChart data={rollingVar} margin={{ top: 2, right: 0, left: 0, bottom: 0 }}>
                          <Area type="monotone" dataKey="var_95" stroke="#f59e0b" strokeWidth={1.2} fill="#f59e0b" fillOpacity={0.15} dot={false} />
                        </AreaChart>
                      </ResponsiveContainer>
                    </div>
                  )}
                </>
              ) : (
                <div className="text-[10px] text-slate-600 mt-1">
                  No VaR snapshot yet — run one from <span className="text-blue-400">/var</span>
                </div>
              )}
            </Link>
          )
        })()}

        {/* Options Lab — IV highlights scoped to the watchlist */}
        {(() => {
          const watchlist: any[] = watchlistItems ?? []
          const snapshots: Record<string, any> = (ivBatchData as any)?.snapshots ?? {}
          const highlights = watchlist
            .map((w: any) => snapshots[w.ticker])
            .filter(Boolean)
            .sort((a: any, b: any) => Math.abs((b.iv_rank ?? 50) - 50) - Math.abs((a.iv_rank ?? 50) - 50))

          return (
            <Link to="/options" className="card flex flex-col hover:border-slate-600/60 transition-all cursor-pointer">
              <div className="flex items-center justify-between mb-1">
                <span className="section-title mb-0 text-[10px]">🧪 Options Lab</span>
                <ArrowUpRight className="w-3 h-3 text-slate-600" />
              </div>
              {watchlist.length === 0 ? (
                <div className="text-[10px] text-slate-600 mt-1">
                  Add instruments to your watchlist (Config) to see IV highlights
                </div>
              ) : highlights.length > 0 ? (
                <div className="space-y-1.5 mt-1">
                  {highlights.map((h: any) => {
                    const rank = h.iv_rank
                    const skewPct = h.skew?.skew_pct
                    const ivCur = h.iv_current_pct
                    const ivPctl = h.iv_percentile
                    const flow: string | null = h.options_flow?.flow_bias ?? null
                    const pcRatio = h.options_flow?.pc_oi_ratio
                    return (
                      <div key={h.ticker} className="pb-1 border-b border-slate-700/20 last:border-0">
                        <div className="flex items-center gap-1.5 text-[10px]">
                          <span>{rank != null && rank > 80 ? '🔴' : rank != null && rank < 20 ? '🟢' : '⚪'}</span>
                          <span className="font-mono text-slate-200 font-bold shrink-0">{h.ticker}</span>
                          <span className="text-slate-500">IVR {rank != null ? rank.toFixed(0) : '—'}</span>
                          {ivCur != null && <span className="text-slate-600">· IV {ivCur.toFixed(1)}%</span>}
                          {skewPct != null && Math.abs(skewPct) > 3 && (
                            <span className={clsx('ml-auto text-[9px]', skewPct > 0 ? 'text-orange-400' : 'text-blue-400')}>
                              skew {skewPct >= 0 ? '+' : ''}{skewPct.toFixed(1)}
                            </span>
                          )}
                        </div>
                        {(ivPctl != null || flow != null || pcRatio != null) && (
                          <div className="text-[8px] text-slate-700 mt-0.5 ml-5 truncate">
                            {ivPctl != null && <span>Pctl {ivPctl.toFixed(0)}</span>}
                            {ivPctl != null && pcRatio != null && ' · '}
                            {pcRatio != null && <span>P/C {pcRatio.toFixed(2)}</span>}
                            {(ivPctl != null || pcRatio != null) && flow && ' · '}
                            {flow && <span className="italic">{flow}</span>}
                          </div>
                        )}
                      </div>
                    )
                  })}
                </div>
              ) : (
                <div className="text-[10px] text-slate-600 mt-1">Loading IV data…</div>
              )}
            </Link>
          )
        })()}
      </div>

      {/* ── Command Center: Intelligence & Contexte ── */}
      <div className="grid grid-cols-4 gap-3">

        <TradeRankList trades={mtmTrades} mode="top" title="🏆 Top Trades" linkTo="/journal" />
        <TradeRankList trades={mtmTrades} mode="worst" title="📉 Worst Trades" linkTo="/journal" />

        {/* Recommandations du jour — patterns from the most recent cycle only */}
        <Link to="/patterns" className="card block hover:border-slate-600/60 transition-all cursor-pointer">
          <div className="flex items-center justify-between mb-1">
            <span className="section-title mb-0 text-[10px]">🎯 Recommandations du jour</span>
            <ArrowUpRight className="w-3 h-3 text-slate-600" />
          </div>
          {cyclePatterns.length > 0 ? (
            <div className="space-y-2.5 mt-1">
              {cyclePatterns.map((p: any, i: number) => {
                const sp = scoreMap[p.id]
                const score: number | null = sp?.score ?? null
                const ticker: string | null = sp?.recommended_trade?.underlying ?? null
                const dateStr = p.created_at ? p.created_at.slice(0, 10) : null
                return (
                  <div key={p.id}>
                    <div className="flex items-center gap-1.5">
                      <span className="text-[9px] text-slate-700 w-3 shrink-0 font-mono">{i + 1}</span>
                      <div className="flex-1 min-w-0">
                        <div className="text-[10px] text-slate-300 truncate leading-tight">{p.name}</div>
                      </div>
                      {score !== null ? (
                        <span className={clsx('text-sm font-bold font-mono shrink-0', scoreColor(score))}>{score}</span>
                      ) : (
                        <span className="text-[9px] text-slate-700 shrink-0">—</span>
                      )}
                    </div>
                    <div className="text-[8px] text-slate-700 mt-0.5 ml-4 font-mono">
                      {ticker && <span className="text-slate-500">{ticker}</span>}
                      {ticker && dateStr && ' · '}
                      {dateStr}
                    </div>
                  </div>
                )
              })}
            </div>
          ) : (
            <div className="text-[10px] text-slate-600 mt-1">Aucun cycle exécuté aujourd'hui</div>
          )}
        </Link>

        {/* Narration du cycle — GPT-4o context narrative from the latest cycle report */}
        {(() => {
          const report = (latestCycleReportData as any)?.report
          const narrative: string = report?.context_narrative?.narrative ?? ''
          const keySignals: string[] = report?.context_narrative?.key_signals ?? []
          return (
            <Link to="/rapport" className="card block hover:border-slate-600/60 transition-all cursor-pointer">
              <div className="flex items-center justify-between mb-1">
                <span className="section-title mb-0 text-[10px] flex items-center gap-1">
                  <Newspaper className="w-2.5 h-2.5" /> Cycle Narrative
                </span>
                <ArrowUpRight className="w-3 h-3 text-slate-600" />
              </div>
              {narrative ? (
                <>
                  <p className="text-[10px] text-slate-400 leading-relaxed line-clamp-6 mt-1">{narrative}</p>
                  {keySignals.length > 0 && (
                    <div className="mt-1.5 pt-1.5 border-t border-slate-700/30 flex flex-wrap gap-1">
                      {keySignals.slice(0, 4).map((s: string, i: number) => (
                        <span key={i} className="text-[8px] bg-blue-900/20 text-blue-400/80 border border-blue-800/30 px-1.5 py-0.5 rounded">
                          {s}
                        </span>
                      ))}
                    </div>
                  )}
                </>
              ) : (
                <div className="text-[10px] text-slate-600 mt-1">No cycle narrative yet</div>
              )}
            </Link>
          )
        })()}
      </div>

      {/* Markets mini overview */}
      <div className="grid grid-cols-4 gap-3">
        {['energy', 'metals', 'indices', 'forex'].map(cls => (
          <div key={cls} className="card">
            <div className="section-title">{assetEmoji[cls]} {cls}</div>
            {allQuotes?.[cls]?.map(q => <QuoteRow key={q.symbol} q={q} />) ?? (
              <div className="text-xs text-slate-600">Loading...</div>
            )}
          </div>
        ))}
      </div>
    </div>
  )
}
