import { useState, useEffect, useCallback } from 'react'
import { Bot, Plus, Trash2, Save, ChevronDown, ChevronRight, ToggleLeft, ToggleRight } from 'lucide-react'
import clsx from 'clsx'

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

interface SignalParam {
  type: 'int' | 'float' | 'pairs' | 'select'
  label: string
  default: number | number[][] | string
  min?: number
  max?: number
  options?: string[]
}

interface SignalDef {
  id: string
  label: string
  description: string
  desk_type?: string
  params: Record<string, SignalParam>
}

interface AIDesk {
  id?: number
  name: string
  type: 'news' | 'fundamental' | 'technical' | 'eco' | 'report' | 'sentiment'
  active: boolean
  system_prompt: string
  instruments: string[]
  config: Record<string, any>
}

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',
]

// Macro regime gauges from MACRO_GAUGE_CONFIG (backend data_fetcher.py)
const MACRO_GAUGE_LIST: { id: string; label: string; bloc: string }[] = [
  // Liquidité / Taux
  { id: 'dxy',              label: 'Dollar DXY',        bloc: 'Liquidité' },
  { id: 'us10y',            label: 'UST 10Y',           bloc: 'Liquidité' },
  { id: 'us3m',             label: 'UST 3M',            bloc: 'Liquidité' },
  { id: 'tips',             label: 'TIPS ETF',          bloc: 'Liquidité' },
  { id: 'tlt',              label: 'TLT 20Y+',          bloc: 'Liquidité' },
  // Crédit
  { id: 'vix',              label: 'VIX',               bloc: 'Crédit' },
  { id: 'hyg',              label: 'HYG (HY Bonds)',    bloc: 'Crédit' },
  { id: 'lqd',              label: 'LQD (IG Bonds)',    bloc: 'Crédit' },
  { id: 'ief',              label: 'IEF (7-10Y)',       bloc: 'Crédit' },
  // Énergie
  { id: 'brent',            label: 'Brent',             bloc: 'Énergie' },
  { id: 'ng',               label: 'Gaz naturel',       bloc: 'Énergie' },
  // Métaux
  { id: 'gold',             label: 'Or',                bloc: 'Métaux' },
  { id: 'silver',           label: 'Argent',            bloc: 'Métaux' },
  { id: 'copper',           label: 'Cuivre',            bloc: 'Métaux' },
  // Croissance
  { id: 'spx',              label: 'S&P 500',           bloc: 'Croissance' },
  { id: 'iwm',              label: 'Russell 2000',      bloc: 'Croissance' },
  { id: 'xli',              label: 'Industriels XLI',   bloc: 'Croissance' },
  // Secteurs
  { id: 'xlk',              label: 'Tech XLK',          bloc: 'Secteurs' },
  { id: 'xlf',              label: 'Financières XLF',   bloc: 'Secteurs' },
  { id: 'xlp',              label: 'Conso. défensif',   bloc: 'Secteurs' },
  { id: 'xlu',              label: 'Utilities XLU',     bloc: 'Secteurs' },
  // Volatilité
  { id: 'vvix',             label: 'VVIX (vol-of-vol)', bloc: 'Volatilité' },
  { id: 'skew',             label: 'CBOE SKEW',         bloc: 'Volatilité' },
  { id: 'ovx',              label: 'OVX (Oil Vol)',      bloc: 'Volatilité' },
  { id: 'gvz',              label: 'GVZ (Gold Vol)',     bloc: 'Volatilité' },
  // Global / EM
  { id: 'eem',              label: 'EM Actions EEM',    bloc: 'Global' },
  { id: 'emb',              label: 'EM Bonds EMB',      bloc: 'Global' },
  { id: 'fxi',              label: 'Chine FXI',         bloc: 'Global' },
  // Forex risk-off
  { id: 'usdjpy',           label: 'USD/JPY',           bloc: 'Forex' },
  // Dérivés calculés
  { id: 'slope_10y3m',      label: 'Slope 10Y-3M',      bloc: 'Dérivés' },
  { id: 'gold_copper_ratio',label: 'Ratio Or/Cuivre',   bloc: 'Dérivés' },
  { id: 'spx_vs_200d',      label: 'SPX vs MA 200j',    bloc: 'Dérivés' },
]

const MACRO_BLOC_ORDER = ['Liquidité','Crédit','Volatilité','Métaux','Énergie','Croissance','Secteurs','Global','Forex','Dérivés']

const TYPE_LABELS: Record<string, string> = {
  news:        'News',
  fundamental: 'Fondamental',
  technical:   'Technical',
  eco:         'Économique',
  report:      'Report',
  sentiment:   'Sentiment',
}

const TYPE_COLORS: Record<string, string> = {
  news:        'text-blue-400 bg-blue-900/20 border-blue-700/40',
  fundamental: 'text-amber-400 bg-amber-900/20 border-amber-700/40',
  technical:   'text-cyan-400 bg-cyan-900/20 border-cyan-700/40',
  eco:         'text-emerald-400 bg-emerald-900/20 border-emerald-700/40',
  report:      'text-violet-400 bg-violet-900/20 border-violet-700/40',
  sentiment:   'text-rose-400 bg-rose-900/20 border-rose-700/40',
}

