import { useState, useEffect, useCallback } from 'react'
import clsx from 'clsx'
import { RefreshCw, TrendingUp, TrendingDown, Minus } from 'lucide-react'
import {
  ComposedChart, Line, XAxis, YAxis, CartesianGrid, Tooltip,
  ResponsiveContainer, ReferenceLine, Area,
} from 'recharts'

const API = ''

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

interface SeriesMeta {
  id: string
  name: string
  category: string
  freq: string
  unit: string
  assets: string[]
}

interface TSPoint {
  event_date: string
  actual_value: number | null
  surprise_zscore: number | null
  surprise_direction: string | null
}

interface FFEvent {
  event_date: string
  event_time: string | null
  event_name: string
  actual_value: string | null
  forecast_value: string | null
  previous_value: string | null
  impact: string
}

interface SeriesHistory {
  series_id: string
  name: string
  unit: string
  category: string
  freq: string
  timeseries: TSPoint[]
  events: FFEvent[]
}

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

const CATEGORY_COLORS: Record<string, string> = {
  employment: '#3b82f6',
  inflation:  '#f59e0b',
  growth:     '#10b981',
  monetary:   '#8b5cf6',
  credit:     '#ef4444',
  rates:      '#06b6d4',
}

const CATEGORY_LABELS: Record<string, string> = {
  employment: 'Employment',
  inflation:  'Inflation',
  growth:     'Growth',
  monetary:   'Monetary',
  credit:     'Credit',
  rates:      'Rates',
}

const RANGE_OPTIONS = [
  { key: '1y',  label: '1Y',  months: 12 },
  { key: '2y',  label: '2Y',  months: 24 },
  { key: '5y',  label: '5Y',  months: 60 },
  { key: '10y', label: '10Y', months: 120 },
  { key: 'all', label: 'All', months: 999 },
]

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

function fromDateForRange(months: number): string {
  if (months >= 999) return '2007-01-01'
  const d = new Date()
  d.setMonth(d.getMonth() - months)
  return d.toISOString().slice(0, 10)
}

function fmtDate(s: string): string {
  return s.slice(0, 7) // YYYY-MM
}

function fmtVal(v: number | null, unit: string): string {
  if (v === null) return '—'
  const fixed = Math.abs(v) < 10 ? 2 : 1
  return `${v.toFixed(fixed)} ${unit}`
}

// ── Custom Tooltip ────────────────────────────────────────────────────────────

interface TooltipPayload {
  event_date: string
  value: number | null
  zscore: number | null
  direction: string | null
  ff_actual?: string
  ff_forecast?: string
  ff_event?: string
}

function ChartTooltip({ active, payload, unit }: {
  active?: boolean
  payload?: Array<{ payload: TooltipPayload }>
  unit: string
}) {
  if (!active || !payload?.length) return null
  const d = payload[0].payload
  return (
    <div className="bg-slate-900 border border-slate-600 rounded p-2.5 text-xs shadow-xl min-w-[160px]">
      <div className="text-slate-400 mb-1">{d.event_date}</div>
      <div className="text-white font-semibold mb-1">
        {d.value !== null ? `${d.value?.toFixed(2)} ${unit}` : '—'}
      </div>
      {d.zscore !== null && (
        <div className={clsx(
          'text-xs',
          d.direction === 'bullish' ? 'text-emerald-400' :
          d.direction === 'bearish' ? 'text-red-400' : 'text-slate-400'
        )}>
          z-score: {d.zscore?.toFixed(2)}
        </div>
      )}
      {d.ff_event && (
        <div className="mt-1.5 pt-1.5 border-t border-slate-700">
          <div className="text-slate-500 text-[10px]">FF Release</div>
          <div className="text-slate-200">{d.ff_event}</div>
          {d.ff_forecast && <div className="text-slate-400">Forecast: {d.ff_forecast}</div>}
          {d.ff_actual   && <div className="text-slate-300">Actual: {d.ff_actual}</div>}
        </div>
      )}
    </div>
  )
}

