import { useState, useEffect, useCallback, useRef } from 'react'
import {
  Search, RefreshCw, Plus, Trash2, Edit3, Sparkles, ExternalLink,
  ChevronDown, ChevronUp, Loader2, CheckCircle, AlertCircle, X,
  SlidersHorizontal, BarChart2, Star, Users
} from 'lucide-react'
import clsx from 'clsx'

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

interface SourceRef {
  title: string
  source: string
  url: string
  date: string
  original_score: number
}

interface InstrumentImpact {
  id: number
  instrument_id: string
  impact_score: number
  direction: 'bullish' | 'bearish' | 'neutral' | 'depends_on_outcome'
  rationale: string
  confidence: number
  ai_generated: number
  manually_adjusted: number
  adjusted_score: number | null
  adjusted_direction: string | null
  override_rationale: string
}

interface MarketEvent {
  id: number
  name: string
  start_date: string
  end_date: string | null
  level: 'long' | 'medium' | 'short'
  category: string
  sub_type: string
  description: string
  market_impact: string
  affected_assets: string[]
  impact_score: number
  absorption_pct: number | null
  source_refs: SourceRef[]
  impacts?: InstrumentImpact[]
  evaluated?: boolean
}

// ── Constants ─────────────────────────────────────────────────────────────────

const CAT_COLORS: Record<string, string> = {
  event_calendar: 'bg-amber-500/20 text-amber-300 border-amber-500/30',
  geopolitical:   'bg-red-500/20 text-red-300 border-red-500/30',
  fundamental:    'bg-emerald-500/20 text-emerald-300 border-emerald-500/30',
  report:         'bg-blue-500/20 text-blue-300 border-blue-500/30',
  sentiment:      'bg-purple-500/20 text-purple-300 border-purple-500/30',
  technical:      'bg-cyan-500/20 text-cyan-300 border-cyan-500/30',
}
const CAT_DOT: Record<string, string> = {
  event_calendar: 'bg-amber-400',
  geopolitical:   'bg-red-400',
  fundamental:    'bg-emerald-400',
  report:         'bg-blue-400',
  sentiment:      'bg-purple-400',
  technical:      'bg-cyan-400',
}
const LEVEL_COLORS: Record<string, string> = {
  long:   'text-purple-400',
  medium: 'text-amber-400',
  short:  'text-emerald-400',
}
const DIR_COLORS: Record<string, string> = {
  bullish:            'text-emerald-400',
  bearish:            'text-red-400',
  neutral:            'text-slate-400',
  depends_on_outcome: 'text-amber-400',
}
const DIR_ICONS: Record<string, string> = {
  bullish: '▲', bearish: '▼', neutral: '●', depends_on_outcome: '◆',
}

const CATEGORIES = ['event_calendar', 'geopolitical', 'fundamental', 'report', 'sentiment', 'technical']
const LEVELS     = ['long', 'medium', 'short']
const ALL_INSTRUMENTS = [
  'SPY','QQQ','IWM','EEM','EFA','GLD','SLV','USO','UNG','TLT',
  'HYG','EURUSD=X','USDJPY=X','GBPUSD=X','VXX','AAPL','NVDA','GS','XOM','BTC-USD',
]

// ── Helpers ───────────────────────────────────────────────────────────────────

function ScoreBar({ score, max = 1 }: { score: number; max?: number }) {
  const pct = Math.round((score / max) * 100)
  const color = score >= 0.7 ? 'bg-red-500' : score >= 0.5 ? 'bg-amber-500' : 'bg-emerald-500'
  return (
    <div className="flex items-center gap-2">
      <div className="flex-1 h-1.5 bg-slate-700 rounded-full overflow-hidden">
        <div className={`h-full rounded-full ${color}`} style={{ width: `${pct}%` }} />
      </div>
      <span className="text-xs text-slate-400 w-8 text-right">{score.toFixed(2)}</span>
    </div>
  )
}

function CatBadge({ cat }: { cat: string }) {
  return (
    <span className={clsx('inline-flex items-center gap-1 px-2 py-0.5 rounded border text-xs font-medium', CAT_COLORS[cat] ?? 'bg-slate-700/50 text-slate-400 border-slate-700')}>
      <span className={clsx('w-1.5 h-1.5 rounded-full', CAT_DOT[cat] ?? 'bg-slate-400')} />
      {cat.replace('_', ' ')}
    </span>
  )
}

// ── Instrument impact row (inline editable) ───────────────────────────────────

