import { useState, useEffect, useCallback } from 'react'
import {
  Zap, RefreshCw, ChevronDown, ChevronRight, AlertCircle,
  TrendingUp, TrendingDown, Minus, Settings, Play, Check, Sliders,
} from 'lucide-react'
import axios from 'axios'
import clsx from 'clsx'

const api = axios.create({ baseURL: '/api' })

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

interface Impact {
  id: number
  instrument_id: string
  impact_score: number
  direction: string
  rationale: string
  confidence: number
  ai_generated: number
  manually_adjusted: number
  adjusted_score?: number
  adjusted_direction?: string
  override_rationale?: string
}

interface EvaluatedSource {
  source_type: string
  source_id: number
  source_name: string
  source_date: string
  category_name: string
  max_score: number
  n_instruments: number
  evaluated_at: string
  impacts: Impact[]
}

interface UnevaluatedEvent {
  id: number
  name: string
  start_date: string
  category: string
  sub_type: string
  impact_score: number
}

interface TopInstrument {
  instrument_id: string
  avg_score: number
  n_events: number
}

interface MonitorData {
  evaluated: EvaluatedSource[]
  unevaluated: UnevaluatedEvent[]
  top_instruments: TopInstrument[]
  period_days: number
  min_score: number
}

interface DefaultImpact {
  instrument_id: string
  sensitivity: number
  typical_direction: string
  notes: string
}

interface Category {
  id: number
  name: string
  type: string
  sub_type: string
  description: string
  default_impacts: DefaultImpact[]
}

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

const DIR_CFG: Record<string, { icon: React.ReactNode; color: string; short: string }> = {
  bullish:             { icon: <TrendingUp className="w-3 h-3" />,  color: 'text-emerald-400', short: '↑' },
  bearish:             { icon: <TrendingDown className="w-3 h-3" />, color: 'text-red-400',     short: '↓' },
  neutral:             { icon: <Minus className="w-3 h-3" />,       color: 'text-slate-400',   short: '—' },
  depends_on_outcome:  { icon: <Minus className="w-3 h-3" />,       color: 'text-amber-400',   short: '?' },
  bullish_if_beat:     { icon: <TrendingUp className="w-3 h-3" />,  color: 'text-emerald-300', short: '↑?' },
  bearish_if_hawkish:  { icon: <TrendingDown className="w-3 h-3" />, color: 'text-red-300',    short: '↓H' },
  bullish_if_surprise: { icon: <TrendingUp className="w-3 h-3" />,  color: 'text-violet-400',  short: '↑!' },
}

const TYPE_CFG: Record<string, { color: string; label: string }> = {
  event_calendar: { color: 'text-amber-400 bg-amber-900/30 border-amber-700/30', label: 'Calendrier' },
  geopolitical:   { color: 'text-red-400 bg-red-900/30 border-red-700/30',       label: 'Géopolitique' },
}

function scoreBar(score: number, color = 'bg-blue-500') {
  return (
    <div className="flex items-center gap-1.5">
      <div className="w-16 h-1.5 bg-slate-800 rounded-full overflow-hidden">
        <div className={clsx('h-full rounded-full', color)} style={{ width: `${score * 100}%` }} />
      </div>
      <span className="text-xs tabular-nums text-slate-400">{(score * 100).toFixed(0)}</span>
    </div>
  )
}

function scoreColor(score: number) {
  if (score >= 0.7) return 'bg-red-500'
  if (score >= 0.5) return 'bg-orange-500'
  if (score >= 0.3) return 'bg-amber-500'
  return 'bg-slate-500'
}

function dirColor(dir: string) {
  return DIR_CFG[dir]?.color ?? 'text-slate-400'
}

// ── AdjustModal ───────────────────────────────────────────────────────────────