// ── Subcomponents ─────────────────────────────────────────────────────────────

function InstrumentSelector({
  selected,
  onChange,
}: {
  selected: string[]
  onChange: (v: string[]) => void
}) {
  const toggle = (t: string) => {
    onChange(selected.includes(t) ? selected.filter(x => x !== t) : [...selected, t])
  }
  const all = selected.length === ALL_INSTRUMENTS.length
  return (
    <div className="space-y-2">
      <div className="flex items-center justify-between">
        <label className="text-xs text-slate-400">Instruments surveillés</label>
        <button
          onClick={() => onChange(all ? [] : [...ALL_INSTRUMENTS])}
          className="text-xs text-blue-400 hover:text-blue-300"
        >
          {all ? 'Tout désélectionner' : 'Tout sélectionner'}
        </button>
      </div>
      <div className="flex flex-wrap gap-1.5">
        {ALL_INSTRUMENTS.map(t => (
          <button
            key={t}
            onClick={() => toggle(t)}
            className={clsx(
              'px-2 py-0.5 rounded text-xs border transition-colors',
              selected.includes(t)
                ? 'bg-blue-900/40 border-blue-600/60 text-blue-300'
                : 'bg-dark-800 border-slate-700/40 text-slate-500 hover:border-slate-600',
            )}
          >
            {t}
          </button>
        ))}
      </div>
    </div>
  )
}


function MacroGaugeSelector({
  selected,
  onChange,
}: {
  selected: string[]
  onChange: (v: string[]) => void
}) {
  const toggle = (id: string) =>
    onChange(selected.includes(id) ? selected.filter(x => x !== id) : [...selected, id])

  const blocs = MACRO_BLOC_ORDER.filter(b => MACRO_GAUGE_LIST.some(g => g.bloc === b))

  return (
    <div className="space-y-3">
      <div className="flex items-center justify-between">
        <label className="text-xs text-slate-400">Compteurs macro surveillés</label>
        <button
          onClick={() => onChange(selected.length === MACRO_GAUGE_LIST.length ? [] : MACRO_GAUGE_LIST.map(g => g.id))}
          className="text-xs text-rose-400 hover:text-rose-300"
        >
          {selected.length === MACRO_GAUGE_LIST.length ? 'Tout désélectionner' : 'Tout sélectionner'}
        </button>
      </div>
      {blocs.map(bloc => {
        const gauges = MACRO_GAUGE_LIST.filter(g => g.bloc === bloc)
        return (
          <div key={bloc}>
            <div className="text-[10px] text-slate-600 uppercase tracking-wider mb-1">{bloc}</div>
            <div className="flex flex-wrap gap-1.5">
              {gauges.map(g => (
                <button
                  key={g.id}
                  onClick={() => toggle(g.id)}
                  className={clsx(
                    'px-2 py-0.5 rounded text-xs border transition-colors',
                    selected.includes(g.id)
                      ? 'bg-rose-900/40 border-rose-600/60 text-rose-300'
                      : 'bg-dark-800 border-slate-700/40 text-slate-500 hover:border-slate-600',
                  )}
                >
                  {g.label}
                </button>
              ))}
            </div>
          </div>
        )
      })}
    </div>
  )
}


function SignalToggle({
  signal,
  value,
  onChange,
}: {
  signal: SignalDef
  value: { enabled: boolean; [k: string]: any }
  onChange: (v: { enabled: boolean; [k: string]: any }) => void
}) {
  const [open, setOpen] = useState(false)

  const update = (key: string, val: any) => {
    onChange({ ...value, [key]: val })
  }

  return (
    <div className={clsx(
      'rounded-lg border transition-colors',
      value.enabled
        ? 'border-cyan-700/40 bg-cyan-900/10'
        : 'border-slate-700/30 bg-dark-800/60',
    )}>
      <div className="flex items-center gap-3 px-3 py-2.5">
        <button
          onClick={() => onChange({ ...value, enabled: !value.enabled })}
          className="shrink-0"
        >
          {value.enabled
            ? <ToggleRight className="w-5 h-5 text-cyan-400" />
            : <ToggleLeft  className="w-5 h-5 text-slate-600" />}
        </button>
        <div className="flex-1 min-w-0">
          <div className={clsx('text-sm font-medium', value.enabled ? 'text-white' : 'text-slate-500')}>
            {signal.label}
          </div>
          <div className="text-xs text-slate-600 truncate">{signal.description}</div>
        </div>
        {value.enabled && Object.keys(signal.params).length > 0 && (
          <button
            onClick={() => setOpen(o => !o)}
            className="text-slate-500 hover:text-slate-300"
          >
            {open
              ? <ChevronDown className="w-4 h-4" />
              : <ChevronRight className="w-4 h-4" />}
          </button>
        )}
      </div>

      {open && value.enabled && (
        <div className="px-4 pb-3 space-y-2 border-t border-slate-700/20 pt-2">
          {Object.entries(signal.params).map(([key, p]) => {
            if (p.type === 'pairs') {
              return (
                <div key={key}>
                  <div className="text-xs text-slate-400 mb-1">{p.label}</div>
                  <div className="text-xs text-slate-500 italic">
                    {JSON.stringify(value[key] ?? p.default)}
                  </div>
                </div>
              )
            }
            if (p.type === 'select') {
              return (
                <div key={key} className="flex items-center gap-3">
                  <label className="text-xs text-slate-400 w-28 shrink-0">{p.label}</label>
                  <select
                    value={value[key] ?? p.default}
                    onChange={e => update(key, e.target.value)}
                    className="w-32 bg-dark-900 border border-slate-700/40 rounded px-2 py-1 text-xs text-white"
                  >
                    {(p.options ?? []).map(o => <option key={o} value={o}>{o}</option>)}
                  </select>
                </div>
              )
            }
            return (
              <div key={key} className="flex items-center gap-3">
                <label className="text-xs text-slate-400 w-28 shrink-0">{p.label}</label>
                <input
                  type="number"
                  min={p.min}
                  max={p.max}
                  step={p.type === 'float' ? 0.01 : 1}
                  value={value[key] ?? p.default}
                  onChange={e => update(key, p.type === 'float' ? parseFloat(e.target.value) : parseInt(e.target.value))}
                  className="w-24 bg-dark-900 border border-slate-700/40 rounded px-2 py-1 text-xs text-white"
                />
              </div>
            )
          })}
        </div>
      )}
    </div>
  )
}


