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
}

// ── Layout constants ───────────────────────────────────────────────────────────
const SCALE       = 2.4   // px per day
const SUB_H       = 26    // height per sub-lane
const SUB_GAP     = 3     // gap between sub-lanes in same level
const LEVEL_GAP   = 14   // gap between levels
const AXIS_H      = 28
const PADDING_TOP = 12
const FRISE_START = '2020-02-01'
const TODAY       = new Date().toISOString().split('T')[0]

const LEVEL_ORDER = ['long', 'medium', 'short'] as const

const COLORS = {
  long:   { bg: '#5b21b6', border: '#7c3aed', text: '#ede9fe', track: 'rgba(109,40,217,0.12)', overlap: 'rgba(124,58,237,0.25)' },
  medium: { bg: '#1d4ed8', border: '#3b82f6', text: '#dbeafe', track: 'rgba(59,130,246,0.10)', overlap: 'rgba(59,130,246,0.22)' },
  short:  { bg: '#065f46', border: '#10b981', text: '#d1fae5', track: 'rgba(16,185,129,0.10)', overlap: 'rgba(16,185,129,0.22)' },
}

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

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

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

// Assign sub-lane index per event within a level (greedy interval scheduling)
function assignSubLanes(evs: MarketEvent[]): Map<number, number> {
  const sorted = [...evs].sort((a, b) => a.start_date.localeCompare(b.start_date))
  const laneEnds: 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 < laneEnds.length; i++) {
      if (ev.start_date >= laneEnds[i]) {
        result.set(ev.id, i)
        laneEnds[i] = end
        placed = true
        break
      }
    }
    if (!placed) {
      result.set(ev.id, laneEnds.length)
      laneEnds.push(end)
    }
  }
  return result
}

// Find overlapping pairs within a level (A in lane 0, B in lane 1+, B starts before A ends)
function findOverlaps(evs: MarketEvent[], subLanes: Map<number, number>): { a: MarketEvent; b: MarketEvent }[] {
  const pairs: { a: MarketEvent; b: MarketEvent }[] = []
  for (let i = 0; i < evs.length; i++) {
    for (let j = i + 1; j < evs.length; j++) {
      const a = evs[i], b = evs[j]
      const aEnd = a.end_date ?? TODAY
      const bEnd = b.end_date ?? TODAY
      const overlapStart = a.start_date > b.start_date ? a.start_date : b.start_date
      const overlapEnd = aEnd < bEnd ? aEnd : bEnd
      if (overlapStart < overlapEnd) {
        const lA = subLanes.get(a.id) ?? 0
        const lB = subLanes.get(b.id) ?? 0
        if (lA !== lB) pairs.push({ a, b })
      }
    }
  }
  return pairs
}

// ── Component ──────────────────────────────────────────────────────────────────

