import { useState, useEffect } from 'react'
import {
  FlaskConical, Library, Zap, BarChart3, RefreshCw, ChevronRight,
  Sliders, Brain, Search, Filter, CheckCircle, XCircle, Minus, AlertCircle,
} from 'lucide-react'
import clsx from 'clsx'

// ── Types ─────────────────────────────────────────────────────────────────────

interface CausalNode {
  id: string; label: string; type: 'input' | 'intermediate' | 'output'
  x: number; y: number; formula?: string; unit?: string; instrument?: string
}
interface CausalEdge {
  from: string; to: string; style: 'solid' | 'dashed'; type?: string; label?: string
}
interface Coefficient {
  value: number; calibrated: number | null; description: string
}
interface GraphJson {
  nodes: CausalNode[]; edges: CausalEdge[]
  coefficients: Record<string, Coefficient>
  instruments: string[]
  input_mapping: Record<string, { source: string; unit?: string; range?: number[] }>
}
interface Template {
  id: number; name: string; category: string; sub_type: string
  instruments: string[]; description: string; graph_json: GraphJson
  ai_rationale: string; calibration_json: Record<string, unknown>
  heuristic_ver: number
}
interface MarketEvent {
  id: number; name: string; category: string; sub_type: string
  start_date: string; level: string; impact_score: number
  market_impact: string; affected_assets: string
  actual_value: number | null; expected_value: number | null; surprise_pct: number | null
  analysis_id: number | null; template_id: number | null; activation_score: number | null
}
interface NodeResult {
  pred: number | null; act: number | null; status: string; label: string
}
interface AnalysisResult {
  event: MarketEvent; template_id: number; template_name: string; instrument: string
  inputs: Record<string, number>; node_values: Record<string, number>
  actual_moves: Record<string, number>; yields: Record<string, number | null>
  activation: {
    score: number | null; nodes: Record<string, NodeResult>; correct: number; total: number
  }
  drift: { pre_pips: number | null; post_pips: number | null; drift_ratio: number | null; leak: string }
  prices_mode: string; analyzed_at: string
}
interface Recommendation {
  template_id: number | null; template_name: string; confidence: number
  rationale: string; coefficient_suggestions: Record<string, number>
  instrument_focus: string[]; alternative_template_id: number | null; notes: string
  error?: string
}
interface CalibRow {
  id: number; name: string; category: string; sub_type: string
  n_analyses: number; avg_activation: number | null
  calibration: Record<string, { n?: number; avg_pred?: number; avg_actual?: number; coef_ratio?: number }>
}

// ── API ───────────────────────────────────────────────────────────────────────

const api = async (path: string, opts?: RequestInit) => {
  const r = await fetch(`http://localhost:8000${path}`, opts)
  if (!r.ok) { const t = await r.text(); throw new Error(t) }
  return r.json()
}

// ── Couleurs / labels ─────────────────────────────────────────────────────────

const NODE_COLORS: Record<string, string> = {
  input:        '#3b82f6',
  intermediate: '#8b5cf6',
  output:       '#10b981',
}
const STATUS_COLOR: Record<string, string> = {
  correct: '#10b981', wrong: '#ef4444', neutral: '#64748b', unknown: '#64748b',
}
const CAT_LABELS: Record<string, string> = {
  macro_us: 'Macro US', macro_eu: 'Macro EU', geopolitical: 'Géopolitique',
  commodity: 'Matières premières', report: 'Report', sentiment: 'Sentiment',
}
const fmtPips = (v: number | null | undefined) =>
  v == null ? '—' : `${v > 0 ? '+' : ''}${v.toFixed(0)} pip`

// ── SVG Graph renderer ────────────────────────────────────────────────────────