function NewsConfig({
  config,
  onChange,
}: {
  config: Record<string, any>
  onChange: (c: Record<string, any>) => void
}) {
  const set = (k: string, v: any) => onChange({ ...config, [k]: v })
  return (
    <div className="space-y-3">
      <div className="grid grid-cols-2 gap-3">
        <div>
          <label className="text-xs text-slate-400 block mb-1">Score min d'impact</label>
          <input
            type="number" min={0} max={1} step={0.05}
            value={config.min_impact ?? 0.55}
            onChange={e => set('min_impact', parseFloat(e.target.value))}
            className="w-full bg-dark-900 border border-slate-700/40 rounded px-2 py-1.5 text-sm text-white"
          />
        </div>
        <div>
          <label className="text-xs text-slate-400 block mb-1">Max events à évaluer</label>
          <input
            type="number" min={1} max={50}
            value={config.max_evaluate ?? 15}
            onChange={e => set('max_evaluate', parseInt(e.target.value))}
            className="w-full bg-dark-900 border border-slate-700/40 rounded px-2 py-1.5 text-sm text-white"
          />
        </div>
      </div>

      <div className="flex items-center gap-3">
        <button
          onClick={() => set('dedup_enabled', !config.dedup_enabled)}
          className="shrink-0"
        >
          {config.dedup_enabled
            ? <ToggleRight className="w-5 h-5 text-blue-400" />
            : <ToggleLeft  className="w-5 h-5 text-slate-600" />}
        </button>
        <span className="text-sm text-slate-300">Déduplication sémantique</span>
        {config.dedup_enabled && (
          <div className="flex items-center gap-2 ml-auto">
            <span className="text-xs text-slate-500">Fenêtre ± jours</span>
            <input
              type="number" min={1} max={7}
              value={config.dedup_lookback_days ?? 2}
              onChange={e => set('dedup_lookback_days', parseInt(e.target.value))}
              className="w-14 bg-dark-900 border border-slate-700/40 rounded px-2 py-1 text-xs text-white"
            />
          </div>
        )}
      </div>
    </div>
  )
}


const ECO_COUNTRIES = [
  { code: 'USD', label: 'États-Unis' },
  { code: 'EUR', label: 'Zone Euro' },
  { code: 'GBP', label: 'Royaume-Uni' },
  { code: 'JPY', label: 'Japon' },
  { code: 'AUD', label: 'Australie' },
  { code: 'CAD', label: 'Canada' },
  { code: 'NZD', label: 'Nouvelle-Zélande' },
  { code: 'CHF', label: 'Suisse' },
  { code: 'CNY', label: 'Chine' },
]
const ECO_DEFAULT_COUNTRIES = ['USD', 'EUR', 'GBP', 'JPY']

const ECO_EVENT_TYPES = [
  { id: 'inflation',   label: 'Inflation (CPI/PCE/PPI)' },
  { id: 'emploi',      label: 'Emploi (NFP/Claims/ADP)' },
  { id: 'pmi',         label: 'PMI (Mfg/Services)' },
  { id: 'pib',         label: 'PIB / Croissance' },
  { id: 'taux',        label: 'Décisions de taux' },
  { id: 'commerce',    label: 'Balance commerciale' },
  { id: 'ventes',      label: 'Ventes au détail' },
  { id: 'logement',    label: 'Immobilier / Logement' },
  { id: 'confiance',   label: 'Confiance / Sentiment' },
]
const ECO_DEFAULT_TYPES = ['inflation', 'emploi', 'pmi', 'pib', 'taux']