function AdjustModal({
  impact, onClose, onSave,
}: {
  impact: Impact
  onClose: () => void
  onSave: (id: number, score: number, dir: string, rationale: string) => void
}) {
  const [score, setScore] = useState(impact.adjusted_score ?? impact.impact_score)
  const [dir, setDir] = useState(impact.adjusted_direction ?? impact.direction)
  const [rationale, setRationale] = useState(impact.override_rationale ?? '')

  const DIRS = ['bullish','bearish','neutral','depends_on_outcome']

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/70">
      <div className="bg-dark-800 border border-slate-700/40 rounded-xl p-5 w-[400px] space-y-4 shadow-2xl">
        <div className="flex items-center justify-between">
          <span className="text-sm font-semibold text-white">Ajuster l'impact — {impact.instrument_id}</span>
          <button onClick={onClose} className="text-slate-500 hover:text-white"><span className="text-lg">×</span></button>
        </div>
        <div>
          <div className="text-xs text-slate-500 mb-1">Score IA : {(impact.impact_score * 100).toFixed(0)}</div>
          <label className="text-xs text-slate-400 mb-1 block">Score ajusté : {(score * 100).toFixed(0)}</label>
          <input type="range" min={0} max={1} step={0.05} value={score}
            onChange={e => setScore(parseFloat(e.target.value))}
            className="w-full accent-blue-500" />
        </div>
        <div>
          <label className="text-xs text-slate-400 mb-1 block">Direction</label>
          <div className="flex gap-1.5">
            {DIRS.map(d => (
              <button key={d} onClick={() => setDir(d)}
                className={clsx('flex-1 text-xs py-1 rounded border transition-colors',
                  dir === d
                    ? 'border-blue-500 bg-blue-900/30 text-blue-300'
                    : 'border-slate-700/40 text-slate-500 hover:text-white'
                )}>
                {d === 'depends_on_outcome' ? '?' : d.slice(0,4)}
              </button>
            ))}
          </div>
        </div>
        <div>
          <label className="text-xs text-slate-400 mb-1 block">Commentaire</label>
          <textarea
            className="w-full text-xs bg-dark-700 border border-slate-700/40 rounded px-2 py-1.5 text-slate-300 placeholder-slate-600 resize-none"
            rows={2} placeholder="Pourquoi ajuster..."
            value={rationale} onChange={e => setRationale(e.target.value)}
          />
        </div>
        <div className="flex gap-2">
          <button onClick={onClose}
            className="flex-1 text-xs py-1.5 border border-slate-700/40 rounded-lg text-slate-400 hover:text-white">
            Annuler
          </button>
          <button onClick={() => { onSave(impact.id, score, dir, rationale); onClose() }}
            className="flex-1 text-xs py-1.5 bg-blue-700/40 hover:bg-blue-700/60 text-blue-300 border border-blue-600/40 rounded-lg">
            Sauvegarder
          </button>
        </div>
      </div>
    </div>
  )
}

// ── ImpactRow ─────────────────────────────────────────────────────────────────

function ImpactRow({
  impact, onAdjust,
}: {
  impact: Impact
  onAdjust: (imp: Impact) => void
}) {
  const score = impact.adjusted_score ?? impact.impact_score
  const dir   = impact.adjusted_direction ?? impact.direction
  const dc    = DIR_CFG[dir] ?? DIR_CFG['neutral']

  return (
    <div className="flex items-center gap-2 py-0.5 group">
      <span className="text-xs font-mono text-slate-300 w-20 shrink-0">{impact.instrument_id}</span>
      {scoreBar(score, scoreColor(score))}
      <span className={clsx('text-xs flex items-center gap-0.5 w-16 shrink-0', dc.color)}>
        {dc.icon}{dc.short}
      </span>
      <span className="text-xs text-slate-600 truncate flex-1">{impact.rationale}</span>
      {impact.manually_adjusted === 1 && (
        <span className="text-xs text-violet-500 shrink-0">✎</span>
      )}
      <button
        onClick={() => onAdjust(impact)}
        className="opacity-0 group-hover:opacity-100 p-0.5 text-slate-600 hover:text-white transition-opacity"
        title="Ajuster">
        <Sliders className="w-3 h-3" />
      </button>
    </div>
  )
}

// ── EvaluatedCard ─────────────────────────────────────────────────────────────