function GraphSVG({
  graph, nodeValues, activationNodes, compact = false,
}: {
  graph: GraphJson
  nodeValues?: Record<string, number>
  activationNodes?: Record<string, NodeResult>
  compact?: boolean
}) {
  const nodes = graph.nodes || []
  const edges = graph.edges || []
  const xs = nodes.map(n => n.x)
  const ys = nodes.map(n => n.y)
  const minX = Math.min(...xs, 0) - 40
  const minY = Math.min(...ys, 0) - 30
  const maxX = Math.max(...xs, 400) + 120
  const maxY = Math.max(...ys, 400) + 60
  const W = maxX - minX; const H = maxY - minY
  const nodeMap = Object.fromEntries(nodes.map(n => [n.id, n]))
  const NW = compact ? 90 : 115; const NH = compact ? 28 : 38

  function nodeColor(n: CausalNode) {
    if (activationNodes?.[n.id]) return STATUS_COLOR[activationNodes[n.id].status] ?? NODE_COLORS[n.type]
    return NODE_COLORS[n.type] ?? '#64748b'
  }
  function edgePath(e: CausalEdge) {
    const s = nodeMap[e.from]; const t = nodeMap[e.to]
    if (!s || !t) return ''
    const x1 = s.x; const y1 = s.y + NH / 2
    const x2 = t.x; const y2 = t.y - NH / 2
    const mx = (x1 + x2) / 2
    return `M${x1},${y1} C${x1},${mx} ${x2},${mx} ${x2},${y2}`
  }

  return (
    <svg viewBox={`${minX} ${minY} ${W} ${H}`}
      style={{ width: '100%', height: compact ? 280 : 460 }}
      className="overflow-visible">
      <defs>
        <marker id="arrow" markerWidth="8" markerHeight="8" refX="6" refY="3" orient="auto">
          <path d="M0,0 L0,6 L8,3 z" fill="#475569" />
        </marker>
      </defs>
      {edges.map((e, i) => {
        const s = nodeMap[e.from]; const t = nodeMap[e.to]
        if (!s || !t) return null
        return (
          <path key={i} d={edgePath(e)} fill="none" stroke="#475569" strokeWidth={1.5}
            strokeDasharray={e.style === 'dashed' ? '5,3' : undefined}
            markerEnd="url(#arrow)" opacity={0.8} />
        )
      })}
      {nodes.map(n => {
        const col  = nodeColor(n)
        const val  = nodeValues?.[n.id]
        const unit = n.unit || ''
        return (
          <g key={n.id} transform={`translate(${n.x - NW / 2},${n.y - NH / 2})`}>
            <rect width={NW} height={NH} rx={6} fill={col} fillOpacity={0.18}
              stroke={col} strokeWidth={1.5} />
            <text x={NW / 2} y={compact ? 11 : 14} textAnchor="middle"
              fill="#e2e8f0" fontSize={compact ? 9 : 10} fontWeight="600">
              {n.label.length > 18 ? n.label.slice(0, 17) + '…' : n.label}
            </text>
            {val != null && (
              <text x={NW / 2} y={compact ? 22 : 27} textAnchor="middle"
                fill={col} fontSize={compact ? 9 : 10} fontWeight="700">
                {val > 0 ? '+' : ''}{val.toFixed(1)}{unit ? ` ${unit}` : ''}
              </text>
            )}
          </g>
        )
      })}
    </svg>
  )
}

// ── Tab Bibliothèque ──────────────────────────────────────────────────────────