function ImpactRow({
  imp, eventId, onUpdated, onDeleted,
}: {
  imp: InstrumentImpact
  eventId: number
  onUpdated: () => void
  onDeleted: () => void
}) {
  const [editing, setEditing] = useState(false)
  const [score, setScore]     = useState(String(imp.adjusted_score ?? imp.impact_score))
  const [dir, setDir]         = useState(imp.adjusted_direction || imp.direction)
  const [note, setNote]       = useState(imp.override_rationale || '')
  const [saving, setSaving]   = useState(false)

  const effectiveScore = imp.adjusted_score ?? imp.impact_score
  const effectiveDir   = imp.adjusted_direction || imp.direction

  const save = async () => {
    setSaving(true)
    await fetch(`/api/market-events/${eventId}/impacts/${imp.id}`, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ adjusted_score: +score, adjusted_direction: dir, override_rationale: note }),
    })
    setSaving(false)
    setEditing(false)
    onUpdated()
  }

  const del = async () => {
    if (!confirm(`Supprimer l'impact sur ${imp.instrument_id} ?`)) return
    await fetch(`/api/market-events/${eventId}/impacts/${imp.id}`, { method: 'DELETE' })
    onDeleted()
  }

  return (
    <div className="border-b border-slate-800/60 last:border-0">
      <div className="flex items-center gap-3 py-2 px-3 hover:bg-slate-800/20">
        {/* Ticker */}
        <span className="font-mono text-sm text-slate-200 w-24 shrink-0">{imp.instrument_id}</span>
        {/* Direction */}
        <span className={clsx('text-sm font-bold w-6 shrink-0', DIR_COLORS[effectiveDir])}>
          {DIR_ICONS[effectiveDir] ?? '●'}
        </span>
        {/* Score bar */}
        <div className="w-28 shrink-0">
          <ScoreBar score={effectiveScore} />
        </div>
        {/* Confidence */}
        <span className="text-xs text-slate-500 w-10 shrink-0">{Math.round(imp.confidence * 100)}%</span>
        {/* Rationale */}
        <span className="text-xs text-slate-400 flex-1 min-w-0 truncate">{imp.rationale}</span>
        {/* AI badge */}
        {imp.ai_generated ? (
          <span className="text-xs text-blue-400 shrink-0">AI</span>
        ) : (
          <span className="text-xs text-slate-600 shrink-0">manual</span>
        )}
        {imp.manually_adjusted ? <span className="text-xs text-amber-400 shrink-0">adj.</span> : null}
        {/* Actions */}
        <button onClick={() => setEditing(x => !x)} className="text-slate-500 hover:text-slate-300 shrink-0"><Edit3 size={12} /></button>
        <button onClick={del} className="text-slate-600 hover:text-red-400 shrink-0"><Trash2 size={12} /></button>
      </div>
      {editing && (
        <div className="px-3 pb-3 grid grid-cols-3 gap-2 bg-slate-800/30">
          <label className="flex flex-col gap-1">
            <span className="text-xs text-slate-500">Score ajusté</span>
            <input type="range" min="0" max="1" step="0.05"
              value={score} onChange={e => setScore(e.target.value)}
              className="w-full accent-amber-400" />
            <span className="text-xs text-center text-amber-300">{(+score).toFixed(2)}</span>
          </label>
          <label className="flex flex-col gap-1">
            <span className="text-xs text-slate-500">Direction</span>
            <select value={dir} onChange={e => setDir(e.target.value)}
              className="bg-dark-900 border border-slate-700 rounded px-2 py-1 text-slate-200 text-sm">
              {['bullish','bearish','neutral','depends_on_outcome'].map(d => (
                <option key={d} value={d}>{d}</option>
              ))}
            </select>
          </label>
          <label className="flex flex-col gap-1">
            <span className="text-xs text-slate-500">Note</span>
            <input value={note} onChange={e => setNote(e.target.value)}
              className="bg-dark-900 border border-slate-700 rounded px-2 py-1 text-slate-200 text-sm"
              placeholder="Raison de l'ajustement..." />
          </label>
          <div className="col-span-3 flex gap-2 mt-1">
            <button onClick={save} disabled={saving}
              className="flex items-center gap-1 bg-emerald-700 hover:bg-emerald-600 text-white text-xs rounded px-3 py-1">
              {saving ? <Loader2 size={11} className="animate-spin" /> : <CheckCircle size={11} />}
              Sauvegarder
            </button>
            <button onClick={() => setEditing(false)} className="text-xs text-slate-500 hover:text-slate-300 px-2">Annuler</button>
          </div>
        </div>
      )}
    </div>
  )
}

// ── Add instrument panel ──────────────────────────────────────────────────────