export default function TimelineFrise({ events, refDate, onDateChange }: Props) {
  const scrollRef = useRef<HTMLDivElement>(null)

  const totalDays = toDay(TODAY) + 90
  const totalWidth = totalDays * SCALE
  const todayX = toDay(TODAY) * SCALE
  const refX   = toDay(refDate) * SCALE
  const yearMarkers = buildYearMarkers(totalDays)

  // Per-level sub-lane assignments
  const byLevel = useMemo(() => {
    const g: Record<string, MarketEvent[]> = { long: [], medium: [], short: [] }
    for (const ev of events) { if (g[ev.level]) g[ev.level].push(ev) }
    return g
  }, [events])

  const subLanesMap = useMemo(() => {
    const m: Record<string, Map<number, number>> = {}
    for (const l of LEVEL_ORDER) m[l] = assignSubLanes(byLevel[l] ?? [])
    return m
  }, [byLevel])

  const maxSubLanes = useMemo(() => {
    const m: Record<string, number> = {}
    for (const l of LEVEL_ORDER) {
      const vals = [...(subLanesMap[l]?.values() ?? [])]
      m[l] = vals.length ? Math.max(...vals) + 1 : 1
    }
    return m
  }, [subLanesMap])

  // Compute Y offset for each level
  const levelY = useMemo(() => {
    const y: Record<string, number> = {}
    let cur = PADDING_TOP
    for (const l of LEVEL_ORDER) {
      y[l] = cur
      cur += maxSubLanes[l] * (SUB_H + SUB_GAP) + LEVEL_GAP
    }
    return y
  }, [maxSubLanes])

  const totalHeight = useMemo(() => {
    return PADDING_TOP +
      LEVEL_ORDER.reduce((acc, l) => acc + maxSubLanes[l] * (SUB_H + SUB_GAP) + LEVEL_GAP, 0) +
      AXIS_H
  }, [maxSubLanes])

  // Auto-scroll to selected date
  useEffect(() => {
    const el = scrollRef.current
    if (!el) return
    el.scrollLeft = Math.max(0, refX - el.clientWidth / 2)
  }, [refDate, refX])

  // Compute overlap zones for background shading
  const overlapZones = useMemo(() => {
    const zones: { x: number; w: number; level: string; laneTop: number; laneBot: number }[] = []
    for (const l of LEVEL_ORDER) {
      const evs = byLevel[l] ?? []
      const sl = subLanesMap[l]
      const pairs = findOverlaps(evs, sl)
      for (const { a, b } of pairs) {
        const overlapStart = a.start_date > b.start_date ? a.start_date : b.start_date
        const overlapEnd = (a.end_date ?? TODAY) < (b.end_date ?? TODAY)
          ? (a.end_date ?? TODAY) : (b.end_date ?? TODAY)
        if (overlapStart >= overlapEnd) continue
        const lA = sl.get(a.id) ?? 0
        const lB = sl.get(b.id) ?? 0
        const minLane = Math.min(lA, lB)
        const maxLane = Math.max(lA, lB)
        zones.push({
          x: toDay(overlapStart) * SCALE,
          w: toDay(overlapEnd) * SCALE - toDay(overlapStart) * SCALE,
          level: l,
          laneTop: levelY[l] + minLane * (SUB_H + SUB_GAP),
          laneBot: levelY[l] + (maxLane + 1) * (SUB_H + SUB_GAP) - SUB_GAP,
        })
      }
    }
    return zones
  }, [byLevel, subLanesMap, levelY])

  return (
    <div className="bg-dark-800 rounded-xl border border-slate-700/40 overflow-hidden">
      {/* Legend */}
      <div className="flex items-center gap-5 px-4 pt-3 pb-2 border-b border-slate-700/30">
        {LEVEL_ORDER.map(l => (
          <div key={l} className="flex items-center gap-1.5 text-xs">
            <div className="w-3 h-2 rounded-sm" style={{ background: COLORS[l].border }} />
            <span className="text-slate-400">
              {l === 'long' ? 'Long terme' : l === 'medium' ? 'Moyen terme' : 'Court terme'}
            </span>
          </div>
        ))}
        <div className="ml-auto flex items-center gap-4 text-xs text-slate-600">
          <span className="flex items-center gap-1">
            <div className="w-2 h-2 rounded-sm bg-white/20 border border-white/20" />
            Zone d'overlap
          </span>
          <span>— cliquer sur un événement pour naviguer</span>
        </div>
      </div>

      {/* Frise */}
      <div
        ref={scrollRef}
        className="overflow-x-auto overflow-y-hidden"
        style={{ height: totalHeight + 'px', cursor: 'grab' }}
      >
        <div className="relative select-none" style={{ width: totalWidth + 'px', height: totalHeight + 'px' }}>

          {/* Year grid lines */}
          {yearMarkers.map(m => (
            <div key={m.label}
              className="absolute top-0 bottom-0 pointer-events-none"
              style={{ left: m.day * SCALE, width: 1, background: 'rgba(255,255,255,0.05)', top: 0, height: '100%' }}
            />
          ))}

          {/* Level track backgrounds */}
          {LEVEL_ORDER.map(l => (
            <div key={l}
              className="absolute left-0 right-0"
              style={{
                top: levelY[l],
                height: maxSubLanes[l] * (SUB_H + SUB_GAP) - SUB_GAP,
                background: COLORS[l].track,
                borderRadius: 4,
              }}
            />
          ))}

          {/* Overlap zone shading */}
          {overlapZones.map((z, i) => (
            <div key={i}
              className="absolute pointer-events-none"
              style={{
                left: z.x,
                top: z.laneTop,
                width: z.w,
                height: z.laneBot - z.laneTop,
                background: COLORS[z.level as keyof typeof COLORS].overlap,
                borderRadius: 3,
                border: `1px solid ${COLORS[z.level as keyof typeof COLORS].border}33`,
              }}
            />
          ))}

          {/* Events */}
          {events.map(ev => {
            const level = ev.level as keyof typeof COLORS
            const c = COLORS[level]
            const sl = subLanesMap[level]?.get(ev.id) ?? 0
            const x = toDay(ev.start_date) * SCALE
            const endDay = ev.end_date ? toDay(ev.end_date) : totalDays
            const w = Math.max((endDay - toDay(ev.start_date)) * SCALE, 6)
            const y = levelY[level] + sl * (SUB_H + SUB_GAP)
            const isSelected = refDate >= ev.start_date && (!ev.end_date || refDate <= ev.end_date)
            const isOngoing = !ev.end_date

            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'}`}
                className="absolute overflow-hidden cursor-pointer transition-opacity"
                style={{
                  left: x,
                  top: y + 2,
                  width: w,
                  height: SUB_H - 4,
                  background: isSelected ? c.border : c.bg,
                  border: `1px solid ${c.border}`,
                  borderRadius: 4,
                  opacity: isSelected ? 1 : 0.82,
                  zIndex: isSelected ? 10 : 2,
                  // Pill shape: if event ends cleanly, right end is rounded normally
                  // If ongoing, indicate continuation visually
                  backgroundImage: isOngoing && !isSelected
                    ? `linear-gradient(90deg, ${c.bg} 85%, ${c.border}44 100%)`
                    : undefined,
                }}
              >
                {/* Event name text */}
                <span
                  className="absolute left-0 top-0 bottom-0 flex items-center px-1.5 font-medium whitespace-nowrap"
                  style={{ color: c.text, fontSize: 10 }}
                >
                  {ev.name}
                </span>
                {/* Ongoing arrow indicator */}
                {isOngoing && (
                  <span
                    className="absolute right-0 top-0 bottom-0 flex items-center pr-1"
                    style={{ color: c.border, fontSize: 10 }}
                  >
                    ▶
                  </span>
                )}
              </div>
            )
          })}

          {/* Today vertical line */}
          <div
            className="absolute pointer-events-none z-20"
            style={{ left: todayX, top: 0, width: 2, height: totalHeight - AXIS_H, background: 'rgba(239,68,68,0.75)' }}
          />

          {/* Selected date line */}
          {refDate !== TODAY && (
            <div
              className="absolute pointer-events-none z-20"
              style={{
                left: refX,
                top: 0,
                width: 1,
                height: totalHeight - AXIS_H,
                borderLeft: '1.5px dashed rgba(255,255,255,0.45)',
              }}
            />
          )}

          {/* Year axis */}
          {yearMarkers.map(m => (
            <div
              key={m.label + 'lbl'}
              className="absolute text-xs text-slate-600 select-none"
              style={{ left: m.day * SCALE + 4, top: totalHeight - AXIS_H + 6 }}
            >
              {m.label}
            </div>
          ))}

          {/* Today label */}
          <div
            className="absolute text-xs text-red-400 font-medium select-none pointer-events-none z-20"
            style={{ left: todayX + 4, top: totalHeight - AXIS_H + 6 }}
          >
            ▲ aujourd'hui
          </div>
        </div>
      </div>
    </div>
  )
}
