'use client'

import { useState } from 'react'

import { useI18n } from '@/components/providers/i18n-provider'
import { RiskDelta } from '@/components/charts/risk-gauge'
import { Button, Field, Input, Notice, Select, Switch } from '@/components/ui/controls'
import {
  Badge,
  KeyValue,
  Meter,
  Panel,
  PanelBody,
  PanelHeader,
  StateBadge,
} from '@/components/ui/display'
import { ApiClientError, api, failureMessage } from '@/lib/api/client'
import { cn } from '@/lib/cn'
import { riskToState } from '@/lib/domain/enums'
import { styleForRisk } from '@/lib/ui/state-styles'

export interface ScenarioView {
  id: string
  key: string
  name: string
  nameAr: string
  description: string
  descriptionAr: string
  category: string
  loadDeltaPct: number
  solarDeltaPct: number
  windDeltaPct: number
  tempDeltaC: number
  assetOutage: boolean
  lineOutage: boolean
  batteryOutage: boolean
  evSurgeMw: number
  industrialMw: number
  durationMin: number
  targetRegion: string | null
  targetAssetCode: string | null
}

interface ScenarioOutcome {
  code: string
  riskBefore: number
  riskAfter: number
  stabilityBefore: number
  stabilityAfter: number
  voltageBefore: number
  voltageAfter: number
  frequencyBefore: number
  frequencyAfter: number
  loadBeforeMw: number
  loadAfterMw: number
  assetStressBefore: number
  assetStressAfter: number
  failureProbBefore: number
  failureProbAfter: number
  regionsAffected: number
  customersImpacted: number
  economicImpactSar: number
  recoveryTimeMin: number
  energyNotServedMwh: number
  verdict: string
  verdictAr: string
  impacts: Array<{
    code: string
    label: string
    labelAr: string
    baselineValue: number
    scenarioValue: number
    unit: string
    severity: string
  }>
}

/**
 * What-if scenarios (§6).
 *
 * Built-in scenarios are one click; the custom builder exposes the same parameters the
 * engine accepts, so an operator can ask a question the product author did not think of.
 * Results are persisted, which is what separates a simulation from a guess.
 */