function EcoConfig({
  config,
  onChange,
}: {
  config: Record<string, any>
  onChange: (c: Record<string, any>) => void
}) {
  const set = (k: string, v: any) => onChange({ ...config, [k]: v })
  const countries: string[] = config.currencies ?? ECO_DEFAULT_COUNTRIES
  const eventTypes: string[] = config.event_types ?? ECO_DEFAULT_TYPES

  const toggleCountry = (code: string) => {
    const next = countries.includes(code)
      ? countries.filter(c => c !== code)
      : [...countries, code]
    set('currencies', next)
  }

  const toggleEventType = (id: string) => {
    const next = eventTypes.includes(id)
      ? eventTypes.filter(t => t !== id)
      : [...eventTypes, id]
    set('event_types', next)
  }

  return (
    <div className="space-y-4">
      {/* Pays / Zones */}
      <div>
        <label className="text-xs text-slate-400 block mb-1.5">Pays / Zones économiques</label>
        <div className="flex flex-wrap gap-1.5">
          {ECO_COUNTRIES.map(c => (
            <button
              key={c.code}
              onClick={() => toggleCountry(c.code)}
              title={c.label}
              className={clsx(
                'px-2.5 py-0.5 rounded text-xs border font-mono transition-colors',
                countries.includes(c.code)
                  ? 'bg-emerald-900/40 border-emerald-600/60 text-emerald-300'
                  : 'bg-dark-800 border-slate-700/40 text-slate-500 hover:border-slate-600',
              )}
            >
              {c.code}
            </button>
          ))}
        </div>
      </div>

      {/* Types d'événements */}
      <div>
        <label className="text-xs text-slate-400 block mb-1.5">Types d'événements calendar</label>
        <div className="flex flex-wrap gap-1.5">
          {ECO_EVENT_TYPES.map(t => (
            <button
              key={t.id}
              onClick={() => toggleEventType(t.id)}
              className={clsx(
                'px-2.5 py-1 rounded text-xs border transition-colors',
                eventTypes.includes(t.id)
                  ? 'bg-blue-900/40 border-blue-600/60 text-blue-300'
                  : 'bg-dark-800 border-slate-700/40 text-slate-500 hover:border-slate-600',
              )}
            >
              {t.label}
            </button>
          ))}
        </div>
      </div>

      {/* Impact + seuil surprise + releases contexte */}
      <div className="grid grid-cols-3 gap-3">
        <div>
          <label className="text-xs text-slate-400 block mb-1">Impact minimum</label>
          <select
            value={config.min_impact ?? 'medium'}
            onChange={e => set('min_impact', e.target.value)}
            className="w-full bg-dark-900 border border-slate-700/40 rounded px-2 py-1.5 text-sm text-white"
          >
            <option value="high">High seulement</option>
            <option value="medium">High + Medium</option>
            <option value="low">Tous niveaux</option>
          </select>
        </div>
        <div>
          <label className="text-xs text-slate-400 block mb-1">Seuil surprise z-score</label>
          <input
            type="number" min={0.5} max={5} step={0.1}
            value={config.z_threshold ?? 1.5}
            onChange={e => set('z_threshold', parseFloat(e.target.value))}
            className="w-full bg-dark-900 border border-slate-700/40 rounded px-2 py-1.5 text-sm text-white"
          />
        </div>
        <div>
          <label className="text-xs text-slate-400 block mb-1">Releases contexte</label>
          <input
            type="number" min={0} max={10}
            value={config.lookback_releases ?? 3}
            onChange={e => set('lookback_releases', parseInt(e.target.value))}
            className="w-full bg-dark-900 border border-slate-700/40 rounded px-2 py-1.5 text-sm text-white"
          />
        </div>
      </div>

      {/* create_market_event toggle */}
      <div className="flex items-center gap-3">
        <button
          onClick={() => set('create_market_event', !(config.create_market_event ?? true))}
          className="shrink-0"
        >
          {(config.create_market_event ?? true)
            ? <ToggleRight className="w-5 h-5 text-emerald-400" />
            : <ToggleLeft  className="w-5 h-5 text-slate-600" />}
        </button>
        <div>
          <span className="text-sm text-slate-300">Créer market_event automatiquement</span>
          <p className="text-xs text-slate-600">Si désactivé, les surprises sont détectées mais pas enregistrées</p>
        </div>
      </div>

      {/* auto_template toggle — only meaningful when create_market_event is on */}
      <div className={`flex items-center gap-3 ${!(config.create_market_event ?? true) ? 'opacity-40 pointer-events-none' : ''}`}>
        <button
          onClick={() => set('auto_template', !(config.auto_template ?? false))}
          className="shrink-0"
        >
          {(config.auto_template ?? false)
            ? <ToggleRight className="w-5 h-5 text-violet-400" />
            : <ToggleLeft  className="w-5 h-5 text-slate-600" />}
        </button>
        <div>
          <span className="text-sm text-slate-300">Associer template causal automatiquement</span>
          <p className="text-xs text-slate-600">L'IA sélectionne le template le plus proche (≥ 60% de confiance) ou en génère un nouveau via GPT-4o</p>
        </div>
      </div>
    </div>
  )
}