// ── Direction Icon ─────────────────────────────────────────────────────────────

function DirIcon({ dir }: { dir: string | null }) {
  if (dir === 'bullish') return <TrendingUp size={12} className="text-emerald-400" />
  if (dir === 'bearish') return <TrendingDown size={12} className="text-red-400" />
  return <Minus size={12} className="text-slate-500" />
}

// ── Series Sidebar ─────────────────────────────────────────────────────────────

function SeriesList({
  series,
  selected,
  onSelect,
}: {
  series: SeriesMeta[]
  selected: string
  onSelect: (id: string) => void
}) {
  const grouped = series.reduce<Record<string, SeriesMeta[]>>((acc, s) => {
    if (!acc[s.category]) acc[s.category] = []
    acc[s.category].push(s)
    return acc
  }, {})

  return (
    <div className="flex flex-col gap-3">
      {Object.entries(grouped).map(([cat, items]) => (
        <div key={cat}>
          <div className="text-xs font-semibold uppercase tracking-wider mb-1"
            style={{ color: CATEGORY_COLORS[cat] ?? '#64748b' }}>
            {CATEGORY_LABELS[cat] ?? cat}
          </div>
          <div className="flex flex-col gap-0.5">
            {items.map(s => (
              <button
                key={s.id}
                onClick={() => onSelect(s.id)}
                className={clsx(
                  'text-left px-2.5 py-1.5 rounded text-sm transition-colors',
                  selected === s.id
                    ? 'bg-slate-700 text-white'
                    : 'text-slate-400 hover:bg-slate-800 hover:text-slate-200'
                )}
              >
                {s.name}
                <span className="ml-1.5 text-xs text-slate-600">{s.unit}</span>
              </button>
            ))}
          </div>
        </div>
      ))}
    </div>
  )
}

// ── Events Table ──────────────────────────────────────────────────────────────

function EventsTable({ events, unit }: { events: FFEvent[]; unit: string }) {
  const recent = [...events].reverse().slice(0, 30)
  if (!recent.length) return (
    <div className="text-slate-600 text-sm text-center py-6">
      No FF events linked to this series yet.<br/>
      <span className="text-xs">Import the CSV and run the bootstrap first.</span>
    </div>
  )

  return (
    <div className="overflow-x-auto">
      <table className="w-full text-xs">
        <thead>
          <tr className="text-slate-500 border-b border-slate-800">
            <th className="text-left py-1.5 pr-3">Date</th>
            <th className="text-left py-1.5 pr-3">Event</th>
            <th className="text-right py-1.5 pr-3">Actual</th>
            <th className="text-right py-1.5 pr-3">Forecast</th>
            <th className="text-right py-1.5">Previous</th>
          </tr>
        </thead>
        <tbody>
          {recent.map((ev, i) => {
            const aNum = parseFloat(ev.actual_value ?? '')
            const fNum = parseFloat(ev.forecast_value ?? '')
            const beat = !isNaN(aNum) && !isNaN(fNum) && aNum !== fNum
            const better = beat && aNum > fNum
            return (
              <tr key={i} className="border-b border-slate-800/50 hover:bg-slate-800/30">
                <td className="py-1.5 pr-3 text-slate-400 tabular-nums">{ev.event_date}</td>
                <td className="py-1.5 pr-3 text-slate-300 max-w-[200px] truncate">{ev.event_name}</td>
                <td className={clsx('py-1.5 pr-3 text-right tabular-nums font-medium',
                  beat ? (better ? 'text-emerald-400' : 'text-red-400') : 'text-slate-200')}>
                  {ev.actual_value ?? '—'}
                </td>
                <td className="py-1.5 pr-3 text-right tabular-nums text-slate-400">
                  {ev.forecast_value ?? '—'}
                </td>
                <td className="py-1.5 text-right tabular-nums text-slate-500">
                  {ev.previous_value ?? '—'}
                </td>
              </tr>
            )
          })}
        </tbody>
      </table>
    </div>
  )
}