function EvaluatedCard({
  source, onAdjust, onReEval,
}: {
  source: EvaluatedSource
  onAdjust: (imp: Impact) => void
  onReEval: (id: number) => void
}) {
  const [open, setOpen] = useState(false)
  const catType = source.impacts[0] ? 'event_calendar' : 'geopolitical'
  const tcfg = TYPE_CFG[source.source_type === 'news' ? 'geopolitical' : 'event_calendar']

  const sorted = [...source.impacts].sort((a, b) =>
    (b.adjusted_score ?? b.impact_score) - (a.adjusted_score ?? a.impact_score)
  )

  return (
    <div className="rounded-xl border border-slate-700/30 bg-dark-800/60 overflow-hidden">
      <div
        className="flex items-center gap-3 px-4 py-3 cursor-pointer hover:bg-dark-700/40 transition-colors"
        onClick={() => setOpen(o => !o)}
      >
        <div className="flex-1 min-w-0">
          <div className="flex items-center gap-2 mb-0.5">
            <span className="text-sm font-medium text-white truncate">{source.source_name}</span>
          </div>
          <div className="flex items-center gap-2 text-xs text-slate-500">
            <span>{source.source_date}</span>
            {source.category_name && (
              <span className={clsx('px-1.5 py-0 rounded border', tcfg?.color ?? 'text-slate-400 border-slate-700/30')}
                style={{ fontSize: 9, paddingTop: 1, paddingBottom: 1 }}>
                {source.category_name}
              </span>
            )}
            <span>{source.n_instruments} instruments</span>
          </div>
        </div>
        <div className="flex items-center gap-3 shrink-0">
          {/* Top 3 instruments mini-badges */}
          <div className="flex gap-1">
            {sorted.slice(0, 3).map(imp => (
              <span key={imp.instrument_id}
                className={clsx('text-xs px-1.5 py-0.5 rounded font-mono',
                  (imp.adjusted_score ?? imp.impact_score) >= 0.7
                    ? 'bg-red-900/30 text-red-300'
                    : (imp.adjusted_score ?? imp.impact_score) >= 0.5
                    ? 'bg-orange-900/30 text-orange-300'
                    : 'bg-slate-700/40 text-slate-400'
                )}>
                {imp.instrument_id}
              </span>
            ))}
          </div>
          <div className="flex items-center gap-1">
            <div className="w-8 h-1.5 bg-slate-800 rounded-full overflow-hidden">
              <div className={clsx('h-full rounded-full', scoreColor(source.max_score))}
                style={{ width: `${source.max_score * 100}%` }} />
            </div>
            <span className="text-xs text-slate-400">{(source.max_score * 100).toFixed(0)}</span>
          </div>
          <button
            onClick={e => { e.stopPropagation(); onReEval(source.source_id) }}
            className="p-1 text-slate-600 hover:text-amber-400 transition-colors"
            title="Re-évaluer">
            <RefreshCw className="w-3 h-3" />
          </button>
          {open ? <ChevronDown className="w-4 h-4 text-slate-500" /> : <ChevronRight className="w-4 h-4 text-slate-500" />}
        </div>
      </div>

      {open && (
        <div className="px-4 pb-3 border-t border-slate-700/20 pt-2 space-y-0.5">
          {sorted.map(imp => (
            <ImpactRow key={imp.id} impact={imp} onAdjust={onAdjust} />
          ))}
        </div>
      )}
    </div>
  )
}

// ── CategoryPanel ─────────────────────────────────────────────────────────────