function FundamentalConfig({
  config,
  onChange,
}: {
  config: Record<string, any>
  onChange: (c: Record<string, any>) => void
}) {
  const set = (k: string, v: any) => onChange({ ...config, [k]: v })
  const FOCUS_TYPES = ['layoffs', 'earnings', 'ma', 'credit', 'regulatory', 'guidance']
  const focus: string[] = config.focus_types ?? FOCUS_TYPES
  const toggleFocus = (t: string) => {
    const next = focus.includes(t) ? focus.filter(x => x !== t) : [...focus, t]
    set('focus_types', next)
  }
  return (
    <div className="space-y-3">
      <div className="grid grid-cols-2 gap-3">
        <div>
          <label className="text-xs text-slate-400 block mb-1">Score min d'impact</label>
          <input
            type="number" min={0} max={1} step={0.05}
            value={config.min_impact ?? 0.45}
            onChange={e => set('min_impact', parseFloat(e.target.value))}
            className="w-full bg-dark-900 border border-slate-700/40 rounded px-2 py-1.5 text-sm text-white"
          />
        </div>
        <div>
          <label className="text-xs text-slate-400 block mb-1">Lookback heures</label>
          <input
            type="number" min={24} max={168}
            value={config.lookback_hours ?? 72}
            onChange={e => set('lookback_hours', parseInt(e.target.value))}
            className="w-full bg-dark-900 border border-slate-700/40 rounded px-2 py-1.5 text-sm text-white"
          />
        </div>
      </div>
      <div>
        <div className="text-xs text-slate-400 mb-2">Types d'événements filtrés</div>
        <div className="flex flex-wrap gap-1.5">
          {FOCUS_TYPES.map(t => (
            <button
              key={t}
              onClick={() => toggleFocus(t)}
              className={clsx(
                'px-2 py-0.5 rounded text-xs border transition-colors capitalize',
                focus.includes(t)
                  ? 'bg-amber-900/40 border-amber-600/60 text-amber-300'
                  : 'bg-dark-800 border-slate-700/40 text-slate-500 hover:border-slate-600',
              )}
            >
              {t}
            </button>
          ))}
        </div>
      </div>
      <div className="flex items-center gap-3">
        <button onClick={() => set('dedup_enabled', !config.dedup_enabled)} className="shrink-0">
          {config.dedup_enabled
            ? <ToggleRight className="w-5 h-5 text-amber-400" />
            : <ToggleLeft  className="w-5 h-5 text-slate-600" />}
        </button>
        <span className="text-sm text-slate-300">Déduplication sémantique</span>
        {config.dedup_enabled && (
          <div className="flex items-center gap-2 ml-auto">
            <span className="text-xs text-slate-500">Fenêtre ± jours</span>
            <input
              type="number" min={1} max={7}
              value={config.dedup_lookback_days ?? 3}
              onChange={e => set('dedup_lookback_days', parseInt(e.target.value))}
              className="w-14 bg-dark-900 border border-slate-700/40 rounded px-2 py-1 text-xs text-white"
            />
          </div>
        )}
      </div>
    </div>
  )
}


function GaugeThresholdConfig({
  selectedGauges,
  config,
  onChange,
}: {
  selectedGauges: string[]
  config: Record<string, any>
  onChange: (c: Record<string, any>) => void
}) {
  if (!selectedGauges.length) return null

  const thresholds: Record<string, any> = config.gauge_thresholds ?? {}

  const update = (gaugeId: string, field: string, val: any) => {
    const current = thresholds[gaugeId] ?? { enabled: false }
    onChange({
      ...config,
      gauge_thresholds: { ...thresholds, [gaugeId]: { ...current, [field]: val } },
    })
  }

  const getGauge = (id: string) => MACRO_GAUGE_LIST.find(g => g.id === id)

  return (
    <div className="space-y-1.5">
      <div className="text-xs text-slate-500 mb-2 flex items-center gap-2">
        <span>Alertes par compteur macro sélectionné</span>
        <span className="text-slate-700">— laisser vide pour désactiver le critère</span>
      </div>
      <div className="grid grid-cols-[auto_1fr_auto_auto_auto] gap-x-3 gap-y-1 items-center text-[10px] text-slate-600 px-1 mb-1">
        <span />
        <span>Compteur</span>
        <span className="text-center w-20">≤ Seuil bas</span>
        <span className="text-center w-20">≥ Seuil haut</span>
        <span className="text-center w-16">Δ% alerte</span>
      </div>
      {selectedGauges.map(gaugeId => {
        const gauge   = getGauge(gaugeId)
        const cfg_g   = thresholds[gaugeId] ?? { enabled: false }
        const enabled = cfg_g.enabled ?? false
        return (
          <div key={gaugeId} className={clsx(
            'grid grid-cols-[auto_1fr_auto_auto_auto] gap-x-3 items-center px-3 py-2 rounded-lg border transition-colors',
            enabled ? 'border-rose-700/40 bg-rose-900/10' : 'border-slate-700/30 bg-dark-800/60',
          )}>
            <button onClick={() => update(gaugeId, 'enabled', !enabled)} className="shrink-0">
              {enabled
                ? <ToggleRight className="w-5 h-5 text-rose-400" />
                : <ToggleLeft  className="w-5 h-5 text-slate-600" />}
            </button>
            <span className={clsx('text-sm', enabled ? 'text-white' : 'text-slate-500')}>
              {gauge?.label ?? gaugeId}
              <span className="ml-1.5 text-[10px] text-slate-600">{gauge?.bloc}</span>
            </span>
            <input
              type="number" step="any" placeholder="—"
              disabled={!enabled}
              value={cfg_g.low_threshold ?? ''}
              onChange={e => update(gaugeId, 'low_threshold', e.target.value === '' ? null : parseFloat(e.target.value))}
              className="w-20 bg-dark-900 border border-slate-700/40 rounded px-2 py-1 text-xs text-white placeholder-slate-700 disabled:opacity-30"
            />
            <input
              type="number" step="any" placeholder="—"
              disabled={!enabled}
              value={cfg_g.high_threshold ?? ''}
              onChange={e => update(gaugeId, 'high_threshold', e.target.value === '' ? null : parseFloat(e.target.value))}
              className="w-20 bg-dark-900 border border-slate-700/40 rounded px-2 py-1 text-xs text-white placeholder-slate-700 disabled:opacity-30"
            />
            <input
              type="number" step="any" placeholder="—"
              disabled={!enabled}
              value={cfg_g.change_pct_threshold ?? ''}
              onChange={e => update(gaugeId, 'change_pct_threshold', e.target.value === '' ? null : parseFloat(e.target.value))}
              className="w-16 bg-dark-900 border border-slate-700/40 rounded px-2 py-1 text-xs text-white placeholder-slate-700 disabled:opacity-30"
            />
          </div>
        )
      })}
    </div>
  )
}