// ── Main Page ─────────────────────────────────────────────────────────────────

export default function MacroSeriesPage() {
  const [seriesList, setSeriesList] = useState<SeriesMeta[]>([])
  const [selectedId, setSelectedId]   = useState<string>('PAYEMS')
  const [range, setRange]             = useState('5y')
  const [history, setHistory]         = useState<SeriesHistory | null>(null)
  const [loading, setLoading]         = useState(false)

  // Load series catalog
  useEffect(() => {
    fetch(`${API}/api/eco/series`).then(r => r.json()).then(setSeriesList).catch(() => {})
  }, [])

  const loadHistory = useCallback(async () => {
    if (!selectedId) return
    setLoading(true)
    try {
      const months = RANGE_OPTIONS.find(r => r.key === range)?.months ?? 60
      const from = fromDateForRange(months)
      const r: SeriesHistory = await fetch(
        `${API}/api/eco/series/${selectedId}/history?from_date=${from}`
      ).then(x => x.json())
      setHistory(r)
    } catch {}
    finally { setLoading(false) }
  }, [selectedId, range])

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

  // Build chart data — merge FRED time series + FF events by date
  const chartData = (() => {
    if (!history) return []
    const ffByDate = new Map<string, FFEvent>()
    for (const ev of history.events) ffByDate.set(ev.event_date, ev)

    return history.timeseries.map(pt => {
      const ff = ffByDate.get(pt.event_date)
      return {
        event_date: pt.event_date,
        label:      fmtDate(pt.event_date),
        value:      pt.actual_value,
        zscore:     pt.surprise_zscore,
        direction:  pt.surprise_direction,
        ff_event:   ff?.event_name ?? null,
        ff_actual:  ff?.actual_value ?? null,
        ff_forecast:ff?.forecast_value ?? null,
        // For reference lines — mark surprise events
        is_surprise: pt.surprise_zscore !== null && Math.abs(pt.surprise_zscore) >= 1.5,
      }
    })
  })()

  const color = CATEGORY_COLORS[history?.category ?? ''] ?? '#3b82f6'

  // Stats
  const values = chartData.map(d => d.value).filter((v): v is number => v !== null)
  const latest = values[values.length - 1] ?? null
  const prev   = values[values.length - 2] ?? null
  const minVal = values.length ? Math.min(...values) : null
  const maxVal = values.length ? Math.max(...values) : null
  const trend  = latest !== null && prev !== null ? (latest > prev ? 1 : latest < prev ? -1 : 0) : 0

  // Big surprises for reference lines
  const bigSurprises = chartData.filter(d => d.is_surprise)

  return (
    <div className="flex h-full overflow-hidden" style={{ minHeight: 0 }}>
      {/* Sidebar */}
      <div className="w-56 shrink-0 bg-slate-900 border-r border-slate-800 overflow-y-auto p-3">
        <div className="text-xs font-bold text-slate-400 uppercase tracking-wider mb-3">
          FRED Series
        </div>
        <SeriesList
          series={seriesList}
          selected={selectedId}
          onSelect={id => { setSelectedId(id); setHistory(null) }}
        />
      </div>

      {/* Main content */}
      <div className="flex-1 overflow-y-auto p-4 space-y-4">
        {/* Header */}
        <div className="flex items-start justify-between flex-wrap gap-3">
          <div>
            <h1 className="text-xl font-bold text-white">
              {history?.name ?? selectedId}
            </h1>
            <div className="text-slate-500 text-xs mt-0.5">
              {history?.category && (
                <span className="mr-2" style={{ color }}>
                  {CATEGORY_LABELS[history.category]}
                </span>
              )}
              {history?.freq} · FRED/{selectedId}
            </div>
          </div>

          <div className="flex items-center gap-2">
            {/* Range selector */}
            <div className="flex gap-1 bg-slate-800 rounded p-0.5">
              {RANGE_OPTIONS.map(r => (
                <button
                  key={r.key}
                  onClick={() => setRange(r.key)}
                  className={clsx(
                    'px-2.5 py-1 rounded text-xs font-medium transition-colors',
                    range === r.key ? 'bg-slate-600 text-white' : 'text-slate-400 hover:text-slate-200'
                  )}
                >
                  {r.label}
                </button>
              ))}
            </div>
            <button
              onClick={loadHistory}
              disabled={loading}
              className="p-1.5 rounded bg-slate-700 hover:bg-slate-600 disabled:opacity-50"
            >
              <RefreshCw size={13} className={clsx(loading && 'animate-spin')} />
            </button>
          </div>
        </div>

        {/* KPI cards */}
        {history && values.length > 0 && (
          <div className="grid grid-cols-4 gap-3">
            {[
              {
                label: 'Latest',
                value: fmtVal(latest, history.unit),
                sub: history.timeseries[history.timeseries.length - 1]?.event_date,
                accent: trend === 1 ? 'text-emerald-400' : trend === -1 ? 'text-red-400' : 'text-slate-200',
                icon: trend === 1 ? <TrendingUp size={14}/> : trend === -1 ? <TrendingDown size={14}/> : <Minus size={14}/>,
              },
              { label: 'Previous', value: fmtVal(prev, history.unit), sub: history.timeseries[history.timeseries.length - 2]?.event_date, accent: 'text-slate-300', icon: null },
              { label: 'Min (period)', value: fmtVal(minVal, history.unit), sub: null, accent: 'text-sky-400', icon: null },
              { label: 'Max (period)', value: fmtVal(maxVal, history.unit), sub: null, accent: 'text-amber-400', icon: null },
            ].map(card => (
              <div key={card.label} className="bg-slate-800 rounded-lg p-3 border border-slate-700">
                <div className="text-slate-500 text-xs mb-1">{card.label}</div>
                <div className={clsx('text-base font-bold flex items-center gap-1', card.accent)}>
                  {card.icon}{card.value}
                </div>
                {card.sub && <div className="text-slate-600 text-xs mt-0.5">{card.sub}</div>}
              </div>
            ))}
          </div>
        )}

        {/* Chart */}
        <div className="bg-slate-800 rounded-lg border border-slate-700 p-4">
          <div className="flex items-center justify-between mb-3">
            <span className="text-sm font-medium text-slate-300">
              Time Series
              {history && <span className="text-slate-500 text-xs ml-2">({chartData.length} data points)</span>}
            </span>
            {bigSurprises.length > 0 && (
              <span className="text-xs text-slate-500">
                {bigSurprises.length} big surprises (|z| ≥ 1.5)
              </span>
            )}
          </div>

          {loading && (
            <div className="h-64 flex items-center justify-center text-slate-600 text-sm">
              Loading…
            </div>
          )}

          {!loading && chartData.length === 0 && (
            <div className="h-64 flex items-center justify-center text-slate-600 text-sm">
              No data — run FRED bootstrap first in the Calendar page.
            </div>
          )}

          {!loading && chartData.length > 0 && (
            <ResponsiveContainer width="100%" height={280}>
              <ComposedChart data={chartData} margin={{ top: 4, right: 16, bottom: 4, left: 0 }}>
                <defs>
                  <linearGradient id={`grad-${selectedId}`} x1="0" y1="0" x2="0" y2="1">
                    <stop offset="5%"  stopColor={color} stopOpacity={0.25} />
                    <stop offset="95%" stopColor={color} stopOpacity={0} />
                  </linearGradient>
                </defs>
                <CartesianGrid strokeDasharray="3 3" stroke="#1e293b" />
                <XAxis
                  dataKey="label"
                  tick={{ fontSize: 10, fill: '#64748b' }}
                  interval="preserveStartEnd"
                  tickLine={false}
                />
                <YAxis
                  tick={{ fontSize: 10, fill: '#64748b' }}
                  tickLine={false}
                  axisLine={false}
                  width={50}
                  tickFormatter={v => `${v}${history?.unit === '%' || history?.unit === 'pp' ? '' : ''}`}
                />
                <Tooltip content={<ChartTooltip unit={history?.unit ?? ''} />} />

                {/* Zero line if series crosses zero */}
                {minVal !== null && maxVal !== null && minVal < 0 && maxVal > 0 && (
                  <ReferenceLine y={0} stroke="#475569" strokeDasharray="4 2" />
                )}

                {/* Big surprise markers */}
                {bigSurprises.map(s => (
                  <ReferenceLine
                    key={s.event_date}
                    x={fmtDate(s.event_date)}
                    stroke={s.direction === 'bullish' ? '#10b981' : s.direction === 'bearish' ? '#ef4444' : '#64748b'}
                    strokeWidth={1}
                    strokeDasharray="3 3"
                    opacity={0.6}
                  />
                ))}

                <Area
                  type="monotone"
                  dataKey="value"
                  stroke={color}
                  strokeWidth={2}
                  fill={`url(#grad-${selectedId})`}
                  dot={false}
                  activeDot={{ r: 4, fill: color }}
                />
              </ComposedChart>
            </ResponsiveContainer>
          )}

          {/* Legend for reference lines */}
          {bigSurprises.length > 0 && (
            <div className="flex items-center gap-4 mt-2 text-xs text-slate-500">
              <span className="flex items-center gap-1">
                <span className="w-4 border-t border-dashed border-emerald-500 inline-block" />
                Bullish surprise (|z|≥1.5)
              </span>
              <span className="flex items-center gap-1">
                <span className="w-4 border-t border-dashed border-red-500 inline-block" />
                Bearish surprise
              </span>
            </div>
          )}
        </div>

        {/* Events table */}
        <div className="bg-slate-800 rounded-lg border border-slate-700 p-4">
          <div className="text-sm font-medium text-slate-300 mb-3">
            FF Calendar Events
            {history && <span className="text-slate-500 text-xs ml-2">({history.events.length} linked)</span>}
          </div>
          {history && <EventsTable events={history.events} unit={history.unit} />}
        </div>

        {/* Z-score context */}
        {history && chartData.some(d => d.zscore !== null) && (
          <div className="bg-slate-800 rounded-lg border border-slate-700 p-4">
            <div className="text-sm font-medium text-slate-300 mb-3">Recent Surprises (FRED z-score)</div>
            <div className="flex flex-col gap-1">
              {chartData
                .filter(d => d.zscore !== null && d.zscore !== 0)
                .slice(-15)
                .reverse()
                .map((d, i) => (
                  <div key={i} className="flex items-center gap-2 text-xs">
                    <span className="text-slate-500 w-24 tabular-nums shrink-0">{d.event_date}</span>
                    <DirIcon dir={d.direction} />
                    <div className="flex-1 bg-slate-700 rounded-full h-1.5 overflow-hidden">
                      <div
                        className={clsx(
                          'h-full rounded-full',
                          d.direction === 'bullish' ? 'bg-emerald-500' :
                          d.direction === 'bearish' ? 'bg-red-500' : 'bg-slate-500'
                        )}
                        style={{ width: `${Math.min(100, Math.abs(d.zscore!) * 25)}%` }}
                      />
                    </div>
                    <span className={clsx(
                      'w-12 text-right tabular-nums',
                      d.direction === 'bullish' ? 'text-emerald-400' :
                      d.direction === 'bearish' ? 'text-red-400' : 'text-slate-400'
                    )}>
                      {d.zscore!.toFixed(2)}σ
                    </span>
                    <span className="text-slate-500 tabular-nums">
                      {d.value?.toFixed(2)} {history.unit}
                    </span>
                  </div>
                ))}
            </div>
          </div>
        )}
      </div>
    </div>
  )
}