function AddInstrumentPanel({ eventId, onAdded }: { eventId: number; onAdded: () => void }) {
  const [open, setOpen]     = useState(false)
  const [ticker, setTicker] = useState('')
  const [score, setScore]   = useState(0.5)
  const [dir, setDir]       = useState('neutral')
  const [rationale, setRat] = useState('')
  const [saving, setSaving] = useState(false)

  const submit = async () => {
    if (!ticker) return
    setSaving(true)
    await fetch(`/api/market-events/${eventId}/impacts`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ instrument_id: ticker, impact_score: score, direction: dir, rationale, confidence: 0.8 }),
    })
    setSaving(false)
    setOpen(false)
    setTicker('')
    setRat('')
    onAdded()
  }

  if (!open) {
    return (
      <button onClick={() => setOpen(true)}
        className="flex items-center gap-1.5 text-xs text-slate-500 hover:text-emerald-400 py-2 px-3 border-t border-slate-800/60">
        <Plus size={12} /> Ajouter instrument
      </button>
    )
  }

  return (
    <div className="border-t border-slate-800/60 px-3 py-3 bg-slate-800/30 grid grid-cols-4 gap-2">
      <select value={ticker} onChange={e => setTicker(e.target.value)}
        className="bg-dark-900 border border-slate-700 rounded px-2 py-1 text-slate-200 text-sm col-span-1">
        <option value="">Ticker...</option>
        {ALL_INSTRUMENTS.map(t => <option key={t} value={t}>{t}</option>)}
      </select>
      <select value={dir} onChange={e => setDir(e.target.value)}
        className="bg-dark-900 border border-slate-700 rounded px-2 py-1 text-slate-200 text-sm">
        {['bullish','bearish','neutral','depends_on_outcome'].map(d => <option key={d} value={d}>{d}</option>)}
      </select>
      <div className="flex flex-col gap-0.5">
        <input type="range" min="0" max="1" step="0.05" value={score}
          onChange={e => setScore(+e.target.value)} className="accent-emerald-400" />
        <span className="text-xs text-center text-emerald-300">{score.toFixed(2)}</span>
      </div>
      <input value={rationale} onChange={e => setRat(e.target.value)} placeholder="Rationale..."
        className="bg-dark-900 border border-slate-700 rounded px-2 py-1 text-slate-200 text-sm" />
      <div className="col-span-4 flex gap-2">
        <button onClick={submit} disabled={saving || !ticker}
          className="flex items-center gap-1 bg-emerald-700 hover:bg-emerald-600 disabled:bg-slate-700 disabled:text-slate-500 text-white text-xs rounded px-3 py-1">
          {saving ? <Loader2 size={11} className="animate-spin" /> : <Plus size={11} />} Ajouter
        </button>
        <button onClick={() => setOpen(false)} className="text-xs text-slate-500 hover:text-slate-300 px-2">Annuler</button>
      </div>
    </div>
  )
}

// ── Event detail panel (right side) ──────────────────────────────────────────