function ReportConfig({
  config,
  onChange,
}: {
  config: Record<string, any>
  onChange: (c: Record<string, any>) => void
}) {
  const set = (k: string, v: any) => onChange({ ...config, [k]: v })
  return (
    <div className="grid grid-cols-2 gap-3">
      <div>
        <label className="text-xs text-slate-400 block mb-1">Jours lookback</label>
        <input
          type="number" min={1} max={30}
          value={config.days ?? 7}
          onChange={e => set('days', parseInt(e.target.value))}
          className="w-full bg-dark-900 border border-slate-700/40 rounded px-2 py-1.5 text-sm text-white"
        />
      </div>
      <div>
        <label className="text-xs text-slate-400 block mb-1">Importance min (1-5)</label>
        <input
          type="number" min={1} max={5}
          value={config.min_importance ?? 3}
          onChange={e => set('min_importance', parseInt(e.target.value))}
          className="w-full bg-dark-900 border border-slate-700/40 rounded px-2 py-1.5 text-sm text-white"
        />
      </div>
    </div>
  )
}


// ── Desk editor ───────────────────────────────────────────────────────────────

function DeskEditor({
  desk,
  catalog,
  onSave,
  onDelete,
}: {
  desk: AIDesk
  catalog: SignalDef[]
  onSave: (d: AIDesk) => void
  onDelete: () => void
}) {
  const [d, setD] = useState<AIDesk>(desk)
  const set = (k: keyof AIDesk, v: any) => setD(prev => ({ ...prev, [k]: v }))
  const dirty = JSON.stringify(d) !== JSON.stringify(desk)

  // Ensure signals config is initialized from catalog for technical + sentiment desks
  useEffect(() => {
    if ((d.type !== 'technical' && d.type !== 'sentiment') || !catalog.length) return
    const signals = d.config.signals ?? {}
    let changed = false
    const next = { ...signals }
    for (const sig of catalog) {
      if (!next[sig.id]) {
        const defaults: Record<string, any> = { enabled: false }
        for (const [k, p] of Object.entries(sig.params)) {
          defaults[k] = p.default
        }
        next[sig.id] = defaults
        changed = true
      }
    }
    if (changed) setD(prev => ({ ...prev, config: { ...prev.config, signals: next } }))
  }, [catalog, d.type])

  const updateSignal = (sigId: string, val: any) => {
    setD(prev => ({
      ...prev,
      config: { ...prev.config, signals: { ...(prev.config.signals ?? {}), [sigId]: val } },
    }))
  }

  return (
    <div className="space-y-5">
      {/* Header controls */}
      <div className="flex items-center gap-3">
        <div className="flex-1">
          <input
            value={d.name}
            onChange={e => set('name', e.target.value)}
            placeholder="Nom du desk"
            className="w-full bg-dark-900 border border-slate-700/40 rounded px-3 py-2 text-sm text-white"
          />
        </div>
        <select
          value={d.type}
          onChange={e => set('type', e.target.value as AIDesk['type'])}
          className="bg-dark-900 border border-slate-700/40 rounded px-3 py-2 text-sm text-white"
        >
          {Object.entries(TYPE_LABELS).map(([v, l]) => (
            <option key={v} value={v}>{l}</option>
          ))}
        </select>
        <button
          onClick={() => set('active', !d.active)}
          className={clsx('flex items-center gap-1.5 px-3 py-2 rounded border text-xs font-medium transition-colors',
            d.active
              ? 'bg-emerald-900/30 border-emerald-700/40 text-emerald-400'
              : 'bg-dark-800 border-slate-700/30 text-slate-500',
          )}
        >
          {d.active ? <ToggleRight className="w-4 h-4" /> : <ToggleLeft className="w-4 h-4" />}
          {d.active ? 'Actif' : 'Inactif'}
        </button>
      </div>

      {/* System prompt */}
      <div>
        <label className="text-xs text-slate-400 block mb-1">System prompt</label>
        <textarea
          value={d.system_prompt}
          onChange={e => set('system_prompt', e.target.value)}
          rows={4}
          placeholder="Instructions spécifiques pour ce desk AI..."
          className="w-full bg-dark-900 border border-slate-700/40 rounded px-3 py-2 text-sm text-white resize-y font-mono"
        />
      </div>

      {/* Instruments / Gauges — not shown for eco (link is through causal graph) */}
      {d.type === 'sentiment' ? (
        <MacroGaugeSelector
          selected={d.instruments}
          onChange={v => set('instruments', v)}
        />
      ) : d.type !== 'eco' && (
        <InstrumentSelector
          selected={d.instruments}
          onChange={v => set('instruments', v)}
        />
      )}

      {/* Type-specific config */}
      <div>
        <div className="text-xs text-slate-400 mb-2">Configuration</div>
        {(d.type === 'news') && (
          <NewsConfig config={d.config} onChange={c => set('config', c)} />
        )}
        {d.type === 'fundamental' && (
          <FundamentalConfig config={d.config} onChange={c => set('config', c)} />
        )}
        {d.type === 'eco' && (
          <EcoConfig config={d.config} onChange={c => set('config', c)} />
        )}
        {d.type === 'report' && (
          <ReportConfig config={d.config} onChange={c => set('config', c)} />
        )}
        {(d.type === 'technical' || d.type === 'sentiment') && catalog.length > 0 && (() => {
          const deskSignals = catalog.filter(s => !s.desk_type || s.desk_type === d.type)
          return (
            <div className="space-y-2">
              {deskSignals.map(sig => (
                <SignalToggle
                  key={sig.id}
                  signal={sig}
                  value={d.config.signals?.[sig.id] ?? { enabled: false }}
                  onChange={v => updateSignal(sig.id, v)}
                />
              ))}
              {d.type === 'technical' && (
                <div className="pt-1">
                  <label className="text-xs text-slate-400 block mb-1">Lookback jours</label>
                  <input
                    type="number" min={1} max={30}
                    value={d.config.lookback_days ?? 7}
                    onChange={e => set('config', { ...d.config, lookback_days: parseInt(e.target.value) })}
                    className="w-24 bg-dark-900 border border-slate-700/40 rounded px-2 py-1.5 text-sm text-white"
                  />
                </div>
              )}
              {d.type === 'sentiment' && (
                <div className="pt-1">
                  <label className="text-xs text-slate-400 block mb-1">Lookback jours</label>
                  <input
                    type="number" min={1} max={14}
                    value={d.config.lookback_days ?? 5}
                    onChange={e => set('config', { ...d.config, lookback_days: parseInt(e.target.value) })}
                    className="w-24 bg-dark-900 border border-slate-700/40 rounded px-2 py-1.5 text-sm text-white"
                  />
                </div>
              )}
            </div>
          )
        })()}
      </div>

      {/* Gauge threshold alerts — Sentiment only */}
      {d.type === 'sentiment' && d.instruments.length > 0 && (
        <div>
          <div className="text-xs text-slate-400 mb-2">Configuration des alertes par compteur</div>
          <GaugeThresholdConfig
            selectedGauges={d.instruments}
            config={d.config}
            onChange={c => set('config', c)}
          />
        </div>
      )}

      {/* Actions */}
      <div className="flex items-center justify-between pt-2 border-t border-slate-700/30">
        <button
          onClick={onDelete}
          className="flex items-center gap-1.5 px-3 py-1.5 rounded text-xs text-red-400 hover:bg-red-900/20 border border-transparent hover:border-red-800/40 transition-colors"
        >
          <Trash2 className="w-3.5 h-3.5" />
          Supprimer
        </button>
        <button
          onClick={() => onSave(d)}
          disabled={!dirty}
          className={clsx(
            'flex items-center gap-1.5 px-4 py-1.5 rounded text-sm font-medium transition-colors',
            dirty
              ? 'bg-blue-600 hover:bg-blue-500 text-white'
              : 'bg-dark-700 text-slate-600 cursor-not-allowed',
          )}
        >
          <Save className="w-4 h-4" />
          Enregistrer
        </button>
      </div>
    </div>
  )
}


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