function TabLibrary() {
  const [templates, setTemplates] = useState<Template[]>([])
  const [selected, setSelected]   = useState<Template | null>(null)
  const [catFilter, setCatFilter] = useState('')
  const [saving, setSaving]       = useState(false)
  const [editCoefs, setEditCoefs] = useState<Record<string, number>>({})
  const [loading, setLoading]     = useState(true)
  const [apiError, setApiError]   = useState<string | null>(null)
  const [debugInfo, setDebugInfo] = useState<Record<string, unknown> | null>(null)

  useEffect(() => {
    setLoading(true); setApiError(null)
    api(`/api/causal-lab/templates${catFilter ? `?category=${catFilter}` : ''}`)
      .then(data => {
        setTemplates(data)
        if (data.length === 0) {
          // Auto-run debug to show diagnostic
          api('/api/causal-lab/debug').then(setDebugInfo).catch(() => {})
        }
      })
      .catch(e => setApiError(String(e)))
      .finally(() => setLoading(false))
  }, [catFilter])

  function selectTemplate(t: Template) {
    setSelected(t)
    setEditCoefs(Object.fromEntries(
      Object.entries(t.graph_json?.coefficients || {}).map(([k, v]) => [k, v.value])
    ))
  }

  async function saveCoefs() {
    if (!selected) return
    setSaving(true)
    try {
      await api(`/api/causal-lab/template/${selected.id}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ coefficients: editCoefs }),
      })
      const fresh = await api(`/api/causal-lab/template/${selected.id}`)
      setSelected(fresh)
    } finally { setSaving(false) }
  }

  const cats = [...new Set(templates.map(t => t.category))]

  return (
    <div className="flex gap-4">
      {/* Liste templates */}
      <div className="w-72 flex-shrink-0">
        <select value={catFilter} onChange={e => setCatFilter(e.target.value)}
          className="w-full mb-3 bg-dark-700 border border-slate-700 rounded px-2 py-1.5 text-xs text-slate-300">
          <option value="">Toutes les catégories</option>
          {cats.map(c => <option key={c} value={c}>{CAT_LABELS[c] ?? c}</option>)}
        </select>

        {apiError && (
          <div className="mb-2 p-3 bg-red-900/20 border border-red-700/40 rounded text-xs text-red-300 break-all">
            <div className="font-bold mb-1">Erreur API</div>
            {apiError}
          </div>
        )}
        {debugInfo && (
          <div className="mb-2 p-3 bg-yellow-900/20 border border-yellow-700/40 rounded text-xs text-yellow-200">
            <div className="font-bold mb-1">Diagnostic</div>
            <pre className="whitespace-pre-wrap">{JSON.stringify(debugInfo, null, 2)}</pre>
          </div>
        )}
        {loading
          ? <div className="text-slate-500 text-xs p-4">Chargement…</div>
          : <div className="space-y-1 overflow-y-auto max-h-[calc(100vh-230px)]">
              {templates.map(t => (
                <button key={t.id} onClick={() => selectTemplate(t)}
                  className={clsx('w-full text-left px-3 py-2.5 rounded border text-xs transition-all',
                    selected?.id === t.id
                      ? 'bg-blue-900/30 border-blue-500/50 text-blue-200'
                      : 'bg-dark-700 border-slate-700/50 text-slate-300 hover:border-slate-500')}>
                  <div className="font-medium truncate">{t.name}</div>
                  <div className="text-slate-500 mt-0.5 flex items-center gap-2">
                    <span className="px-1 rounded bg-slate-700/50">{CAT_LABELS[t.category] ?? t.category}</span>
                    <span>{t.instruments.join(', ')}</span>
                  </div>
                </button>
              ))}
            </div>
        }
      </div>

      {/* Détail */}
      {selected ? (
        <div className="flex-1 overflow-y-auto space-y-4">
          <div className="bg-dark-700 rounded-lg p-4 border border-slate-700/40">
            <div className="flex items-start justify-between mb-2">
              <div>
                <h3 className="text-white font-semibold">{selected.name}</h3>
                <p className="text-slate-400 text-xs mt-1">{selected.description}</p>
              </div>
              <span className="text-xs px-2 py-1 rounded bg-purple-900/30 text-purple-300 border border-purple-700/40">
                v{selected.heuristic_ver}
              </span>
            </div>
            {selected.ai_rationale && (
              <div className="mt-3 p-3 bg-blue-900/10 border border-blue-800/30 rounded text-xs text-blue-200">
                <Brain className="w-3 h-3 inline mr-1.5 text-blue-400" />
                {selected.ai_rationale}
              </div>
            )}
            <div className="mt-3 flex gap-2 flex-wrap">
              {selected.instruments.map(i => (
                <span key={i} className="text-xs px-2 py-0.5 rounded bg-emerald-900/20 text-emerald-400 border border-emerald-700/30">
                  {i}
                </span>
              ))}
            </div>
          </div>

          <div className="bg-dark-700 rounded-lg p-4 border border-slate-700/40">
            <h4 className="text-slate-300 text-xs font-semibold mb-3 uppercase tracking-wider">Graphe causal</h4>
            <GraphSVG graph={selected.graph_json} />
          </div>

          <div className="bg-dark-700 rounded-lg p-4 border border-slate-700/40">
            <h4 className="text-slate-300 text-xs font-semibold mb-3 uppercase tracking-wider flex items-center gap-2">
              <Sliders className="w-3.5 h-3.5" /> Coefficients heuristiques
            </h4>
            <div className="space-y-3">
              {Object.entries(selected.graph_json?.coefficients || {}).map(([k, c]) => (
                <div key={k} className="grid grid-cols-[1fr_auto] gap-3 items-center">
                  <div>
                    <div className="text-xs text-slate-300 font-medium">{k}</div>
                    <div className="text-xs text-slate-500">{c.description}</div>
                  </div>
                  <input type="number" step="0.001"
                    value={editCoefs[k] ?? c.value}
                    onChange={e => setEditCoefs(p => ({ ...p, [k]: parseFloat(e.target.value) }))}
                    className="w-28 bg-dark-800 border border-slate-600 rounded px-2 py-1 text-xs text-slate-200 text-right" />
                </div>
              ))}
            </div>
            <button onClick={saveCoefs} disabled={saving}
              className="mt-4 px-4 py-2 bg-blue-600 hover:bg-blue-500 disabled:opacity-50 rounded text-xs font-medium text-white">
              {saving ? 'Sauvegarde…' : 'Sauvegarder les coefficients'}
            </button>
          </div>
        </div>
      ) : (
        <div className="flex-1 flex items-center justify-center text-slate-600 text-sm">
          Sélectionnez un template dans la liste
        </div>
      )}
    </div>
  )
}

// ── Tab Analyser ──────────────────────────────────────────────────────────────

function TabAnalyze() {
  const [events, setEvents]       = useState<MarketEvent[]>([])
  const [templates, setTemplates] = useState<Template[]>([])
  const [selEvent, setSelEvent]   = useState<MarketEvent | null>(null)
  const [selTmpl, setSelTmpl]     = useState<number>(0)
  const [instrument, setInstr]    = useState('EURUSD')
  const [manualInputs, setManual] = useState<Record<string, number>>({})
  const [result, setResult]       = useState<AnalysisResult | null>(null)
  const [rec, setRec]             = useState<Recommendation | null>(null)
  const [loadingRec, setLoadRec]  = useState(false)
  const [loadingAn, setLoadAn]    = useState(false)
  const [q, setQ]                 = useState('')
  const [catF, setCatF]           = useState('')
  const [error, setError]         = useState('')

  useEffect(() => {
    Promise.all([
      api(`/api/causal-lab/market-events?limit=200${catF ? `&category=${catF}` : ''}${q ? `&q=${encodeURIComponent(q)}` : ''}`),
      api('/api/causal-lab/templates'),
    ]).then(([evs, tmps]) => { setEvents(evs); setTemplates(tmps) })
  }, [catF, q])

  const currentTemplate = templates.find(t => t.id === selTmpl)
  const manualNodes = currentTemplate?.graph_json?.input_mapping
    ? Object.entries(currentTemplate.graph_json.input_mapping).filter(([, c]) => c.source === 'user_input')
    : []

  async function recommend() {
    if (!selEvent) return
    setLoadRec(true); setRec(null); setError('')
    try {
      const r = await api('/api/causal-lab/recommend', {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ market_event_id: selEvent.id }),
      })
      setRec(r.recommendation)
      if (r.recommendation?.template_id) setSelTmpl(r.recommendation.template_id)
    } catch (e: unknown) {
      setError(e instanceof Error ? e.message : String(e))
    } finally { setLoadRec(false) }
  }

  async function analyze() {
    if (!selEvent || !selTmpl) return
    setLoadAn(true); setResult(null); setError('')
    try {
      const r = await api('/api/causal-lab/analyze', {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          market_event_id: selEvent.id,
          template_id: selTmpl, instrument,
          inputs: manualInputs, coef_overrides: {},
        }),
      })
      setResult(r)
    } catch (e: unknown) {
      setError(e instanceof Error ? e.message : String(e))
    } finally { setLoadAn(false) }
  }

  return (
    <div className="flex gap-4">
      {/* Colonne gauche */}
      <div className="w-72 flex-shrink-0 space-y-3">
        <div className="flex gap-2">
          <div className="relative flex-1">
            <Search className="w-3.5 h-3.5 absolute left-2 top-2 text-slate-500" />
            <input value={q} onChange={e => setQ(e.target.value)} placeholder="Rechercher un événement…"
              className="w-full bg-dark-700 border border-slate-700 rounded pl-7 pr-2 py-1.5 text-xs text-slate-300" />
          </div>
          <select value={catF} onChange={e => setCatF(e.target.value)}
            className="bg-dark-700 border border-slate-700 rounded px-2 py-1.5 text-xs text-slate-300">
            <option value="">Tous</option>
            {Object.entries(CAT_LABELS).map(([k, v]) => <option key={k} value={k}>{v}</option>)}
          </select>
        </div>

        <div className="space-y-1 overflow-y-auto max-h-64 border border-slate-700/30 rounded-lg p-1">
          {events.length === 0
            ? <div className="text-slate-600 text-xs p-3 text-center">Aucun événement</div>
            : events.map(ev => (
              <button key={ev.id} onClick={() => { setSelEvent(ev); setResult(null); setRec(null) }}
                className={clsx('w-full text-left px-3 py-2 rounded border text-xs transition-all',
                  selEvent?.id === ev.id
                    ? 'bg-blue-900/30 border-blue-500/50 text-blue-200'
                    : 'bg-dark-700 border-slate-700/50 text-slate-300 hover:border-slate-500')}>
                <div className="font-medium truncate">{ev.name}</div>
                <div className="text-slate-500 flex justify-between">
                  <span>{ev.start_date?.slice(0, 10)}</span>
                  {ev.activation_score != null && (
                    <span className={clsx('font-semibold',
                      ev.activation_score >= 0.7 ? 'text-emerald-400' :
                      ev.activation_score >= 0.4 ? 'text-yellow-400' : 'text-red-400')}>
                      {(ev.activation_score * 100).toFixed(0)}%
                    </span>
                  )}
                </div>
              </button>
          ))}
        </div>

        <select value={selTmpl} onChange={e => setSelTmpl(Number(e.target.value))}
          className="w-full bg-dark-700 border border-slate-700 rounded px-2 py-2 text-xs text-slate-300">
          <option value={0}>— Choisir un template —</option>
          {templates.map(t => <option key={t.id} value={t.id}>{t.name}</option>)}
        </select>

        <select value={instrument} onChange={e => setInstr(e.target.value)}
          className="w-full bg-dark-700 border border-slate-700 rounded px-2 py-2 text-xs text-slate-300">
          {['EURUSD', 'XAUUSD', 'SP500', 'BRENT'].map(i => <option key={i} value={i}>{i}</option>)}
        </select>

        {manualNodes.length > 0 && (
          <div className="bg-dark-800 rounded p-3 space-y-2 border border-slate-700/30">
            <div className="text-xs text-slate-400 font-semibold">Inputs manuels</div>
            {manualNodes.map(([id, cfg]) => {
              const range = cfg.range as [number, number] | undefined
              return (
                <div key={id} className="flex items-center gap-2">
                  <span className="text-xs text-slate-400 flex-1 capitalize">{id.replace(/_/g, ' ')}</span>
                  <input type="range" min={range?.[0] ?? -3} max={range?.[1] ?? 3} step={0.5}
                    value={manualInputs[id] ?? 0}
                    onChange={e => setManual(p => ({ ...p, [id]: parseFloat(e.target.value) }))}
                    className="w-24" />
                  <span className="text-xs text-slate-300 w-8 text-right">
                    {(manualInputs[id] ?? 0) > 0 ? '+' : ''}{manualInputs[id] ?? 0}
                  </span>
                </div>
              )
            })}
          </div>
        )}

        <button onClick={recommend} disabled={!selEvent || loadingRec}
          className="w-full flex items-center justify-center gap-2 px-3 py-2 bg-purple-700/50 hover:bg-purple-700 disabled:opacity-40 rounded text-xs font-medium text-purple-200 border border-purple-700/40">
          <Brain className="w-3.5 h-3.5" />
          {loadingRec ? 'GPT-4o analyse…' : 'Recommandation GPT-4o'}
        </button>
        <button onClick={analyze} disabled={!selEvent || !selTmpl || loadingAn}
          className="w-full flex items-center justify-center gap-2 px-3 py-2 bg-blue-600 hover:bg-blue-500 disabled:opacity-40 rounded text-xs font-medium text-white">
          <Zap className="w-3.5 h-3.5" />
          {loadingAn ? 'Analyse…' : 'Lancer l\'analyse'}
        </button>

        {error && (
          <div className="p-3 bg-red-900/20 border border-red-700/40 rounded text-xs text-red-300">{error}</div>
        )}
      </div>

      {/* Colonne droite: résultats */}
      <div className="flex-1 space-y-4 min-w-0">
        {/* Recommandation IA */}
        {rec && (
          <div className="bg-purple-900/10 border border-purple-700/30 rounded-lg p-4">
            <div className="flex items-center gap-2 mb-2">
              <Brain className="w-4 h-4 text-purple-400" />
              <span className="text-sm font-semibold text-purple-200">Recommandation GPT-4o</span>
              {rec.confidence != null && (
                <span className="ml-auto text-xs text-purple-400 font-bold">
                  {(rec.confidence * 100).toFixed(0)}% confiance
                </span>
              )}
            </div>
            {rec.error
              ? <div className="text-red-400 text-xs">{rec.error}</div>
              : <>
                  <div className="text-sm text-white font-medium mb-1">Template : {rec.template_name}</div>
                  <p className="text-xs text-purple-200/80">{rec.rationale}</p>
                  {rec.notes && <p className="text-xs text-slate-400 mt-1">{rec.notes}</p>}
                  {Object.keys(rec.coefficient_suggestions || {}).length > 0 && (
                    <div className="mt-2 flex flex-wrap gap-2">
                      {Object.entries(rec.coefficient_suggestions).map(([k, v]) => (
                        <span key={k} className="text-xs px-2 py-0.5 bg-purple-900/30 text-purple-300 rounded border border-purple-700/30">
                          {k} = {v}
                        </span>
                      ))}
                    </div>
                  )}
                </>
            }
          </div>
        )}

        {/* Résultat */}
        {result && (
          <>
            <div className="bg-dark-700 rounded-lg p-4 border border-slate-700/40">
              <div className="flex items-center justify-between mb-3">
                <h3 className="text-white font-semibold text-sm">{result.event.name}</h3>
                <div className="flex items-center gap-3">
                  <span className="text-xs text-slate-400">{result.event.start_date?.slice(0, 10)}</span>
                  <span className={clsx('text-sm font-bold px-3 py-1 rounded',
                    result.activation.score == null          ? 'text-slate-400 bg-slate-800' :
                    result.activation.score >= 0.7           ? 'text-emerald-400 bg-emerald-900/30' :
                    result.activation.score >= 0.4           ? 'text-yellow-400 bg-yellow-900/30' :
                                                               'text-red-400 bg-red-900/30')}>
                    {result.activation.score != null
                      ? `${(result.activation.score * 100).toFixed(0)}% activation`
                      : 'N/A'}
                  </span>
                </div>
              </div>

              <div className="grid grid-cols-4 gap-3 mb-3">
                {[
                  { label: 'Pré-drift', val: fmtPips(result.drift?.pre_pips) },
                  { label: 'Réel post', val: fmtPips(result.drift?.post_pips) },
                  { label: 'Mode prix', val: result.prices_mode },
                  { label: 'Fuite info', val: result.drift?.leak ?? '—' },
                ].map(m => (
                  <div key={m.label} className="bg-dark-800 rounded p-3 text-center">
                    <div className="text-xs text-slate-500">{m.label}</div>
                    <div className="text-sm font-bold text-slate-200 mt-0.5">{m.val}</div>
                  </div>
                ))}
              </div>

              <div className="flex flex-wrap gap-2">
                {Object.entries(result.activation.nodes).map(([id, node]) => {
                  const Icon = node.status === 'correct' ? CheckCircle : node.status === 'wrong' ? XCircle : Minus
                  const col =
                    node.status === 'correct' ? 'text-emerald-400 border-emerald-700/40 bg-emerald-900/10' :
                    node.status === 'wrong'   ? 'text-red-400 border-red-700/40 bg-red-900/10' :
                    'text-slate-500 border-slate-700/40 bg-slate-800/30'
                  return (
                    <div key={id} className={clsx('flex items-center gap-1.5 px-3 py-1.5 rounded border text-xs', col)}>
                      <Icon className="w-3.5 h-3.5" />
                      <span>{node.label}</span>
                      {node.pred != null && (
                        <span className="opacity-70">
                          P:{node.pred > 0 ? '+' : ''}{node.pred.toFixed(1)} /
                          A:{node.act != null ? (node.act > 0 ? '+' : '') + node.act.toFixed(1) : '—'}
                        </span>
                      )}
                    </div>
                  )
                })}
              </div>
            </div>

            <div className="bg-dark-700 rounded-lg p-4 border border-slate-700/40">
              <h4 className="text-slate-300 text-xs font-semibold mb-3 uppercase tracking-wider">
                Graphe causal — valeurs calculées
              </h4>
              {currentTemplate && (
                <GraphSVG graph={currentTemplate.graph_json}
                  nodeValues={result.node_values}
                  activationNodes={result.activation.nodes} />
              )}
            </div>

            {result.yields && (
              <div className="bg-dark-700 rounded-lg p-4 border border-slate-700/40">
                <h4 className="text-slate-300 text-xs font-semibold mb-3 uppercase tracking-wider">
                  Taux réels
                </h4>
                <div className="grid grid-cols-3 gap-3">
                  {[
                    { label: 'US 10Y', v: result.yields.us10y },
                    { label: 'EU 10Y', v: result.yields.eu10y },
                    { label: 'US 2Y',  v: result.yields.us2y  },
                  ].map(y => (
                    <div key={y.label} className="bg-dark-800 rounded p-3 text-center">
                      <div className="text-xs text-slate-500">{y.label}</div>
                      <div className={clsx('text-sm font-bold mt-0.5',
                        y.v == null ? 'text-slate-600' : y.v > 0 ? 'text-red-400' : 'text-emerald-400')}>
                        {y.v == null ? '—' : `${y.v > 0 ? '+' : ''}${y.v.toFixed(3)}%`}
                      </div>
                    </div>
                  ))}
                </div>
              </div>
            )}
          </>
        )}

        {(loadingAn || loadingRec) && (
          <div className="flex items-center justify-center h-48 text-slate-500 gap-3">
            <RefreshCw className="w-5 h-5 animate-spin" />
            <span className="text-sm">
              {loadingAn ? 'Récupération des prix (yfinance)…' : 'GPT-4o en cours…'}
            </span>
          </div>
        )}

        {!result && !loadingAn && !loadingRec && !rec && (
          <div className="flex flex-col items-center justify-center h-64 text-slate-600 space-y-3">
            <FlaskConical className="w-12 h-12 opacity-30" />
            <div className="text-sm text-center">
              Sélectionnez un événement, choisissez un template et lancez l'analyse
            </div>
          </div>
        )}
      </div>
    </div>
  )
}

// ── Tab Calibration ───────────────────────────────────────────────────────────

function TabCalibration() {
  const [data, setData]   = useState<CalibRow[]>([])
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    api('/api/causal-lab/calibration').then(setData).finally(() => setLoading(false))
  }, [])

  if (loading) return <div className="text-slate-500 text-sm p-6">Chargement…</div>

  return (
    <div className="space-y-3">
      <div className="text-xs text-slate-500 flex items-center gap-2">
        <AlertCircle className="w-3.5 h-3.5" />
        Statistiques agrégées de toutes les analyses par template.
        Le ratio pred/réel converge vers 1.0 quand les coefficients sont bien calibrés.
      </div>
      <div className="overflow-x-auto">
        <table className="w-full text-xs">
          <thead>
            <tr className="border-b border-slate-700/50">
              {['Template', 'Catégorie', 'Nb analyses', 'Activation moy.', 'Pred. moy. (pip)', 'Réel moy. (pip)', 'Ratio'].map(h => (
                <th key={h} className="px-3 py-2 text-left text-slate-500 uppercase tracking-wider font-medium">{h}</th>
              ))}
            </tr>
          </thead>
          <tbody>
            {data.map(row => {
              const calib = row.calibration || {}
              const instKey = Object.keys(calib).find(k =>
                !['n_events', 'avg_activation', 'last_analyzed'].includes(k))
              const instData = instKey ? calib[instKey] : null
              return (
                <tr key={row.id} className="border-b border-slate-800/50 hover:bg-dark-700/30 transition-colors">
                  <td className="px-3 py-2.5 text-slate-200 font-medium">{row.name}</td>
                  <td className="px-3 py-2.5 text-slate-400">{CAT_LABELS[row.category] ?? row.category}</td>
                  <td className="px-3 py-2.5 text-slate-300">{row.n_analyses}</td>
                  <td className="px-3 py-2.5">
                    {row.avg_activation != null
                      ? <span className={clsx('font-bold',
                          row.avg_activation >= 0.7 ? 'text-emerald-400' :
                          row.avg_activation >= 0.4 ? 'text-yellow-400' : 'text-red-400')}>
                          {(row.avg_activation * 100).toFixed(0)}%
                        </span>
                      : <span className="text-slate-600">—</span>}
                  </td>
                  <td className="px-3 py-2.5 text-slate-300">{instData?.avg_pred?.toFixed(1) ?? '—'}</td>
                  <td className="px-3 py-2.5 text-slate-300">{instData?.avg_actual?.toFixed(1) ?? '—'}</td>
                  <td className="px-3 py-2.5">
                    {instData?.coef_ratio != null
                      ? <span className={clsx('font-bold',
                          Math.abs(instData.coef_ratio - 1) < 0.2 ? 'text-emerald-400' :
                          Math.abs(instData.coef_ratio - 1) < 0.5 ? 'text-yellow-400' : 'text-red-400')}>
                          {instData.coef_ratio.toFixed(2)}x
                        </span>
                      : <span className="text-slate-600">—</span>}
                  </td>
                </tr>
              )
            })}
          </tbody>
        </table>
        {data.length === 0 && (
          <div className="text-center py-12 text-slate-600 text-sm">
            Aucune analyse effectuée pour l'instant. Lancez des analyses dans l'onglet "Analyser".
          </div>
        )}
      </div>
    </div>
  )
}

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

const TABS = [
  { id: 'library', label: 'Bibliothèque',  icon: Library     },
  { id: 'analyze', label: 'Analyser',      icon: FlaskConical },
  { id: 'calib',   label: 'Calibration',   icon: BarChart3   },
]

export default function CausalLab() {
  const [tab, setTab] = useState('library')

  return (
    <div className="p-6 min-h-screen">
      <div className="flex items-center gap-3 mb-6">
        <FlaskConical className="w-6 h-6 text-blue-400" />
        <div>
          <h1 className="text-xl font-bold text-white">Lab Causal</h1>
          <p className="text-slate-400 text-xs mt-0.5">
            Bibliothèque de graphes causaux · Analyse empirique · Calibration IA
          </p>
        </div>
      </div>

      <div className="flex gap-1 mb-6 bg-dark-800 p-1 rounded-lg w-fit border border-slate-700/30">
        {TABS.map(({ id, label, icon: Icon }) => (
          <button key={id} onClick={() => setTab(id)}
            className={clsx('flex items-center gap-2 px-4 py-2 rounded text-sm font-medium transition-all',
              tab === id ? 'bg-blue-600 text-white' : 'text-slate-400 hover:text-slate-200')}>
            <Icon className="w-4 h-4" />
            {label}
          </button>
        ))}
      </div>

      <div className="bg-dark-800 rounded-xl p-5 border border-slate-700/30">
        {tab === 'library' && <TabLibrary />}
        {tab === 'analyze' && <TabAnalyze />}
        {tab === 'calib'   && <TabCalibration />}
      </div>
    </div>
  )
}