function EventDetail({
  event, onClose, onUpdated, onDeleted,
}: {
  event: MarketEvent
  onClose: () => void
  onUpdated: (ev: MarketEvent) => void
  onDeleted: (id: number) => void
}) {
  const [detail, setDetail]       = useState<MarketEvent>(event)
  const [evaluating, setEval]     = useState(false)
  const [evalMsg, setEvalMsg]     = useState<string | null>(null)
  const [editing, setEditing]     = useState(false)
  const [editData, setEditData]   = useState<Partial<MarketEvent>>({})
  const [saving, setSaving]       = useState(false)

  const loadDetail = useCallback(async () => {
    const r = await fetch(`/api/market-events/${event.id}`)
    if (r.ok) {
      const d = await r.json()
      setDetail(d)
    }
  }, [event.id])

  useEffect(() => { loadDetail() }, [loadDetail])

  const evaluate = async (force = false) => {
    setEval(true)
    setEvalMsg(null)
    try {
      const r = await fetch(`/api/market-events/${event.id}/evaluate?force=${force}`, { method: 'POST' })
      const d = await r.json()
      if (!r.ok) throw new Error(d.detail || r.statusText)
      setEvalMsg(`✓ ${d.n_instruments} instruments évalués`)
      await loadDetail()
    } catch (e: any) {
      setEvalMsg(`✗ ${e.message}`)
    } finally {
      setEval(false)
    }
  }

  const saveEdit = async () => {
    setSaving(true)
    const payload = { ...detail, ...editData, source_refs: detail.source_refs ?? [] }
    const r = await fetch(`/api/market-events/${event.id}`, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload),
    })
    setSaving(false)
    if (r.ok) {
      setEditing(false)
      await loadDetail()
      onUpdated({ ...detail, ...editData } as MarketEvent)
    }
  }

  const del = async () => {
    if (!confirm(`Supprimer "${detail.name}" ?`)) return
    await fetch(`/api/market-events/${event.id}`, { method: 'DELETE' })
    onDeleted(event.id)
    onClose()
  }

  const impacts = detail.impacts || []
  const evalScore = detail.impact_score

  return (
    <div className="flex flex-col h-full overflow-hidden">
      {/* Header */}
      <div className="flex items-start gap-3 px-5 py-4 border-b border-slate-700/40 shrink-0">
        <div className="flex-1 min-w-0">
          {editing ? (
            <input
              defaultValue={detail.name}
              onChange={e => setEditData(d => ({ ...d, name: e.target.value }))}
              className="bg-dark-900 border border-amber-500/50 rounded px-3 py-1.5 text-slate-100 font-bold text-sm w-full"
            />
          ) : (
            <h2 className="text-slate-100 font-bold text-sm leading-snug">{detail.name}</h2>
          )}
          <div className="flex items-center gap-2 mt-1.5 flex-wrap">
            <CatBadge cat={detail.category} />
            {detail.sub_type && <span className="text-xs text-slate-500">{detail.sub_type}</span>}
            <span className={clsx('text-xs font-semibold', LEVEL_COLORS[detail.level])}>{detail.level}</span>
            <span className="text-xs text-slate-500">{detail.start_date}</span>
            {detail.end_date && <span className="text-xs text-slate-600">→ {detail.end_date}</span>}
          </div>
        </div>
        <div className="flex items-center gap-1.5 shrink-0">
          <button onClick={() => { setEditing(x => !x); setEditData({}) }}
            className={clsx('p-1.5 rounded hover:bg-slate-700/50', editing ? 'text-amber-400' : 'text-slate-500 hover:text-slate-300')}>
            <Edit3 size={14} />
          </button>
          <button onClick={del} className="p-1.5 rounded text-slate-600 hover:text-red-400 hover:bg-red-900/20">
            <Trash2 size={14} />
          </button>
          <button onClick={onClose} className="p-1.5 rounded text-slate-500 hover:text-slate-300 hover:bg-slate-700/50">
            <X size={14} />
          </button>
        </div>
      </div>

      {/* Scrollable body */}
      <div className="flex-1 overflow-y-auto space-y-4 px-5 py-4">

        {/* Impact score + absorption */}
        <div className="grid grid-cols-2 gap-3">
          <div className="bg-slate-800/40 rounded-lg p-3">
            <div className="text-xs text-slate-500 mb-1">Score impact</div>
            <ScoreBar score={evalScore} />
          </div>
          {detail.absorption_pct != null && (
            <div className="bg-slate-800/40 rounded-lg p-3">
              <div className="text-xs text-slate-500 mb-1">Absorption marché</div>
              <div className="flex items-center gap-2">
                <div className="flex-1 h-1.5 bg-slate-700 rounded-full overflow-hidden">
                  <div className="h-full bg-blue-500 rounded-full" style={{ width: `${detail.absorption_pct}%` }} />
                </div>
                <span className="text-xs text-blue-300">{detail.absorption_pct}%</span>
              </div>
            </div>
          )}
        </div>

        {/* Description */}
        {editing ? (
          <textarea
            defaultValue={detail.description}
            onChange={e => setEditData(d => ({ ...d, description: e.target.value }))}
            rows={3}
            className="w-full bg-dark-900 border border-slate-700 rounded px-3 py-2 text-slate-300 text-sm resize-none"
          />
        ) : detail.description ? (
          <p className="text-sm text-slate-300 leading-relaxed">{detail.description}</p>
        ) : null}

        {editing ? (
          <div className="grid grid-cols-3 gap-2">
            <div>
              <div className="text-xs text-slate-500 mb-1">Catégorie</div>
              <select defaultValue={detail.category}
                onChange={e => setEditData(d => ({ ...d, category: e.target.value }))}
                className="w-full bg-dark-900 border border-slate-700 rounded px-2 py-1 text-slate-200 text-sm">
                {CATEGORIES.map(c => <option key={c} value={c}>{c}</option>)}
              </select>
            </div>
            <div>
              <div className="text-xs text-slate-500 mb-1">Niveau</div>
              <select defaultValue={detail.level}
                onChange={e => setEditData(d => ({ ...d, level: e.target.value as any }))}
                className="w-full bg-dark-900 border border-slate-700 rounded px-2 py-1 text-slate-200 text-sm">
                {LEVELS.map(l => <option key={l} value={l}>{l}</option>)}
              </select>
            </div>
            <div>
              <div className="text-xs text-slate-500 mb-1">Score impact</div>
              <input type="number" step="0.05" min="0" max="1" defaultValue={detail.impact_score}
                onChange={e => setEditData(d => ({ ...d, impact_score: +e.target.value }))}
                className="w-full bg-dark-900 border border-slate-700 rounded px-2 py-1 text-slate-200 text-sm" />
            </div>
          </div>
        ) : null}

        {editing && (
          <div className="flex gap-2">
            <button onClick={saveEdit} disabled={saving}
              className="flex items-center gap-1.5 bg-emerald-700 hover:bg-emerald-600 text-white text-sm rounded-lg px-4 py-1.5">
              {saving ? <Loader2 size={13} className="animate-spin" /> : <CheckCircle size={13} />} Sauvegarder
            </button>
            <button onClick={() => setEditing(false)} className="text-sm text-slate-500 hover:text-slate-300 px-3">Annuler</button>
          </div>
        )}

        {/* Sources */}
        {(detail.source_refs?.length ?? 0) > 0 && (
          <div>
            <div className="text-xs text-slate-500 uppercase tracking-wide mb-2">Sources</div>
            <div className="space-y-1.5">
              {detail.source_refs!.map((ref, i) => (
                <div key={i} className="flex items-start gap-2 bg-slate-800/40 rounded-lg px-3 py-2">
                  <div className="flex-1 min-w-0">
                    <div className="text-xs text-slate-200 font-medium truncate">{ref.title}</div>
                    <div className="flex items-center gap-2 mt-0.5">
                      <span className="text-xs text-slate-500">{ref.source}</span>
                      <span className="text-xs text-slate-600">{ref.date}</span>
                      <span className="text-xs text-slate-600">score brut: {ref.original_score?.toFixed(2)}</span>
                    </div>
                  </div>
                  {ref.url && (
                    <a href={ref.url} target="_blank" rel="noreferrer"
                      className="text-slate-500 hover:text-blue-400 shrink-0 mt-0.5">
                      <ExternalLink size={12} />
                    </a>
                  )}
                </div>
              ))}
            </div>
          </div>
        )}

        {/* Instrument impacts */}
        <div>
          <div className="flex items-center justify-between mb-2">
            <div className="text-xs text-slate-500 uppercase tracking-wide">
              Impacts instruments
              <span className="text-slate-600 ml-1.5 normal-case">({impacts.length})</span>
            </div>
            <div className="flex items-center gap-2">
              {evalMsg && (
                <span className={clsx('text-xs', evalMsg.startsWith('✓') ? 'text-emerald-400' : 'text-red-400')}>
                  {evalMsg}
                </span>
              )}
              <button
                onClick={() => evaluate(impacts.length > 0)}
                disabled={evaluating}
                className="flex items-center gap-1.5 text-xs bg-blue-700/40 hover:bg-blue-700/60 border border-blue-700/50 text-blue-300 rounded px-3 py-1"
              >
                {evaluating ? <Loader2 size={11} className="animate-spin" /> : <Sparkles size={11} />}
                {impacts.length > 0 ? 'Ré-analyser' : 'Analyser IA'}
              </button>
            </div>
          </div>

          {impacts.length === 0 ? (
            <div className="text-xs text-slate-600 italic py-3 px-3 bg-slate-800/30 rounded-lg">
              Aucun impact évalué — cliquez sur "Analyser IA" pour lancer l'évaluation.
            </div>
          ) : (
            <div className="bg-slate-800/30 rounded-lg overflow-hidden">
              {/* Header */}
              <div className="grid text-xs text-slate-600 px-3 py-1.5 border-b border-slate-800 bg-slate-800/50"
                style={{ gridTemplateColumns: '6rem 1.5rem 8rem 2.5rem 1fr 3rem 3rem 1.5rem 1.5rem' }}>
                <span>Instrument</span>
                <span></span>
                <span>Score</span>
                <span>Conf.</span>
                <span>Rationale</span>
                <span></span>
                <span></span>
                <span></span>
                <span></span>
              </div>
              {impacts
                .slice()
                .sort((a, b) => (b.adjusted_score ?? b.impact_score) - (a.adjusted_score ?? a.impact_score))
                .map(imp => (
                  <ImpactRow
                    key={imp.id}
                    imp={imp}
                    eventId={detail.id}
                    onUpdated={loadDetail}
                    onDeleted={loadDetail}
                  />
                ))}
              <AddInstrumentPanel eventId={detail.id} onAdded={loadDetail} />
            </div>
          )}
          {impacts.length === 0 && (
            <div className="mt-2">
              <AddInstrumentPanel eventId={detail.id} onAdded={loadDetail} />
            </div>
          )}
        </div>
      </div>
    </div>
  )
}