export default function AIDesks() {
  const [desks, setDesks]       = useState<AIDesk[]>([])
  const [catalog, setCatalog]   = useState<SignalDef[]>([])
  const [selected, setSelected] = useState<number | null>(null)
  const [loading, setLoading]   = useState(true)
  const [saving, setSaving]     = useState(false)
  const [msg, setMsg]           = useState<{ ok: boolean; text: string } | null>(null)

  const load = useCallback(async () => {
    setLoading(true)
    const [dRes, cRes] = await Promise.all([
      fetch('/api/ai-desks'),
      fetch('/api/ai-desks/signal-catalog'),
    ])
    const dData = await dRes.json()
    const cData = await cRes.json()
    setDesks(dData)
    setCatalog(cData)
    if (dData.length > 0 && selected === null) setSelected(0)
    setLoading(false)
  }, [])

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

  const showMsg = (ok: boolean, text: string) => {
    setMsg({ ok, text })
    setTimeout(() => setMsg(null), 3000)
  }

  const handleSave = async (d: AIDesk) => {
    setSaving(true)
    try {
      const method = d.id ? 'PUT' : 'POST'
      const url    = d.id ? `/api/ai-desks/${d.id}` : '/api/ai-desks'
      const r = await fetch(url, {
        method,
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(d),
      })
      if (r.ok) {
        showMsg(true, 'Desk enregistré')
        await load()
      } else {
        const err = await r.json()
        showMsg(false, err.detail ?? 'Erreur sauvegarde')
      }
    } finally {
      setSaving(false)
    }
  }

  const handleDelete = async (d: AIDesk) => {
    if (!d.id) return
    if (!confirm(`Supprimer le desk "${d.name}" ?`)) return
    const r = await fetch(`/api/ai-desks/${d.id}`, { method: 'DELETE' })
    if (r.ok) {
      showMsg(true, 'Desk supprimé')
      setSelected(null)
      await load()
    }
  }

  const handleNew = () => {
    const newDesk: AIDesk = {
      name:          'Nouveau Desk',
      type:          'news',
      active:        true,
      system_prompt: '',
      instruments:   [],
      config:        {},
    }
    setDesks(prev => [...prev, newDesk])
    setSelected(desks.length)
  }

  const currentDesk = selected !== null ? desks[selected] : null

  return (
    <div className="p-6 max-w-7xl mx-auto space-y-4">
      {/* Header */}
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-3">
          <Bot className="w-6 h-6 text-blue-400" />
          <div>
            <h1 className="text-xl font-bold text-white">AI Desks</h1>
            <p className="text-sm text-slate-500">Configurer les agents IA spécialisés</p>
          </div>
        </div>
        <button
          onClick={handleNew}
          className="flex items-center gap-2 px-4 py-2 bg-blue-600 hover:bg-blue-500 text-white text-sm rounded-lg transition-colors"
        >
          <Plus className="w-4 h-4" />
          Nouveau desk
        </button>
      </div>

      {msg && (
        <div className={clsx(
          'px-4 py-2 rounded-lg text-sm border',
          msg.ok
            ? 'bg-emerald-900/30 border-emerald-700/40 text-emerald-300'
            : 'bg-red-900/30 border-red-700/40 text-red-300',
        )}>
          {msg.text}
        </div>
      )}

      {loading ? (
        <div className="text-slate-500 text-sm py-8 text-center">Chargement...</div>
      ) : (
        <div className="grid grid-cols-[240px_1fr] gap-4">
          {/* Desk list */}
          <div className="space-y-1">
            {desks.map((d, i) => (
              <button
                key={d.id ?? `new-${i}`}
                onClick={() => setSelected(i)}
                className={clsx(
                  'w-full text-left px-3 py-2.5 rounded-lg border transition-colors',
                  selected === i
                    ? 'bg-blue-900/30 border-blue-700/40 text-white'
                    : 'bg-dark-800/60 border-slate-700/30 text-slate-400 hover:text-white hover:border-slate-600/60',
                )}
              >
                <div className="flex items-center gap-2">
                  <span className={clsx(
                    'inline-block w-1.5 h-1.5 rounded-full',
                    d.active ? 'bg-emerald-400' : 'bg-slate-600',
                  )} />
                  <span className="text-sm font-medium truncate">{d.name}</span>
                </div>
                <span className={clsx(
                  'inline-block mt-1 px-1.5 py-0.5 rounded text-xs border',
                  TYPE_COLORS[d.type] ?? 'text-slate-400 bg-dark-700 border-slate-700/30',
                )}>
                  {TYPE_LABELS[d.type] ?? d.type}
                </span>
              </button>
            ))}
          </div>

          {/* Editor */}
          {currentDesk ? (
            <div className="bg-dark-800/60 rounded-xl border border-slate-700/30 p-5">
              <DeskEditor
                key={currentDesk.id ?? `new-${selected}`}
                desk={currentDesk}
                catalog={catalog}
                onSave={handleSave}
                onDelete={() => handleDelete(currentDesk)}
              />
            </div>
          ) : (
            <div className="bg-dark-800/60 rounded-xl border border-slate-700/30 flex items-center justify-center text-slate-600 text-sm">
              Sélectionner un desk ou en créer un nouveau
            </div>
          )}
        </div>
      )}
    </div>
  )
}
