import { useRef, useEffect, useMemo } from 'react'

interface MarketEvent {
  id: number
  name: string
  start_date: string
  end_date: string | null
  level: 'long' | 'medium' | 'short'
  category: string
  impact_score: number
}

interface Props {
  events: MarketEvent[]
  refDate: string
  onDateChange: (d: string) => void
}

const SCALE       = 1.8   // px per day
const MARGIN_LEFT = 52    // year label area
const LEVEL_W     = 190   // fixed px per level column
const SUBCOL_GAP  = 2
const COL_GAP     = 8
const CONTAINER_H = 560
const MIN_EV_H    = 20
const FRISE_START = '2020-02-01'
const LEVEL_ORDER = ['long', 'medium', 'short'] as const

type Level = typeof LEVEL_ORDER[number]

const COLORS: Record<Level, { bg: string; border: string; text: string; track: string }> = {
  long:   { bg: '#2e1065', border: '#7c3aed', text: '#ede9fe', track: 'rgba(109,40,217,0.07)' },
  medium: { bg: '#1e3a5f', border: '#3b82f6', text: '#dbeafe', track: 'rgba(59,130,246,0.07)' },
  short:  { bg: '#064e3b', border: '#10b981', text: '#d1fae5', track: 'rgba(16,185,129,0.07)' },
}

const LEVEL_LABELS: Record<Level, string> = {
  long: 'Long Terme',
  medium: 'Moyen Terme',
  short: 'Court Terme',
}

function toDay(date: string): number {
  const origin = new Date(FRISE_START).getTime()
  return Math.floor((new Date(date + 'T00:00:00Z').getTime() - origin) / 86_400_000)
}

function assignSubCols(evs: MarketEvent[]): Map<number, number> {
  const sorted = [...evs].sort((a, b) => a.start_date.localeCompare(b.start_date))
  const colEnds: string[] = []
  const result = new Map<number, number>()
  for (const ev of sorted) {
    const end = ev.end_date ?? '2099-12-31'
    let placed = false
    for (let i = 0; i < colEnds.length; i++) {
      if (ev.start_date >= colEnds[i]) {
        result.set(ev.id, i); colEnds[i] = end; placed = true; break
      }
    }
    if (!placed) { result.set(ev.id, colEnds.length); colEnds.push(end) }
  }
  return result
}