// ── Create event modal ────────────────────────────────────────────────────────

function CreateModal({ onCreated, onClose }: { onCreated: () => void; onClose: () => void }) {
  const [form, setForm] = useState({
    name: '', start_date: new Date().toISOString().slice(0, 10),
    category: 'fundamental', level: 'short', sub_type: '',
    description: '', impact_score: 0.5,
  })
  const [saving, setSaving] = useState(false)

  const submit = async () => {
    if (!form.name || !form.start_date) return
    setSaving(true)
    await fetch('/api/market-events', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ ...form, source_refs: [] }),
    })
    setSaving(false)
    onCreated()
    onClose()
  }

  const f = (k: string) => (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) =>
    setForm(d => ({ ...d, [k]: e.target.value }))

  return (
    <div className="fixed inset-0 bg-black/60 z-50 flex items-center justify-center">
      <div className="bg-dark-800 border border-slate-700/50 rounded-xl w-full max-w-lg shadow-2xl">
        <div className="flex items-center justify-between px-5 py-4 border-b border-slate-700/40">
          <h3 className="text-slate-100 font-semibold">Nouvel événement marché</h3>
          <button onClick={onClose} className="text-slate-500 hover:text-slate-300"><X size={16} /></button>
        </div>
        <div className="p-5 space-y-3">
          <input value={form.name} onChange={f('name')} placeholder="Nom de l'événement *"
            className="w-full bg-dark-900 border border-slate-700 rounded px-3 py-2 text-slate-200 text-sm" />
          <div className="grid grid-cols-2 gap-3">
            <div>
              <div className="text-xs text-slate-500 mb-1">Date début</div>
              <input type="date" value={form.start_date} onChange={f('start_date')}
                className="w-full bg-dark-900 border border-slate-700 rounded px-3 py-2 text-slate-200 text-sm" />
            </div>
            <div>
              <div className="text-xs text-slate-500 mb-1">Catégorie</div>
              <select value={form.category} onChange={f('category')}
                className="w-full bg-dark-900 border border-slate-700 rounded px-3 py-2 text-slate-200 text-sm">
                {CATEGORIES.map(c => <option key={c} value={c}>{c}</option>)}
              </select>
            </div>
            <div>
              <div className="text-xs text-slate-500 mb-1">Niveau</div>
              <select value={form.level} onChange={f('level')}
                className="w-full bg-dark-900 border border-slate-700 rounded px-3 py-2 text-slate-200 text-sm">
                {LEVELS.map(l => <option key={l} value={l}>{l}</option>)}
              </select>
            </div>
            <div>
              <div className="text-xs text-slate-500 mb-1">Sous-type</div>
              <input value={form.sub_type} onChange={f('sub_type')} placeholder="ex: CPI, Conflit..."
                className="w-full bg-dark-900 border border-slate-700 rounded px-3 py-2 text-slate-200 text-sm" />
            </div>
          </div>
          <textarea value={form.description} onChange={f('description')} placeholder="Description..." rows={3}
            className="w-full bg-dark-900 border border-slate-700 rounded px-3 py-2 text-slate-200 text-sm resize-none" />
          <div>
            <div className="text-xs text-slate-500 mb-1">Score impact: {form.impact_score.toFixed(2)}</div>
            <input type="range" min="0" max="1" step="0.05" value={form.impact_score}
              onChange={e => setForm(d => ({ ...d, impact_score: +e.target.value }))}
              className="w-full accent-amber-400" />
          </div>
        </div>
        <div className="flex gap-2 px-5 pb-5">
          <button onClick={submit} disabled={saving || !form.name}
            className="flex items-center gap-2 bg-emerald-700 hover:bg-emerald-600 disabled:bg-slate-700 disabled:text-slate-500 text-white rounded-lg px-5 py-2 text-sm font-medium">
            {saving ? <Loader2 size={14} className="animate-spin" /> : <Plus size={14} />} Créer
          </button>
          <button onClick={onClose} className="text-sm text-slate-500 hover:text-slate-300 px-4">Annuler</button>
        </div>
      </div>
    </div>
  )
}

