'use client'

import { useState } from 'react'

import { Button, Notice, Select } from '@/components/ui/controls'
import { Badge, EmptyState, Panel, PanelBody, PanelHeader } from '@/components/ui/display'
import { useI18n } from '@/components/providers/i18n-provider'
import { api } from '@/lib/api/client'
import { formatDateTime, formatNumber } from '@/lib/i18n/translate'
import { cn } from '@/lib/cn'

/**
 * The Scenario Discovery Lab (§19, §21, §22).
 *
 * Five buttons, each a different question the search can be pointed at, and a result list
 * that leads with *plausibility* rather than severity. A finding built from a
 * once-in-a-century coincidence is not a finding, and ranking by severity alone would put
 * exactly those at the top.
 *
 * The budget line under the results is not decoration: a search that stopped early has to
 * say so, or a partial sweep reads as an exhaustive one.
 */

export interface DiscoveryView {
  code: string
  runCode: string
  objective: string
  narrative: string
  narrativeAr: string
  originAsset: string
  regionCode: string
  riskBefore: number
  riskAfter: number
  cascadeProbability: number
  cascadeDepth: number
  assetsAffected: number
  noveltyScore: number
  riskScore: number
  probability: number
  severity: number
  reproducibility: number
  confidence: number
  status: string
  createdAt: number
  conditions: Array<{
    leverKey: string
    label: string
    labelAr: string
    magnitude: number
    unit: string
    plausibility: number
  }>
}

export interface DiscoveryRunView {
  code: string
  objective: string
  scopeKind: string
  scopeCode: string
  simulationsRun: number
  maxSimulations: number
  durationMs: number
  discovered: number
  summary: string
  summaryAr: string
  status: string
  createdAt: number
}

const OBJECTIVES = [
  { key: 'hidden_risk', label: 'discovery.discoverHidden' },
  { key: 'cascade_trigger', label: 'discovery.findTriggers' },
  { key: 'breaking_point', label: 'discovery.findBreaking' },
  { key: 'worst_combination', label: 'discovery.findWorst' },
  { key: 'minimum_failure', label: 'discovery.findMinimum' },
] as const

function scoreTone(value: number): string {
  if (value >= 75) return 'text-critical'
  if (value >= 55) return 'text-warning'
  if (value >= 35) return 'text-watch'
  return 'text-text-muted'
}