export default function TimelineVertical({ events, refDate, onDateChange }: Props) {
  const scrollRef = useRef<HTMLDivElement>(null)
  const today = useMemo(() => new Date().toISOString().split('T')[0], [])
  const todayDay = toDay(today)
  const totalDays = todayDay + 60
  const totalHeight = totalDays * SCALE
  const refY = toDay(refDate) * SCALE
  const todayY = todayDay * SCALE

  const yearMarkers = useMemo(() => {
    const origin = new Date(FRISE_START)
    const out: { day: number; label: string }[] = []
    for (let y = origin.getFullYear(); y <= origin.getFullYear() + Math.ceil(totalDays / 365) + 1; y++) {
      const jan1 = new Date(y, 0, 1)
      const day = Math.floor((jan1.getTime() - origin.getTime()) / 86_400_000)
      if (day >= 0 && day <= totalDays) out.push({ day, label: String(y) })
    }
    return out
  }, [totalDays])

  const byLevel = useMemo(() => {
    const g: Record<Level, MarketEvent[]> = { long: [], medium: [], short: [] }
    for (const ev of events) {
      const l = ev.level as Level
      if (g[l]) g[l].push(ev)
    }
    return g
  }, [events])

  const subColsMap = useMemo(() => {
    const m = {} as Record<Level, Map<number, number>>
    for (const l of LEVEL_ORDER) m[l] = assignSubCols(byLevel[l])
    return m
  }, [byLevel])

  const maxSubCols = useMemo(() => {
    const m = { long: 1, medium: 1, short: 1 } as Record<Level, number>
    for (const l of LEVEL_ORDER) {
      const vals = [...subColsMap[l].values()]
      if (vals.length) m[l] = Math.min(Math.max(...vals) + 1, 4) // cap at 4 sub-cols
    }
    return m
  }, [subColsMap])

  const colX = useMemo(() => {
    const x = {} as Record<Level, number>
    let cur = MARGIN_LEFT
    for (const l of LEVEL_ORDER) { x[l] = cur; cur += LEVEL_W + COL_GAP }
    return x
  }, [])

  const totalWidth = MARGIN_LEFT + LEVEL_ORDER.length * (LEVEL_W + COL_GAP)

  function subColW(level: Level): number {
    const n = maxSubCols[level]
    return Math.max((LEVEL_W - (n - 1) * SUBCOL_GAP) / n, 30)
  }

  useEffect(() => {
    const el = scrollRef.current
    if (!el) return
    el.scrollTop = Math.max(0, refY - el.clientHeight / 2)
  }, [refDate, refY])

  return (
    <div className="bg-dark-800 rounded-xl border border-slate-700/40 overflow-hidden">
      {/* Column headers */}
      <div className="flex border-b border-slate-700/30" style={{ paddingLeft: MARGIN_LEFT + 'px' }}>
        {LEVEL_ORDER.map((l, i) => (
          <div
            key={l}
            className="flex items-center justify-center text-xs font-semibold py-2.5 shrink-0"
            style={{
              width: LEVEL_W + 'px',
              marginRight: i < LEVEL_ORDER.length - 1 ? COL_GAP + 'px' : 0,
              color: COLORS[l].text,
              borderBottom: `2px solid ${COLORS[l].border}`,
            }}
          >
            {LEVEL_LABELS[l]}
          </div>
        ))}
      </div>

      {/* Scrollable area */}
      <div
        ref={scrollRef}
        style={{ height: CONTAINER_H + 'px', overflowY: 'auto', overflowX: 'hidden', position: 'relative' }}
        className="scrollbar-thin"
      >
        <div style={{ position: 'relative', height: totalHeight + 'px', width: totalWidth + 'px', minWidth: '100%' }}>

          {/* Column track backgrounds */}
          {LEVEL_ORDER.map(l => (
            <div key={l} style={{
              position: 'absolute',
              top: 0,
              height: totalHeight + 'px',
              left: colX[l],
              width: LEVEL_W + 'px',
              background: COLORS[l].track,
              borderLeft: `1px solid ${COLORS[l].border}18`,
              borderRight: `1px solid ${COLORS[l].border}18`,
            }} />
          ))}

          {/* Year lines + labels */}
          {yearMarkers.map(m => (
            <div key={m.label} style={{
              position: 'absolute',
              top: m.day * SCALE,
              left: 0,
              width: totalWidth + 'px',
              height: 1,
              background: 'rgba(255,255,255,0.055)',
              pointerEvents: 'none',
            }}>
              <span style={{
                position: 'absolute',
                left: 3,
                top: 2,
                fontSize: 9,
                fontWeight: 600,
                color: 'rgba(100,116,139,0.9)',
                userSelect: 'none',
              }}>
                {m.label}
              </span>
            </div>
          ))}

          {/* Events */}
          {events.map(ev => {
            const l = ev.level as Level
            const c = COLORS[l]
            const sc = subColsMap[l].get(ev.id) ?? 0
            // cap sub-col index to max allowed
            const cappedSc = Math.min(sc, maxSubCols[l] - 1)
            const scw = subColW(l)
            const x = colX[l] + cappedSc * (scw + SUBCOL_GAP)
            const topY = toDay(ev.start_date) * SCALE
            const endDay = ev.end_date ? toDay(ev.end_date) : totalDays
            const h = Math.max((endDay - toDay(ev.start_date)) * SCALE, MIN_EV_H)
            const isActive = refDate >= ev.start_date && (!ev.end_date || refDate <= ev.end_date)
            const isOngoing = !ev.end_date
            const daysSinceStart = Math.max(0, Math.floor(
              (new Date(refDate).getTime() - new Date(ev.start_date).getTime()) / 86_400_000
            ))

            return (
              <div
                key={ev.id}
                onClick={() => onDateChange(ev.start_date)}
                title={`[${ev.level.toUpperCase()}] ${ev.name}\n${ev.start_date}${ev.end_date ? ' → ' + ev.end_date : ' → en cours'}`}
                style={{
                  position: 'absolute',
                  top: topY + 1,
                  left: x + 1,
                  width: scw - 2,
                  height: h - 2,
                  background: isActive ? c.border : c.bg,
                  border: `1px solid ${isActive ? c.border : c.border + '88'}`,
                  borderRadius: 3,
                  cursor: 'pointer',
                  overflow: 'hidden',
                  opacity: isActive ? 1 : 0.7,
                  zIndex: isActive ? 10 : 2,
                  backgroundImage: isOngoing && !isActive
                    ? `linear-gradient(180deg, ${c.bg} 80%, ${c.border}30 100%)`
                    : undefined,
                  transition: 'opacity 0.15s',
                }}
              >
                <div style={{
                  padding: '2px 4px',
                  fontSize: 9,
                  fontWeight: 600,
                  color: c.text,
                  lineHeight: 1.25,
                  whiteSpace: 'nowrap',
                  overflow: 'hidden',
                  textOverflow: 'ellipsis',
                }}>
                  {ev.name}
                </div>
                {h > 46 && isActive && (
                  <div style={{ padding: '0 4px', fontSize: 8, color: c.text + 'bb' }}>
                    J+{daysSinceStart}
                  </div>
                )}
                {isOngoing && (
                  <div style={{
                    position: 'absolute',
                    bottom: 1,
                    left: '50%',
                    transform: 'translateX(-50%)',
                    fontSize: 8,
                    color: c.border + 'cc',
                  }}>▼</div>
                )}
              </div>
            )
          })}

          {/* Today line */}
          <div style={{
            position: 'absolute',
            top: todayY,
            left: 0,
            width: totalWidth + 'px',
            height: 2,
            background: 'rgba(239,68,68,0.75)',
            zIndex: 20,
            pointerEvents: 'none',
          }}>
            <span style={{
              position: 'absolute',
              right: 4,
              top: 3,
              fontSize: 9,
              color: '#f87171',
              userSelect: 'none',
            }}>aujourd'hui</span>
          </div>

          {/* Selected date line */}
          {refDate !== today && (
            <div style={{
              position: 'absolute',
              top: refY,
              left: 0,
              width: totalWidth + 'px',
              height: 0,
              borderTop: '1.5px dashed rgba(255,255,255,0.38)',
              zIndex: 20,
              pointerEvents: 'none',
            }} />
          )}

        </div>
      </div>
    </div>
  )
}