// ── Event list row ────────────────────────────────────────────────────────────

function EventRow({
  ev, selected, onClick,
}: { ev: MarketEvent; selected: boolean; onClick: () => void }) {
  return (
    <div
      onClick={onClick}
      className={clsx(
        'flex items-center gap-3 px-4 py-3 cursor-pointer border-b border-slate-800/50 hover:bg-slate-800/40 transition-colors',
        selected && 'bg-slate-800/60 border-l-2 border-l-blue-500',
      )}
    >
      <span className={clsx('w-1.5 h-1.5 rounded-full shrink-0', CAT_DOT[ev.category] ?? 'bg-slate-500')} />
      <div className="flex-1 min-w-0">
        <div className="text-sm text-slate-200 truncate font-medium">{ev.name}</div>
        <div className="flex items-center gap-2 mt-0.5">
          <span className="text-xs text-slate-500">{ev.start_date}</span>
          {ev.sub_type && <span className="text-xs text-slate-600">{ev.sub_type}</span>}
        </div>
      </div>
      <div className="shrink-0 text-right">
        <div className="text-xs font-bold" style={{ color: ev.impact_score >= 0.7 ? '#ef4444' : ev.impact_score >= 0.5 ? '#f59e0b' : '#10b981' }}>
          {ev.impact_score.toFixed(2)}
        </div>
        <div className={clsx('text-xs', LEVEL_COLORS[ev.level])}>{ev.level}</div>
      </div>
    </div>
  )
}

// ── Main page ─────────────────────────────────────────────────────────────────