export function DiscoveryLab({
  initialDiscoveries,
  initialRuns,
  regions,
  canRun,
}: {
  initialDiscoveries: DiscoveryView[]
  initialRuns: DiscoveryRunView[]
  regions: Array<{ code: string; name: string; nameAr: string }>
  canRun: boolean
}) {
  const { t, locale } = useI18n()
  const [discoveries, setDiscoveries] = useState(initialDiscoveries)
  const [runs, setRuns] = useState(initialRuns)
  const [scope, setScope] = useState('')
  const [busy, setBusy] = useState<string | null>(null)
  const [lastRun, setLastRun] = useState<{
    simulationsRun: number
    budgetExhausted: boolean
    skippedImplausible: number
    durationMs: number
  } | null>(null)
  const [error, setError] = useState<string | null>(null)

  const num = (value: number, digits = 0) =>
    formatNumber(locale, value, { maximumFractionDigits: digits })

  const run = async (objective: string) => {
    setBusy(objective)
    setError(null)
    try {
      const result = await api.post<{
        discoveries: unknown[]
        simulationsRun: number
        budgetExhausted: boolean
        skippedImplausible: number
        durationMs: number
      }>('/api/discovery/run', {
        objective,
        regionCode: scope || null,
        maxSimulations: 60,
        persist: true,
      })

      setLastRun({
        simulationsRun: result.simulationsRun,
        budgetExhausted: result.budgetExhausted,
        skippedImplausible: result.skippedImplausible,
        durationMs: result.durationMs,
      })

      const refreshed = await api.get<{ discoveries: DiscoveryView[]; runs: DiscoveryRunView[] }>(
        '/api/discovery?limit=12',
      )
      setDiscoveries(refreshed.discoveries)
      setRuns(refreshed.runs)
    } catch (caught) {
      setError(caught instanceof Error ? caught.message : t('common.error'))
    } finally {
      setBusy(null)
    }
  }

  return (
    <div className="space-y-4">
      <Notice tone="info">{t('discovery.sandbox')}</Notice>

      {canRun ? (
        <Panel>
          <PanelHeader title={t('discovery.title')} subtitle={t('discovery.subtitle')} />
          <PanelBody className="space-y-3">
            <label className="block max-w-xs">
              <span className="mb-1 block text-[11px] text-text-muted">{t('discovery.scope')}</span>
              <Select value={scope} onChange={(event) => setScope(event.target.value)}>
                <option value="">{t('discovery.national')}</option>
                {regions.map((region) => (
                  <option key={region.code} value={region.code}>
                    {locale === 'ar' ? region.nameAr : region.name}
                  </option>
                ))}
              </Select>
            </label>

            <div className="flex flex-wrap gap-2">
              {OBJECTIVES.map((objective) => (
                <Button
                  key={objective.key}
                  variant={objective.key === 'hidden_risk' ? 'primary' : 'secondary'}
                  onClick={() => run(objective.key)}
                  disabled={busy !== null}
                >
                  {busy === objective.key ? t('common.running') : t(objective.label)}
                </Button>
              ))}
            </div>

            {lastRun ? (
              <p className="text-[11px] leading-relaxed text-text-muted">
                {lastRun.simulationsRun} {t('discovery.simulations')} ·{' '}
                {num(lastRun.durationMs)} ms · {lastRun.skippedImplausible}{' '}
                {t('discovery.skipped')}
                {'. '}
                <span className={lastRun.budgetExhausted ? 'text-warning' : 'text-normal'}>
                  {lastRun.budgetExhausted ? t('discovery.exhausted') : t('discovery.complete')}
                </span>
              </p>
            ) : null}

            {error ? <p className="text-[11px] text-critical">{error}</p> : null}
          </PanelBody>
        </Panel>
      ) : null}

      {/* ── Findings ─────────────────────────────────────────────────────────── */}
      {discoveries.length === 0 ? (
        <EmptyState title={t('uiState.empty')} body={t('discovery.empty')} />
      ) : (
        <div className="grid gap-3 xl:grid-cols-2">
          {discoveries.map((discovery) => (
            <div key={discovery.code} className="min-w-0">
              <Panel>
                <PanelHeader
                  title={
                    <span className="font-mono text-[12px]">
                      {discovery.originAsset} · {discovery.regionCode}
                    </span>
                  }
                  action={
                    <div className="flex flex-wrap items-center gap-1.5">
                      {discovery.status === 'new' ? (
                        <Badge tone="brand" dot>
                          {t('discovery.newFinding')}
                        </Badge>
                      ) : null}
                      <Badge tone="muted">{t(`discovery.${objectiveKey(discovery.objective)}`)}</Badge>
                    </div>
                  }
                />
                <PanelBody className="space-y-3">
                  <p className="text-[12px] leading-relaxed">
                    {locale === 'ar' ? discovery.narrativeAr : discovery.narrative}
                  </p>

                  {/* Conditions, each with how ordinary it is. */}
                  <ul className="flex flex-wrap gap-1.5">
                    {discovery.conditions.map((condition) => (
                      <li
                        key={condition.leverKey}
                        className="rounded-full border border-border bg-surface-2 px-2 py-0.5 text-[10px]"
                        title={`${t('discovery.plausibility')}: ${num(condition.plausibility)}%`}
                      >
                        {locale === 'ar' ? condition.labelAr : condition.label}{' '}
                        <span className="font-mono tabular-nums">
                          {condition.magnitude > 0 ? '+' : ''}
                          {num(condition.magnitude, 1)}
                          {condition.unit === '%' ? '٪' : condition.unit ? ` ${condition.unit}` : ''}
                        </span>
                      </li>
                    ))}
                  </ul>

                  <div className="grid grid-cols-2 gap-2 sm:grid-cols-4">
                    {(
                      [
                        ['discovery.riskScore', discovery.riskScore],
                        ['discovery.plausibility', discovery.probability],
                        ['discovery.novelty', discovery.noveltyScore],
                        ['discovery.reproducibility', discovery.reproducibility],
                      ] as const
                    ).map(([key, value]) => (
                      <div key={key} className="min-w-0">
                        <p className="truncate text-[10px] text-text-faint">{t(key)}</p>
                        <p
                          className={cn(
                            'font-mono text-sm font-semibold tabular-nums',
                            key === 'discovery.riskScore' ? scoreTone(value) : 'text-text',
                          )}
                        >
                          {num(value)}
                        </p>
                      </div>
                    ))}
                  </div>

                  <p className="text-[10px] text-text-faint">
                    {formatDateTime(locale, discovery.createdAt)} ·{' '}
                    {t('common.simulated')}
                  </p>
                </PanelBody>
              </Panel>
            </div>
          ))}
        </div>
      )}

      {/* ── Runs ─────────────────────────────────────────────────────────────── */}
      {runs.length ? (
        <Panel>
          <PanelHeader title={t('discovery.runs')} />
          <PanelBody>
            <ul className="space-y-1.5">
              {runs.map((entry) => (
                <li
                  key={entry.code}
                  className="flex min-w-0 flex-wrap items-baseline gap-2 rounded-lg border border-border px-3 py-2 text-[11px]"
                >
                  <span className="font-mono text-text-muted">{entry.code}</span>
                  <span className="min-w-0 flex-1 truncate text-text-muted">
                    {locale === 'ar' ? entry.summaryAr : entry.summary}
                  </span>
                  <span className="shrink-0 font-mono tabular-nums text-text-faint">
                    {entry.simulationsRun}/{entry.maxSimulations} · {num(entry.durationMs)} ms
                  </span>
                </li>
              ))}
            </ul>
          </PanelBody>
        </Panel>
      ) : null}
    </div>
  )
}

/** Map the stored objective onto its label key. */
function objectiveKey(objective: string): string {
  switch (objective) {
    case 'cascade_trigger':
      return 'findTriggers'
    case 'breaking_point':
      return 'findBreaking'
    case 'worst_combination':
      return 'findWorst'
    case 'minimum_failure':
      return 'findMinimum'
    default:
      return 'discoverHidden'
  }
}