export function ScenarioRunner({
  scenarios,
  regions,
  canRun,
  canCreate,
}: {
  scenarios: ScenarioView[]
  regions: Array<{ code: string; name: string; nameAr: string }>
  canRun: boolean
  canCreate: boolean
}) {
  const { t, locale, n, mw, duration } = useI18n()

  const [selected, setSelected] = useState<string | null>(scenarios[0]?.key ?? null)
  const [regionScope, setRegionScope] = useState('')
  const [outcome, setOutcome] = useState<ScenarioOutcome | null>(null)
  const [running, setRunning] = useState(false)
  const [error, setError] = useState<string | null>(null)

  const [custom, setCustom] = useState({
    loadDeltaPct: 25,
    solarDeltaPct: 0,
    windDeltaPct: 0,
    tempDeltaC: 3,
    lineOutage: false,
    batteryOutage: false,
    evSurgeMw: 0,
    industrialMw: 0,
    durationMin: 120,
  })
  const [useCustom, setUseCustom] = useState(false)

  const run = async () => {
    if (running || !canRun) return
    setRunning(true)
    setError(null)
    setOutcome(null)
    try {
      const body = useCustom
        ? {
            kind: 'scenario' as const,
            name: t('scenarios.custom'),
            params: { ...custom, regionCode: regionScope || null },
          }
        : {
            kind: 'scenario' as const,
            scenarioKey: selected ?? undefined,
            params: regionScope ? { regionCode: regionScope } : undefined,
          }
      setOutcome(await api.post<ScenarioOutcome>('/api/simulations', body))
    } catch (caught) {
      setError(
        caught instanceof ApiClientError
          ? failureMessage(caught.failure, locale)
          : t('simulations.failed'),
      )
    } finally {
      setRunning(false)
    }
  }

  const active = scenarios.find((scenario) => scenario.key === selected)

  return (
    <div className="space-y-6">
      <div className="grid gap-6 xl:grid-cols-[1fr_360px]">
        <Panel>
          <PanelHeader
            title={t('scenarios.builtIn')}
            action={
              <Switch
                checked={useCustom}
                onChange={setUseCustom}
                label={t('scenarios.custom')}
              />
            }
          />
          <PanelBody>
            {useCustom ? (
              <div className="grid gap-4 sm:grid-cols-2">
                <Field label={t('scenarios.loadDelta')} htmlFor="loadDelta" hint="%">
                  <Input
                    id="loadDelta"
                    type="number"
                    min={-100}
                    max={200}
                    value={custom.loadDeltaPct}
                    onChange={(e) => setCustom({ ...custom, loadDeltaPct: Number(e.target.value) })}
                  />
                </Field>
                <Field label={t('scenarios.tempDelta')} htmlFor="tempDelta" hint={t('common.units.celsius')}>
                  <Input
                    id="tempDelta"
                    type="number"
                    min={-25}
                    max={25}
                    step={0.5}
                    value={custom.tempDeltaC}
                    onChange={(e) => setCustom({ ...custom, tempDeltaC: Number(e.target.value) })}
                  />
                </Field>
                <Field label={t('scenarios.solarDelta')} htmlFor="solarDelta" hint="%">
                  <Input
                    id="solarDelta"
                    type="number"
                    min={-100}
                    max={200}
                    value={custom.solarDeltaPct}
                    onChange={(e) => setCustom({ ...custom, solarDeltaPct: Number(e.target.value) })}
                  />
                </Field>
                <Field label={t('scenarios.windDelta')} htmlFor="windDelta" hint="%">
                  <Input
                    id="windDelta"
                    type="number"
                    min={-100}
                    max={200}
                    value={custom.windDeltaPct}
                    onChange={(e) => setCustom({ ...custom, windDeltaPct: Number(e.target.value) })}
                  />
                </Field>
                <Field label={t('scenarios.evSurge')} htmlFor="evSurge" hint={t('common.units.mw')}>
                  <Input
                    id="evSurge"
                    type="number"
                    min={0}
                    max={5000}
                    value={custom.evSurgeMw}
                    onChange={(e) => setCustom({ ...custom, evSurgeMw: Number(e.target.value) })}
                  />
                </Field>
                <Field
                  label={t('scenarios.industrialSurge')}
                  htmlFor="industrial"
                  hint={t('common.units.mw')}
                >
                  <Input
                    id="industrial"
                    type="number"
                    min={0}
                    max={5000}
                    value={custom.industrialMw}
                    onChange={(e) => setCustom({ ...custom, industrialMw: Number(e.target.value) })}
                  />
                </Field>
                <Field label={t('scenarios.duration')} htmlFor="duration" hint={t('common.units.minutes')}>
                  <Input
                    id="duration"
                    type="number"
                    min={5}
                    max={1440}
                    value={custom.durationMin}
                    onChange={(e) => setCustom({ ...custom, durationMin: Number(e.target.value) })}
                  />
                </Field>
                <div className="flex flex-col justify-end gap-3 pb-1">
                  <Switch
                    checked={custom.lineOutage}
                    onChange={(value) => setCustom({ ...custom, lineOutage: value })}
                    label={t('scenarios.lineOutage')}
                  />
                  <Switch
                    checked={custom.batteryOutage}
                    onChange={(value) => setCustom({ ...custom, batteryOutage: value })}
                    label={t('scenarios.batteryOutage')}
                  />
                </div>
              </div>
            ) : (
              <ul className="grid gap-2 sm:grid-cols-2">
                {scenarios.map((scenario) => {
                  const isActive = scenario.key === selected
                  return (
                    <li key={scenario.key}>
                      <button
                        type="button"
                        onClick={() => {
                          setSelected(scenario.key)
                          setOutcome(null)
                        }}
                        className={cn(
                          'h-full w-full rounded-lg border p-3.5 text-start transition-colors',
                          isActive
                            ? 'border-brand/50 bg-brand/8'
                            : 'border-border bg-surface-2/40 hover:border-border-strong',
                        )}
                      >
                        <div className="flex items-center justify-between gap-2">
                          <span
                            className={cn(
                              'text-sm font-medium',
                              isActive ? 'text-brand' : 'text-text',
                            )}
                          >
                            {locale === 'ar' ? scenario.nameAr : scenario.name}
                          </span>
                          <Badge tone="muted">{scenario.category}</Badge>
                        </div>
                        <p className="mt-1.5 line-clamp-2 text-xs leading-relaxed text-text-muted">
                          {locale === 'ar' ? scenario.descriptionAr : scenario.description}
                        </p>
                      </button>
                    </li>
                  )
                })}
              </ul>
            )}
          </PanelBody>
        </Panel>

        <Panel>
          <PanelHeader title={t('scenarios.parameters')} />
          <PanelBody className="space-y-4">
            <Field label={t('scenarios.scope')} htmlFor="scope">
              <Select
                id="scope"
                value={regionScope}
                onChange={(event) => setRegionScope(event.target.value)}
              >
                <option value="">{t('scenarios.national')}</option>
                {regions.map((region) => (
                  <option key={region.code} value={region.code}>
                    {locale === 'ar' ? region.nameAr : region.name}
                  </option>
                ))}
              </Select>
            </Field>

            {!useCustom && active ? (
              <dl className="divide-y divide-border/60 border-y border-border/60">
                {active.loadDeltaPct !== 0 ? (
                  <KeyValue label={t('scenarios.loadDelta')} value={`${active.loadDeltaPct}%`} mono />
                ) : null}
                {active.tempDeltaC !== 0 ? (
                  <KeyValue
                    label={t('scenarios.tempDelta')}
                    value={`${active.tempDeltaC}${t('common.units.celsius')}`}
                    mono
                  />
                ) : null}
                {active.solarDeltaPct !== 0 ? (
                  <KeyValue label={t('scenarios.solarDelta')} value={`${active.solarDeltaPct}%`} mono />
                ) : null}
                {active.windDeltaPct !== 0 ? (
                  <KeyValue label={t('scenarios.windDelta')} value={`${active.windDeltaPct}%`} mono />
                ) : null}
                {active.evSurgeMw > 0 ? (
                  <KeyValue
                    label={t('scenarios.evSurge')}
                    value={`${mw(active.evSurgeMw)} ${t('common.units.mw')}`}
                    mono
                  />
                ) : null}
                {active.industrialMw > 0 ? (
                  <KeyValue
                    label={t('scenarios.industrialSurge')}
                    value={`${mw(active.industrialMw)} ${t('common.units.mw')}`}
                    mono
                  />
                ) : null}
                {active.lineOutage ? (
                  <KeyValue label={t('scenarios.lineOutage')} value={t('common.yes')} />
                ) : null}
                {active.batteryOutage ? (
                  <KeyValue label={t('scenarios.batteryOutage')} value={t('common.yes')} />
                ) : null}
                {active.assetOutage ? (
                  <KeyValue
                    label={t('scenarios.assetOutage')}
                    value={active.targetAssetCode ?? t('common.yes')}
                  />
                ) : null}
                <KeyValue label={t('scenarios.duration')} value={duration(active.durationMin)} />
              </dl>
            ) : null}

            {error ? <Notice tone="danger">{error}</Notice> : null}

            {canRun ? (
              <Button className="w-full" onClick={run} loading={running}>
                {running ? t('scenarios.running') : t('scenarios.run')}
              </Button>
            ) : (
              <Notice tone="info">{t('common.permissionDeniedBody')}</Notice>
            )}

            {!canCreate ? null : (
              <p className="text-[11px] leading-relaxed text-text-faint">
                {t('scenarios.customNote')}
              </p>
            )}
          </PanelBody>
        </Panel>
      </div>

      {outcome ? (
        <Panel className="nabdh-enter">
          <PanelHeader
            title={t('simulations.results.title')}
            subtitle={outcome.code}
            action={
              <StateBadge
                state={riskToState(outcome.riskAfter)}
                label={t(`states.${riskToState(outcome.riskAfter)}`)}
              />
            }
          />
          <PanelBody className="space-y-5">
            <RiskDelta
              before={outcome.riskBefore}
              after={outcome.riskAfter}
              beforeLabel={t('common.baseline')}
              afterLabel={t('common.scenario')}
              note={locale === 'ar' ? outcome.verdictAr : outcome.verdict}
            />

            <dl className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
              <Result
                label={t('simulations.results.gridStability')}
                before={n(outcome.stabilityBefore, { maximumFractionDigits: 1 })}
                after={n(outcome.stabilityAfter, { maximumFractionDigits: 1 })}
              />
              <Result
                label={t('simulations.results.load')}
                before={mw(outcome.loadBeforeMw)}
                after={mw(outcome.loadAfterMw)}
                unit={t('common.units.mw')}
              />
              <Result
                label={t('simulations.results.frequency')}
                before={n(outcome.frequencyBefore, { minimumFractionDigits: 3, maximumFractionDigits: 3 })}
                after={n(outcome.frequencyAfter, { minimumFractionDigits: 3, maximumFractionDigits: 3 })}
                unit={t('common.units.hz')}
              />
              <Result
                label={t('simulations.results.assetStress')}
                before={n(outcome.assetStressBefore, { maximumFractionDigits: 1 })}
                after={n(outcome.assetStressAfter, { maximumFractionDigits: 1 })}
                unit="%"
              />
            </dl>

            <dl className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
              <Single
                label={t('simulations.results.regionsAffected')}
                value={n(outcome.regionsAffected)}
              />
              <Single
                label={t('simulations.results.customersImpacted')}
                value={n(outcome.customersImpacted)}
                tone={outcome.customersImpacted > 0 ? 'critical' : undefined}
              />
              <Single
                label={t('simulations.results.energyNotServed')}
                value={`${n(outcome.energyNotServedMwh, { maximumFractionDigits: 1 })} ${t('common.units.mwh')}`}
              />
              <Single
                label={t('simulations.results.recoveryTime')}
                value={duration(outcome.recoveryTimeMin)}
              />
            </dl>

            <Notice tone="warning">
              {t('simulations.results.economicImpact')}:{' '}
              {n(outcome.economicImpactSar, { maximumFractionDigits: 0 })} {t('common.units.sar')} ·{' '}
              {t('common.demoEstimate')}
            </Notice>

            {outcome.impacts.length > 0 ? (
              <div>
                <p className="mb-2 text-[10px] font-semibold uppercase tracking-wide text-text-faint">
                  {t('grid.regionTable')}
                </p>
                <ul className="space-y-1.5">
                  {outcome.impacts.map((impact) => (
                    <li
                      key={impact.code}
                      className="flex items-center gap-3 rounded-lg border border-border bg-surface-2/40 px-3 py-2"
                    >
                      <span className="w-32 shrink-0 truncate text-xs text-text">
                        {locale === 'ar' ? impact.labelAr : impact.label}
                      </span>
                      <Meter
                        value={impact.scenarioValue}
                        state={riskToState(impact.scenarioValue)}
                        className="flex-1"
                      />
                      <span className="tnum w-24 shrink-0 text-end text-[11px]">
                        <span className="text-text-faint">
                          {n(impact.baselineValue, { maximumFractionDigits: 0 })}%
                        </span>
                        <span className="mx-1 text-text-faint">→</span>
                        <span className={styleForRisk(impact.scenarioValue).text}>
                          {n(impact.scenarioValue, { maximumFractionDigits: 0 })}%
                        </span>
                      </span>
                    </li>
                  ))}
                </ul>
              </div>
            ) : null}
          </PanelBody>
        </Panel>
      ) : null}
    </div>
  )
}

function Result({
  label,
  before,
  after,
  unit,
}: {
  label: string
  before: string
  after: string
  unit?: string
}) {
  return (
    <div className="rounded-lg border border-border bg-surface-2/40 px-3.5 py-3">
      <dt className="text-[10px] uppercase tracking-wide text-text-faint">{label}</dt>
      <dd className="tnum mt-1.5 text-sm">
        <span className="text-text-muted">{before}</span>
        <span className="mx-1.5 text-text-faint">→</span>
        <span className="font-semibold text-text">{after}</span>
        {unit ? <span className="ms-1 text-[10px] text-text-faint">{unit}</span> : null}
      </dd>
    </div>
  )
}

function Single({
  label,
  value,
  tone,
}: {
  label: string
  value: string
  tone?: 'critical'
}) {
  return (
    <div className="rounded-lg border border-border bg-surface-2/40 px-3.5 py-3">
      <dt className="text-[10px] uppercase tracking-wide text-text-faint">{label}</dt>
      <dd
        className={cn(
          'tnum mt-1.5 text-lg font-semibold',
          tone === 'critical' ? 'text-critical' : 'text-text',
        )}
      >
        {value}
      </dd>
    </div>
  )
}