function CategoryPanel({ onClose }: { onClose: () => void }) {
  const [categories, setCategories] = useState<Category[]>([])
  const [selected, setSelected] = useState<Category | null>(null)
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    api.get('/impact/categories').then(r => {
      setCategories(r.data)
      setLoading(false)
    }).catch(() => setLoading(false))
  }, [])

  return (
    <div className="rounded-xl border border-slate-700/40 bg-dark-800/80 p-4 space-y-3">
      <div className="flex items-center justify-between">
        <span className="text-sm font-semibold text-white">Catégories & Impacts par défaut</span>
        <button onClick={onClose} className="text-slate-500 hover:text-white text-lg">×</button>
      </div>
      {loading ? (
        <div className="text-xs text-slate-500">Chargement...</div>
      ) : (
        <div className="grid grid-cols-2 gap-3">
          {/* Category list */}
          <div className="space-y-1 max-h-[500px] overflow-y-auto pr-1">
            {categories.map(cat => (
              <div key={cat.name}
                className={clsx('rounded-lg border px-3 py-2 cursor-pointer transition-colors',
                  selected?.name === cat.name
                    ? 'border-blue-600/50 bg-blue-900/20'
                    : 'border-slate-700/30 bg-dark-700/40 hover:bg-dark-700/70'
                )}
                onClick={() => setSelected(cat)}
              >
                <div className="flex items-center gap-2">
                  <span className={clsx('text-xs px-1.5 py-0 rounded border',
                    TYPE_CFG[cat.type]?.color ?? 'text-slate-400 border-slate-700/30'
                  )} style={{ fontSize: 8, paddingTop: 1, paddingBottom: 1 }}>
                    {TYPE_CFG[cat.type]?.label ?? cat.type}
                  </span>
                  <span className="text-xs text-slate-300 truncate">{cat.name}</span>
                </div>
                <div className="text-xs text-slate-600 mt-0.5">{cat.default_impacts.length} instruments</div>
              </div>
            ))}
          </div>

          {/* Default impacts detail */}
          <div className="border border-slate-700/30 rounded-lg p-3 max-h-[500px] overflow-y-auto">
            {selected ? (
              <div className="space-y-2">
                <div className="text-xs font-semibold text-white">{selected.name}</div>
                <div className="text-xs text-slate-500">{selected.description}</div>
                <div className="space-y-1 mt-2">
                  {[...selected.default_impacts]
                    .sort((a, b) => b.sensitivity - a.sensitivity)
                    .map(di => {
                      const dc = DIR_CFG[di.typical_direction] ?? DIR_CFG['neutral']
                      return (
                        <div key={di.instrument_id} className="flex items-center gap-2 py-0.5">
                          <span className="text-xs font-mono text-slate-300 w-20 shrink-0">{di.instrument_id}</span>
                          {scoreBar(di.sensitivity, scoreColor(di.sensitivity))}
                          <span className={clsx('text-xs shrink-0', dc.color)}>{dc.short}</span>
                          <span className="text-xs text-slate-600 truncate">{di.notes}</span>
                        </div>
                      )
                    })}
                </div>
              </div>
            ) : (
              <div className="text-xs text-slate-600 italic">Sélectionne une catégorie</div>
            )}
          </div>
        </div>
      )}
    </div>
  )
}

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