export default function MarketEvents() {
  const [events, setEvents]         = useState<MarketEvent[]>([])
  const [total, setTotal]           = useState(0)
  const [loading, setLoading]       = useState(false)
  const [selected, setSelected]     = useState<MarketEvent | null>(null)
  const [showCreate, setShowCreate] = useState(false)
  const [bulkIds, setBulkIds]       = useState<Set<number>>(new Set())
  const [bulking, setBulking]       = useState(false)
  const [bulkMsg, setBulkMsg]       = useState<string | null>(null)

  // Filters
  const [search, setSearch]         = useState('')
  const [category, setCategory]     = useState('')
  const [level, setLevel]           = useState('')
  const [minScore, setMinScore]     = useState(0)
  const [evaluated, setEvaluated]   = useState<'' | 'true' | 'false'>('')
  const [dateFrom, setDateFrom]     = useState('')
  const [dateTo, setDateTo]         = useState('')
  const [showFilters, setShowFilters] = useState(false)

  const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null)

  const load = useCallback(async () => {
    setLoading(true)
    const params = new URLSearchParams()
    if (search)    params.set('search', search)
    if (category)  params.set('category', category)
    if (level)     params.set('level', level)
    if (minScore)  params.set('min_score', String(minScore))
    if (dateFrom)  params.set('date_from', dateFrom)
    if (dateTo)    params.set('date_to', dateTo)
    if (evaluated) params.set('evaluated', evaluated)
    params.set('limit', '500')
    const r = await fetch(`/api/market-events?${params}`)
    if (r.ok) {
      const d = await r.json()
      setEvents(d.events)
      setTotal(d.total)
    }
    setLoading(false)
  }, [search, category, level, minScore, dateFrom, dateTo, evaluated])

  useEffect(() => {
    if (debounceRef.current) clearTimeout(debounceRef.current)
    debounceRef.current = setTimeout(load, 250)
  }, [load])

  const bulkEvaluate = async () => {
    if (bulkIds.size === 0) return
    setBulking(true)
    setBulkMsg(null)
    const r = await fetch('/api/market-events/bulk-evaluate', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify([...bulkIds]),
    })
    const d = await r.json()
    setBulkMsg(`✓ ${d.evaluated} évalués${d.errors > 0 ? `, ${d.errors} erreurs` : ''}`)
    setBulkIds(new Set())
    setBulking(false)
    load()
  }

  const unevaluatedIds = events.filter(e => !e.evaluated).map(e => e.id)

  return (
    <div className="flex h-screen overflow-hidden">
      {/* ── Left panel: filters + list ── */}
      <div className="w-[380px] shrink-0 flex flex-col border-r border-slate-700/40 overflow-hidden">
        {/* Top bar */}
        <div className="px-4 pt-4 pb-3 border-b border-slate-700/30 space-y-2">
          <div className="flex items-center gap-2">
            <h1 className="text-base font-bold text-slate-100 flex-1">Market Events</h1>
            <button onClick={() => setShowCreate(true)}
              className="flex items-center gap-1 bg-emerald-700 hover:bg-emerald-600 text-white text-xs rounded-lg px-2.5 py-1.5">
              <Plus size={12} /> Nouveau
            </button>
            <button onClick={load} disabled={loading}
              className="p-1.5 text-slate-500 hover:text-slate-300 hover:bg-slate-700/50 rounded">
              <RefreshCw size={14} className={loading ? 'animate-spin' : ''} />
            </button>
          </div>

          {/* Search */}
          <div className="relative">
            <Search size={13} className="absolute left-2.5 top-1/2 -translate-y-1/2 text-slate-500" />
            <input value={search} onChange={e => setSearch(e.target.value)}
              placeholder="Recherche..."
              className="w-full bg-slate-800/60 border border-slate-700/50 rounded-lg pl-8 pr-3 py-1.5 text-sm text-slate-200 placeholder:text-slate-600" />
          </div>

          {/* Quick filter chips */}
          <div className="flex flex-wrap gap-1.5">
            {CATEGORIES.map(c => (
              <button key={c} onClick={() => setCategory(category === c ? '' : c)}
                className={clsx(
                  'px-2 py-0.5 rounded-full text-xs border transition-colors',
                  category === c
                    ? (CAT_COLORS[c] ?? 'bg-slate-700 text-slate-200 border-slate-600')
                    : 'border-slate-800 text-slate-600 hover:border-slate-600 hover:text-slate-400',
                )}>
                {c.replace('_', ' ')}
              </button>
            ))}
            <button onClick={() => setShowFilters(x => !x)}
              className={clsx('px-2 py-0.5 rounded-full text-xs border transition-colors ml-auto',
                showFilters ? 'bg-slate-700 text-slate-300 border-slate-600' : 'border-slate-800 text-slate-600 hover:border-slate-600')}>
              <SlidersHorizontal size={11} className="inline mr-0.5" />
              Filtres
            </button>
          </div>

          {/* Extended filters */}
          {showFilters && (
            <div className="grid grid-cols-2 gap-2 pt-1">
              <div>
                <div className="text-xs text-slate-600 mb-1">Niveau</div>
                <select value={level} onChange={e => setLevel(e.target.value)}
                  className="w-full bg-dark-900 border border-slate-700 rounded px-2 py-1 text-slate-300 text-xs">
                  <option value="">Tous</option>
                  {LEVELS.map(l => <option key={l} value={l}>{l}</option>)}
                </select>
              </div>
              <div>
                <div className="text-xs text-slate-600 mb-1">Évaluación</div>
                <select value={evaluated} onChange={e => setEvaluated(e.target.value as any)}
                  className="w-full bg-dark-900 border border-slate-700 rounded px-2 py-1 text-slate-300 text-xs">
                  <option value="">Tous</option>
                  <option value="true">Évalués</option>
                  <option value="false">Non évalués</option>
                </select>
              </div>
              <div>
                <div className="text-xs text-slate-600 mb-1">Date depuis</div>
                <input type="date" value={dateFrom} onChange={e => setDateFrom(e.target.value)}
                  className="w-full bg-dark-900 border border-slate-700 rounded px-2 py-1 text-slate-300 text-xs" />
              </div>
              <div>
                <div className="text-xs text-slate-600 mb-1">Date jusqu'à</div>
                <input type="date" value={dateTo} onChange={e => setDateTo(e.target.value)}
                  className="w-full bg-dark-900 border border-slate-700 rounded px-2 py-1 text-slate-300 text-xs" />
              </div>
              <div className="col-span-2">
                <div className="text-xs text-slate-600 mb-1">Score min: {minScore.toFixed(2)}</div>
                <input type="range" min="0" max="1" step="0.05" value={minScore}
                  onChange={e => setMinScore(+e.target.value)}
                  className="w-full accent-slate-400" />
              </div>
            </div>
          )}
        </div>

        {/* Bulk actions */}
        {unevaluatedIds.length > 0 && (
          <div className="px-4 py-2 border-b border-slate-800/50 flex items-center gap-2 bg-blue-900/10">
            <Users size={12} className="text-blue-400" />
            <span className="text-xs text-blue-300 flex-1">
              {unevaluatedIds.length} non évalués
            </span>
            {bulkMsg && <span className="text-xs text-emerald-400">{bulkMsg}</span>}
            <button
              onClick={() => { setBulkIds(new Set(unevaluatedIds)); setTimeout(bulkEvaluate, 50) }}
              disabled={bulking}
              className="flex items-center gap-1 text-xs bg-blue-700/50 hover:bg-blue-700/70 text-blue-200 rounded px-2 py-1">
              {bulking ? <Loader2 size={10} className="animate-spin" /> : <Sparkles size={10} />}
              Évaluer tous
            </button>
          </div>
        )}

        {/* Count */}
        <div className="px-4 py-1.5 text-xs text-slate-600 border-b border-slate-800/30">
          {total} événement{total !== 1 ? 's' : ''}
          {(category || level || search || minScore > 0 || evaluated || dateFrom || dateTo) && ' (filtré)'}
        </div>

        {/* List */}
        <div className="flex-1 overflow-y-auto">
          {loading && events.length === 0 ? (
            <div className="flex items-center justify-center h-32 text-slate-500 text-sm">
              <Loader2 size={16} className="animate-spin mr-2" /> Chargement...
            </div>
          ) : events.length === 0 ? (
            <div className="text-center py-12 text-slate-600 text-sm">Aucun événement trouvé</div>
          ) : (
            events.map(ev => (
              <EventRow
                key={ev.id}
                ev={ev}
                selected={selected?.id === ev.id}
                onClick={() => setSelected(ev)}
              />
            ))
          )}
        </div>
      </div>

      {/* ── Right panel: detail ── */}
      <div className="flex-1 overflow-hidden bg-dark-900/40">
        {selected ? (
          <EventDetail
            key={selected.id}
            event={selected}
            onClose={() => setSelected(null)}
            onUpdated={updated => {
              setEvents(evs => evs.map(e => e.id === updated.id ? { ...e, ...updated } : e))
            }}
            onDeleted={id => {
              setEvents(evs => evs.filter(e => e.id !== id))
              setSelected(null)
            }}
          />
        ) : (
          <div className="flex flex-col items-center justify-center h-full text-slate-600 gap-3">
            <BarChart2 size={40} className="opacity-30" />
            <div className="text-sm">Sélectionne un événement pour voir le détail</div>
            <div className="text-xs opacity-60">Sources · Impacts par instrument · Analyse IA</div>
          </div>
        )}
      </div>

      {showCreate && <CreateModal onCreated={load} onClose={() => setShowCreate(false)} />}
    </div>
  )
}
