'use client'

import { useState } from 'react'

import { useI18n } from '@/components/providers/i18n-provider'
import { useDeclaredMode } from '@/components/providers/app-mode-provider'
import { Button, Field, Input, Notice, Select } from '@/components/ui/controls'
import { Badge, Meter, Panel, PanelBody, PanelHeader, StatCard } from '@/components/ui/display'
import { SimulationProgress } from '@/components/twin/simulation-progress'
import { api, ApiClientError } from '@/lib/api/client'
import { cn } from '@/lib/cn'

/**
 * The Resilience Lab (§40) and the adversarial twin (§38).
 *
 * Two experiments that ask opposite questions. The disturbance test says "here is a bad
 * thing; how well do we take it". The adversarial search says "find me the *least* bad
 * combination of ordinary things that still breaks us" — which is the harder question and
 * the one planning actually turns on.
 *
 * The page declares itself a simulation for as long as it is open, so nothing on it can
 * be mistaken for an operational reading.
 */

const DISTURBANCES = [
  'heat_wave',
  'demand_surge',
  'renewable_drop',
  'multi_failure',
  'maintenance_outage',
] as const

interface ResilienceScore {
  score: number
  band: string
  summary: string
  summaryAr: string
  components: Array<{ key: string; value: number; normalised: number; weight: number; unit: string }>
}

interface TestResult {
  code: string
  disturbance: string
  magnitude: number
  before: ResilienceScore
  during: ResilienceScore
  after: ResilienceScore
  recoveryMin: number
  verdict: string
  verdictAr: string
}

interface AdversarialResult {
  assetCode: string
  found: boolean
  metric: number
  target: number
  riskBefore: number
  plausibilityCost: number
  evaluations: number
  summary: string
  summaryAr: string
  doses: Array<{ key: string; label: string; labelAr: string; amount: number; unit: string }>
}

