'use client'

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

import { useI18n } from '@/components/providers/i18n-provider'
import { TimeSeriesChart } from '@/components/charts/time-series'
import { Button, Segmented } from '@/components/ui/controls'
import { Badge, Meter, Panel, PanelBody, PanelHeader, StateBadge } from '@/components/ui/display'
import { cn } from '@/lib/cn'
import { riskToState } from '@/lib/domain/enums'
import { CHART_COLORS, styleForRisk } from '@/lib/ui/state-styles'

export interface ReplayFrame {
  ts: number
  offsetMin: number
  phase: string
  label: string
  labelAr: string
  loadPct: number
  tempC: number
  voltageKv: number
  frequencyHz: number
  riskScore: number
  marker: string | null
  note: string
  noteAr: string
}

/**
 * Incident replay (§25).
 *
 * The scrubber steps through recorded frames and marks two moments: when a conventional
 * threshold alarm fired, and when NABDH's composite risk would have raised a warning.
 * The gap between them is the prevention window — the whole argument for the platform,
 * expressed as a measurable interval rather than a claim.
 */
export function IncidentReplay({
  frames,
  nabdhLeadTimeMin,
  thresholdLeadMin,
  wasPrevented,
}: {
  frames: ReplayFrame[]
  nabdhLeadTimeMin: number
  thresholdLeadMin: number
  wasPrevented: boolean
}) {
  const { t, locale, n, time, duration } = useI18n()

  const [index, setIndex] = useState(0)
  const [playing, setPlaying] = useState(false)
  const [speed, setSpeed] = useState('1')
  const timerRef = useRef<number | undefined>(undefined)

  const frame = frames[Math.min(index, frames.length - 1)]

  useEffect(() => {
    if (!playing) return
    const interval = 900 / Number(speed)
    timerRef.current = window.setInterval(() => {
      setIndex((current) => {
        if (current >= frames.length - 1) {
          setPlaying(false)
          return current
        }
        return current + 1
      })
    }, interval)
    return () => window.clearInterval(timerRef.current)
  }, [playing, speed, frames.length])

  const markers = useMemo(() => {
    const list: Array<{ x: number; label: string; color: string }> = []
    const nabdh = frames.find((entry) => entry.marker === 'nabdh_detect')
    const threshold = frames.find((entry) => entry.marker === 'threshold_trigger')
    const event = frames.find((entry) => entry.marker === 'failure' || entry.marker === 'prevented')
    if (nabdh) list.push({ x: nabdh.ts, label: t('incidents.replay.nabdhDetect'), color: CHART_COLORS.primary })
    if (threshold)
      list.push({ x: threshold.ts, label: t('incidents.replay.thresholdTrigger'), color: CHART_COLORS.quaternary })
    if (event)
      list.push({
        x: event.ts,
        label: wasPrevented ? t('incidents.replay.prevented') : t('incidents.replay.failure'),
        color: wasPrevented ? CHART_COLORS.primary : CHART_COLORS.danger,
      })
    return list
  }, [frames, t, wasPrevented])

  // Only the frames up to the playhead are drawn, so the chart fills in as it plays.
  const data = frames.slice(0, index + 1).map((entry) => ({
    ts: entry.ts,
    risk: entry.riskScore,
    loadPct: entry.loadPct,
    tempC: entry.tempC,
  }))

  const advantage = nabdhLeadTimeMin - thresholdLeadMin

  return (
    <Panel>
      <PanelHeader
        title={t('incidents.replay.title')}
        subtitle={t('incidents.replay.subtitle')}
        action={
          <div className="flex flex-wrap items-center gap-2">
            <Button
              size="sm"
              variant={playing ? 'secondary' : 'primary'}
              onClick={() => {
                if (index >= frames.length - 1) setIndex(0)
                setPlaying((current) => !current)
              }}
            >
              {playing ? t('incidents.replay.pause') : t('incidents.replay.play')}
            </Button>
            <Button
              size="sm"
              variant="ghost"
              onClick={() => {
                setPlaying(false)
                setIndex(0)
              }}
            >
              {t('incidents.replay.restart')}
            </Button>
            <Segmented
              ariaLabel={t('incidents.replay.speed')}
              size="sm"
              value={speed}
              onChange={setSpeed}
              options={[
                { value: '0.5', label: '0.5×' },
                { value: '1', label: '1×' },
                { value: '2', label: '2×' },
                { value: '4', label: '4×' },
              ]}
            />
          </div>
        }
      />

      <PanelBody className="space-y-5">
        {/* Prevention window */}
        <div className="grid gap-3 sm:grid-cols-3">
          <WindowCard
            label={t('incidents.replay.nabdhDetect')}
            value={duration(nabdhLeadTimeMin)}
            tone="brand"
            active={frame.offsetMin >= -nabdhLeadTimeMin}
          />
          <WindowCard
            label={t('incidents.replay.thresholdTrigger')}
            value={thresholdLeadMin > 0 ? duration(thresholdLeadMin) : t('common.none')}
            tone="watch"
            active={thresholdLeadMin > 0 && frame.offsetMin >= -thresholdLeadMin}
          />
          <WindowCard
            label={t('incidents.replay.preventionWindow')}
            value={advantage > 0 ? duration(advantage) : t('common.none')}
            tone="info"
            active={advantage > 0}
          />
        </div>

        {advantage > 0 ? (
          <p className="rounded-lg border border-brand/30 bg-brand/8 px-4 py-3 text-sm text-brand">
            {t('incidents.replay.leadAdvantage', { minutes: advantage })}
          </p>
        ) : (
          <p className="rounded-lg border border-border bg-surface-2/40 px-4 py-3 text-sm text-text-muted">
            {t('incidents.replay.noAdvantage')}
          </p>
        )}

        {/* Chart */}
        <TimeSeriesChart
          data={data}
          height={240}
          yDomain={[0, 120]}
          ariaLabel={t('incidents.replay.title')}
          markers={markers}
          valueFormatter={(value, key) =>
            key === 'tempC'
              ? `${n(value, { maximumFractionDigits: 0 })}${t('common.units.celsius')}`
              : `${n(value, { maximumFractionDigits: 0 })}%`
          }
          series={[
            { key: 'risk', label: t('common.riskScore'), color: CHART_COLORS.danger, type: 'area' },
            { key: 'loadPct', label: t('assets.columns.load'), color: CHART_COLORS.secondary, type: 'line' },
            {
              key: 'tempC',
              label: t('assets.columns.temperature'),
              color: CHART_COLORS.quaternary,
              type: 'line',
              strokeDasharray: '4 4',
            },
          ]}
        />

        {/* Scrubber */}
        <div>
          <label htmlFor="replay-scrubber" className="sr-only">
            {t('incidents.replay.title')}
          </label>
          <input
            id="replay-scrubber"
            type="range"
            min={0}
            max={frames.length - 1}
            value={index}
            onChange={(event) => {
              setPlaying(false)
              setIndex(Number(event.target.value))
            }}
            className="w-full accent-brand"
          />
          <div className="mt-1 flex justify-between text-[10px] text-text-faint">
            <span>{frames[0] ? time(frames[0].ts) : ''}</span>
            <span className="tnum font-medium text-text-muted">
              {frame.offsetMin >= 0 ? '+' : ''}
              {frame.offsetMin} {t('common.units.minutes')} · {time(frame.ts)}
            </span>
            <span>{frames[frames.length - 1] ? time(frames[frames.length - 1].ts) : ''}</span>
          </div>
        </div>

        {/* Current frame */}
        <div className="rounded-lg border border-border bg-surface-2/40 p-4">
          <div className="flex flex-wrap items-center justify-between gap-3">
            <div className="flex flex-wrap items-center gap-2">
              <StateBadge
                state={riskToState(frame.riskScore)}
                label={locale === 'ar' ? frame.labelAr : frame.label}
                pulse={frame.riskScore >= 75}
              />
              {frame.marker ? (
                <Badge tone={frame.marker === 'nabdh_detect' ? 'brand' : 'info'}>
                  {t(
                    frame.marker === 'nabdh_detect'
                      ? 'incidents.replay.nabdhDetect'
                      : frame.marker === 'threshold_trigger'
                        ? 'incidents.replay.thresholdTrigger'
                        : frame.marker === 'prevented'
                          ? 'incidents.replay.prevented'
                          : 'incidents.replay.failure',
                  )}
                </Badge>
              ) : null}
            </div>
            <span className={cn('tnum text-2xl font-semibold', styleForRisk(frame.riskScore).text)}>
              {n(frame.riskScore, { maximumFractionDigits: 0 })}%
            </span>
          </div>

          <Meter value={frame.riskScore} state={riskToState(frame.riskScore)} className="mt-3" />

          {frame.note ? (
            <p className="mt-3 text-xs leading-relaxed text-text-muted">
              {locale === 'ar' ? frame.noteAr : frame.note}
            </p>
          ) : null}

          <dl className="mt-4 grid grid-cols-2 gap-3 border-t border-border pt-3 sm:grid-cols-4">
            <Reading label={t('assets.columns.load')} value={`${n(frame.loadPct, { maximumFractionDigits: 0 })}%`} />
            <Reading
              label={t('assets.columns.temperature')}
              value={`${n(frame.tempC, { maximumFractionDigits: 0 })}${t('common.units.celsius')}`}
            />
            <Reading
              label={t('grid.electrical.voltage')}
              value={`${n(frame.voltageKv, { maximumFractionDigits: 1 })} ${t('common.units.kv')}`}
            />
            <Reading
              label={t('grid.electrical.frequency')}
              value={`${n(frame.frequencyHz, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} ${t('common.units.hz')}`}
            />
          </dl>
        </div>
      </PanelBody>
    </Panel>
  )
}

function WindowCard({
  label,
  value,
  tone,
  active,
}: {
  label: string
  value: string
  tone: 'brand' | 'watch' | 'info'
  active: boolean
}) {
  const tones = {
    brand: 'border-brand/35 bg-brand/8 text-brand',
    watch: 'border-watch/35 bg-watch/8 text-watch',
    info: 'border-info/35 bg-info/8 text-info',
  }
  return (
    <div
      className={cn(
        'rounded-lg border px-4 py-3 transition-opacity',
        tones[tone],
        active ? 'opacity-100' : 'opacity-45',
      )}
    >
      <p className="text-[10px] uppercase tracking-wide opacity-80">{label}</p>
      <p className="tnum mt-1 text-lg font-semibold">{value}</p>
    </div>
  )
}

function Reading({ label, value }: { label: string; value: string }) {
  return (
    <div>
      <dt className="text-[10px] uppercase tracking-wide text-text-faint">{label}</dt>
      <dd className="tnum mt-0.5 text-sm font-medium text-text">{value}</dd>
    </div>
  )
}