export default function ImpactMonitor() {
  const [data, setData] = useState<MonitorData | null>(null)
  const [loading, setLoading] = useState(false)
  const [evaluating, setEvaluating] = useState<Set<number>>(new Set())
  const [days, setDays] = useState(14)
  const [minScore, setMinScore] = useState(0.3)
  const [adjusting, setAdjusting] = useState<Impact | null>(null)
  const [showCategories, setShowCategories] = useState(false)
  const [tab, setTab] = useState<'evaluated' | 'pending'>('evaluated')

  const load = useCallback(() => {
    setLoading(true)
    api.get(`/impact/monitor?days=${days}&min_score=${minScore}`)
      .then(r => setData(r.data))
      .catch(() => {})
      .finally(() => setLoading(false))
  }, [days, minScore])

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

  async function evaluateEvent(eventId: number, force = false) {
    setEvaluating(s => new Set(s).add(eventId))
    try {
      await api.post(`/impact/evaluate/event/${eventId}?force=${force}`)
      load()
    } catch (e) {
      console.error(e)
    } finally {
      setEvaluating(s => { const n = new Set(s); n.delete(eventId); return n })
    }
  }

  async function evaluateAllPending() {
    if (!data?.unevaluated.length) return
    const ids = data.unevaluated.slice(0, 10).map(e => e.id)
    setEvaluating(new Set(ids))
    try {
      await api.post('/impact/evaluate/bulk', ids)
      load()
    } finally {
      setEvaluating(new Set())
    }
  }

  async function saveAdjustment(id: number, score: number, dir: string, rationale: string) {
    await api.put(`/impact/adjust/${id}`, {
      adjusted_score: score,
      adjusted_direction: dir,
      override_rationale: rationale,
    })
    load()
  }

  const evaluated  = data?.evaluated  ?? []
  const unevaluated = data?.unevaluated ?? []
  const topInstr   = data?.top_instruments ?? []

  return (
    <div className="p-6 max-w-screen-xl mx-auto space-y-5">

      {/* Header */}
      <div className="flex flex-wrap items-center gap-3">
        <div className="flex items-center gap-2">
          <Zap className="w-5 h-5 text-amber-400" />
          <h1 className="text-xl font-bold text-white">Impact Monitor</h1>
          <span className="text-xs text-slate-500 bg-dark-700 border border-slate-700/40 px-2 py-0.5 rounded-full">
            Événements Éco + Géopolitique
          </span>
        </div>

        <div className="ml-auto flex items-center gap-2">
          {/* Days selector */}
          <div className="flex items-center gap-1 bg-dark-800 border border-slate-700/40 rounded-xl p-1">
            {[7, 14, 30, 90].map(d => (
              <button key={d} onClick={() => setDays(d)}
                className={clsx('px-3 py-1 text-xs rounded-lg transition-colors',
                  days === d ? 'bg-blue-700/50 text-blue-300' : 'text-slate-400 hover:text-white hover:bg-dark-700'
                )}>
                {d}j
              </button>
            ))}
          </div>

          {/* Min score */}
          <div className="flex items-center gap-1.5 text-xs text-slate-400">
            <span>Seuil</span>
            <select
              className="bg-dark-700 border border-slate-700/40 rounded px-1.5 py-1 text-xs text-slate-300"
              value={minScore}
              onChange={e => setMinScore(parseFloat(e.target.value))}
            >
              {[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7].map(v => (
                <option key={v} value={v}>{(v * 100).toFixed(0)}</option>
              ))}
            </select>
          </div>

          <button onClick={load} disabled={loading}
            className="flex items-center gap-1.5 text-xs px-3 py-1.5 bg-dark-800 border border-slate-700/40 rounded-lg text-slate-400 hover:text-white transition-colors disabled:opacity-40">
            <RefreshCw className={clsx('w-3 h-3', loading && 'animate-spin')} />
            Actualiser
          </button>

          <button onClick={() => setShowCategories(s => !s)}
            className={clsx('flex items-center gap-1.5 text-xs px-3 py-1.5 border rounded-lg transition-colors',
              showCategories
                ? 'bg-slate-700/50 text-white border-slate-600/50'
                : 'bg-dark-800 border-slate-700/40 text-slate-400 hover:text-white'
            )}>
            <Settings className="w-3 h-3" />
            Catégories
          </button>
        </div>
      </div>

      {/* Categories panel */}
      {showCategories && <CategoryPanel onClose={() => setShowCategories(false)} />}

      {/* Top instruments bar */}
      {topInstr.length > 0 && (
        <div className="rounded-xl border border-slate-700/30 bg-dark-800/60 px-4 py-3">
          <div className="text-xs text-slate-500 uppercase tracking-wide mb-2">
            Instruments les plus impactés — {days}j
          </div>
          <div className="flex flex-wrap gap-2">
            {topInstr.map(ti => (
              <div key={ti.instrument_id}
                className="flex items-center gap-1.5 bg-dark-700/60 border border-slate-700/30 rounded-lg px-2.5 py-1">
                <span className="text-xs font-mono font-semibold text-white">{ti.instrument_id}</span>
                <div className="w-12 h-1 bg-slate-800 rounded-full overflow-hidden">
                  <div className={clsx('h-full rounded-full', scoreColor(ti.avg_score))}
                    style={{ width: `${ti.avg_score * 100}%` }} />
                </div>
                <span className="text-xs text-slate-500">{ti.n_events}×</span>
              </div>
            ))}
          </div>
        </div>
      )}

      {/* Tabs */}
      <div className="flex items-center gap-1 border-b border-slate-700/30">
        <button onClick={() => setTab('evaluated')}
          className={clsx('px-4 py-2 text-sm transition-colors border-b-2',
            tab === 'evaluated'
              ? 'text-white border-blue-500'
              : 'text-slate-500 border-transparent hover:text-white'
          )}>
          Évalués <span className="ml-1.5 text-xs text-slate-600">({evaluated.length})</span>
        </button>
        <button onClick={() => setTab('pending')}
          className={clsx('px-4 py-2 text-sm transition-colors border-b-2',
            tab === 'pending'
              ? 'text-white border-amber-500'
              : 'text-slate-500 border-transparent hover:text-white'
          )}>
          À évaluer
          {unevaluated.length > 0 && (
            <span className="ml-1.5 text-xs px-1.5 py-0.5 bg-amber-900/40 text-amber-400 rounded-full border border-amber-700/30">
              {unevaluated.length}
            </span>
          )}
        </button>
      </div>

      {/* Loading */}
      {loading && (
        <div className="space-y-3">
          {[1,2,3].map(i => (
            <div key={i} className="h-16 rounded-xl bg-dark-800/60 border border-slate-700/30 animate-pulse" />
          ))}
        </div>
      )}

      {/* Evaluated tab */}
      {!loading && tab === 'evaluated' && (
        <div className="space-y-2">
          {evaluated.length === 0 ? (
            <div className="text-center py-16 text-slate-500">
              <AlertCircle className="w-8 h-8 mx-auto mb-3 opacity-30" />
              <p>Aucun événement évalué sur les {days} derniers jours</p>
              <p className="text-xs mt-1">Passe à l'onglet "À évaluer" pour lancer les évaluations IA</p>
            </div>
          ) : (
            evaluated.map(src => (
              <EvaluatedCard
                key={`${src.source_type}-${src.source_id}`}
                source={src}
                onAdjust={imp => setAdjusting(imp)}
                onReEval={id => evaluateEvent(id, true)}
              />
            ))
          )}
        </div>
      )}

      {/* Pending tab */}
      {!loading && tab === 'pending' && (
        <div className="space-y-3">
          {unevaluated.length > 0 && (
            <div className="flex items-center justify-between">
              <span className="text-xs text-slate-500">
                {unevaluated.length} événement(s) récents sans évaluation IA
              </span>
              <button
                onClick={evaluateAllPending}
                disabled={evaluating.size > 0}
                className="flex items-center gap-1.5 text-xs px-3 py-1.5 bg-amber-800/30 hover:bg-amber-800/50 text-amber-300 border border-amber-700/40 rounded-lg transition-colors disabled:opacity-40">
                <Play className="w-3 h-3" />
                Évaluer les 10 premiers (IA)
              </button>
            </div>
          )}

          {unevaluated.length === 0 ? (
            <div className="text-center py-16 text-slate-500">
              <Check className="w-8 h-8 mx-auto mb-3 opacity-30 text-emerald-400" />
              <p>Tous les événements récents ont été évalués</p>
            </div>
          ) : (
            <div className="space-y-2">
              {unevaluated.map(ev => (
                <div key={ev.id}
                  className="flex items-center gap-3 rounded-xl border border-slate-700/30 bg-dark-800/60 px-4 py-3">
                  <div className="flex-1 min-w-0">
                    <div className="text-sm text-slate-300 truncate">{ev.name}</div>
                    <div className="flex items-center gap-2 mt-0.5 text-xs text-slate-500">
                      <span>{ev.start_date}</span>
                      {ev.sub_type && (
                        <span className="px-1.5 py-0 rounded bg-slate-700/40 border border-slate-600/30"
                          style={{ fontSize: 9, paddingTop: 1, paddingBottom: 1 }}>
                          {ev.sub_type}
                        </span>
                      )}
                    </div>
                  </div>
                  <button
                    onClick={() => evaluateEvent(ev.id)}
                    disabled={evaluating.has(ev.id)}
                    className="flex items-center gap-1.5 text-xs px-3 py-1.5 bg-blue-800/30 hover:bg-blue-800/50 text-blue-300 border border-blue-700/40 rounded-lg transition-colors disabled:opacity-40">
                    {evaluating.has(ev.id)
                      ? <><RefreshCw className="w-3 h-3 animate-spin" /> Analyse IA...</>
                      : <><Zap className="w-3 h-3" /> Évaluer IA</>
                    }
                  </button>
                </div>
              ))}
            </div>
          )}
        </div>
      )}

      {/* Adjust modal */}
      {adjusting && (
        <AdjustModal
          impact={adjusting}
          onClose={() => setAdjusting(null)}
          onSave={saveAdjustment}
        />
      )}
    </div>
  )
}