export function ResilienceLab({
  defaultAsset,
  className,
}: {
  defaultAsset: string
  className?: string
}) {
  const { t, locale, n } = useI18n()
  const ar = locale === 'ar'
  useDeclaredMode('simulation')

  const [disturbance, setDisturbance] = useState<(typeof DISTURBANCES)[number]>('heat_wave')
  const [magnitude, setMagnitude] = useState('')
  const [test, setTest] = useState<TestResult | null>(null)
  const [adversarial, setAdversarial] = useState<AdversarialResult | null>(null)
  const [assetCode, setAssetCode] = useState(defaultAsset)
  const [busy, setBusy] = useState<'test' | 'adversarial' | null>(null)
  const [error, setError] = useState<string | null>(null)

  const fail = (cause: unknown) =>
    setError(cause instanceof ApiClientError ? (ar ? cause.failure.messageAr : cause.failure.message) : String(cause))

  const runTest = async () => {
    setBusy('test')
    setError(null)
    try {
      const parsed = Number.parseFloat(magnitude)
      setTest(
        await api.post<TestResult>('/api/resilience', {
          disturbance,
          magnitude: Number.isFinite(parsed) ? parsed : undefined,
          persist: true,
        }),
      )
    } catch (cause) {
      fail(cause)
    } finally {
      setBusy(null)
    }
  }

  const runAdversarial = async () => {
    setBusy('adversarial')
    setError(null)
    try {
      setAdversarial(
        await api.post<AdversarialResult>('/api/adversarial', {
          assetCode: assetCode.trim().toUpperCase(),
          targetRisk: 90,
        }),
      )
    } catch (cause) {
      fail(cause)
    } finally {
      setBusy(null)
    }
  }

  return (
    <div className={cn('space-y-4', className)}>
      {error ? <Notice tone="danger">{error}</Notice> : null}

      <Panel>
        <PanelHeader
          title={t('resilience.lab')}
          subtitle={t('resilience.subtitle')}
          action={<Badge tone="accent">{t('mode.simulation.short')}</Badge>}
        />
        <PanelBody className="pt-0">
          <div className="flex flex-wrap items-end gap-3">
            <Field label={t('resilience.lab')} htmlFor="disturbance" className="w-56">
              <Select
                id="disturbance"
                value={disturbance}
                onChange={(event) => setDisturbance(event.target.value as (typeof DISTURBANCES)[number])}
              >
                {DISTURBANCES.map((entry) => (
                  <option key={entry} value={entry}>
                    {t(`resilience.disturbance.${entry}`)}
                  </option>
                ))}
              </Select>
            </Field>
            <Field label={t('scenarioCanvas.magnitude')} htmlFor="magnitude" className="w-32">
              <Input
                id="magnitude"
                type="number"
                value={magnitude}
                placeholder="auto"
                onChange={(event) => setMagnitude(event.target.value)}
              />
            </Field>
            <Button onClick={runTest} loading={busy === 'test'}>
              {t('resilience.run')}
            </Button>
          </div>
        </PanelBody>
      </Panel>

      <SimulationProgress running={busy !== null} />

      {test ? (
        <>
          <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
            <StatCard
              label={t('resilience.before')}
              value={n(test.before.score, { maximumFractionDigits: 0 })}
              hint={t(`resilience.band.${test.before.band}`)}
            />
            <StatCard
              label={t('resilience.during')}
              value={n(test.during.score, { maximumFractionDigits: 0 })}
              state={test.during.score < test.before.score - 15 ? 'critical' : 'warning'}
              hint={t(`resilience.band.${test.during.band}`)}
            />
            <StatCard
              label={t('resilience.after')}
              value={n(test.after.score, { maximumFractionDigits: 0 })}
              state={test.after.score >= test.before.score - 2 ? 'normal' : 'warning'}
              hint={t(`resilience.band.${test.after.band}`)}
            />
            <StatCard
              label={t('resilience.recovery')}
              value={n(test.recoveryMin)}
              unit={t('common.minutes')}
            />
          </div>

          <Panel>
            <PanelHeader
              title={t(`resilience.disturbance.${test.disturbance}`)}
              subtitle={ar ? test.verdictAr : test.verdict}
              action={<Badge tone="muted">{test.code}</Badge>}
            />
            <PanelBody className="space-y-2 pt-0">
              {test.during.components.map((component) => {
                const before = test.before.components.find((entry) => entry.key === component.key)
                return (
                  <div key={component.key}>
                    <div className="flex items-baseline justify-between gap-3 text-[11px]">
                      <span className="text-text-muted">{t(`resilience.factor.${component.key}`)}</span>
                      <span className="tnum">
                        <span className="text-text-faint">
                          {n(before?.normalised ?? 0, { maximumFractionDigits: 0 })}
                        </span>
                        <span className="mx-1 text-text-faint">→</span>
                        <span
                          className={cn(
                            'font-medium',
                            component.normalised < (before?.normalised ?? 0) - 5
                              ? 'text-critical'
                              : 'text-text',
                          )}
                        >
                          {n(component.normalised, { maximumFractionDigits: 0 })}
                        </span>
                      </span>
                    </div>
                    <Meter
                      className="mt-1"
                      value={component.normalised}
                      state={
                        component.normalised >= 70 ? 'normal' : component.normalised >= 45 ? 'watch' : 'critical'
                      }
                    />
                  </div>
                )
              })}
            </PanelBody>
          </Panel>
        </>
      ) : null}

      <Panel>
        <PanelHeader title={t('resilience.adversarial')} subtitle={t('resilience.adversarialHint')} />
        <PanelBody className="pt-0">
          <div className="flex flex-wrap items-end gap-3">
            <Field label={t('aiOps.focusAsset')} htmlFor="adversarial-asset" className="w-40">
              <Input
                id="adversarial-asset"
                value={assetCode}
                onChange={(event) => setAssetCode(event.target.value)}
                className="font-mono text-xs"
              />
            </Field>
            <Button variant="secondary" onClick={runAdversarial} loading={busy === 'adversarial'}>
              {t('resilience.adversarialRun')}
            </Button>
          </div>

          {adversarial ? (
            <div className="mt-4 space-y-3">
              <p
                className={cn(
                  'rounded-lg border px-3 py-2 text-[11px] leading-relaxed',
                  adversarial.found
                    ? 'border-critical/30 bg-critical/8 text-critical'
                    : 'border-normal/30 bg-normal/8 text-normal',
                )}
              >
                {ar ? adversarial.summaryAr : adversarial.summary}
              </p>

              {adversarial.doses.length > 0 ? (
                <ul className="space-y-1.5">
                  {adversarial.doses.map((dose) => (
                    <li
                      key={dose.key}
                      className="flex items-baseline justify-between gap-3 rounded-lg border border-border bg-surface-2/40 px-3 py-2 text-[11px]"
                    >
                      <span className="text-text">{ar ? dose.labelAr : dose.label}</span>
                      <span className="tnum font-medium text-watch">
                        +{n(dose.amount, { maximumFractionDigits: 1 })} {dose.unit}
                      </span>
                    </li>
                  ))}
                </ul>
              ) : null}

              <div className="flex flex-wrap gap-x-6 gap-y-1 border-t border-border/70 pt-2 text-[11px] text-text-muted">
                <span className="tnum">
                  {t('common.riskScore')} {n(adversarial.riskBefore, { maximumFractionDigits: 0 })}% →{' '}
                  <span className="font-medium text-critical">
                    {n(adversarial.metric, { maximumFractionDigits: 0 })}%
                  </span>
                </span>
                <span className="tnum">
                  {t('resilience.plausibility')} {n(adversarial.plausibilityCost, { maximumFractionDigits: 1 })}
                </span>
                <span className="tnum">
                  {t('counterfactual.evaluations')} {n(adversarial.evaluations)}
                </span>
              </div>
            </div>
          ) : null}
        </PanelBody>
      </Panel>
    </div>
  )
}
