import type { Metadata } from 'next'

import { PermissionGate } from '@/components/console/permission-gate'
import { TwinWorkbench, type TwinStatePayload } from '@/components/twin/twin-workbench'
import { AskTheFuture, WhatBreaksFirst } from '@/components/intelligence/wow-actions'
import { TrustDialog } from '@/components/intelligence/trust-dialog'
import { DemoDataBadge, ErrorState, PageHeader } from '@/components/ui/display'
import { getCurrentUser } from '@/lib/auth/current-user'
import { REGIONS } from '@/lib/data/regions'
import { getI18n } from '@/lib/i18n/server'
import {
  getDeviations,
  getTwinState,
  listScenarios,
  listSnapshots,
  listTwinSimulations,
  listTwins,
} from '@/lib/services/twin-service'

export const metadata: Metadata = { title: 'Digital Twin' }
export const dynamic = 'force-dynamic'

/**
 * The digital twin (§13–§37).
 *
 * The server renders the first state so the scene is on screen before any JavaScript
 * runs — a twin that spends two seconds on a spinner has already lost the argument that
 * it is a live view of something. Everything interactive after that is client-side
 * against the twin's own API.
 */
export default async function DigitalTwinPage({
  searchParams,
}: {
  searchParams: Promise<{ twin?: string; asset?: string }>
}) {
  const user = await getCurrentUser()
  const { t, locale } = await getI18n()
  if (!user?.permissions.has('twin.read')) return <PermissionGate />

  const { twin: requested, asset } = await searchParams
  const twins = await listTwins()

  // Open on the twin that was asked for; failing that, on the one that covers the asset
  // in question; failing that, on the national view.
  const target =
    twins.find((entry) => entry.code === requested) ??
    (asset ? twins.find((entry) => entry.assetCode === asset) : undefined) ??
    twins.find((entry) => entry.level === 'national') ??
    twins[0]

  if (!target) {
    return (
      <>
        <PageHeader title={t('twin.title')} subtitle={t('twin.subtitle')} />
        <ErrorState title={t('uiState.empty')} body={t('twin.subtitle')} />
      </>
    )
  }

  const [state, deviations, scenarios, simulations, snapshots] = await Promise.all([
    getTwinState(target.code),
    getDeviations(target.code, { limit: 8 }),
    listScenarios(),
    listTwinSimulations(target.code, 8),
    listSnapshots(target.code, 8),
  ])

  if (!state) {
    return (
      <>
        <PageHeader title={t('twin.title')} subtitle={t('twin.subtitle')} />
        <ErrorState title={t('uiState.error')} body={target.code} />
      </>
    )
  }

  const payload: TwinStatePayload = {
    twin: state.twin,
    ts: state.ts,
    source: state.source,
    snapshot: state.snapshot,
    fidelity: state.fidelity,
    assets: state.assets,
    scene: {
      nodes: state.scene.nodes,
      edges: state.scene.edges,
      radius: state.scene.radius,
      level: state.scene.level,
      focusCode: state.scene.focusCode,
    },
  }

  return (
    <>
      <PageHeader
        title={t('twin.title')}
        subtitle={t('twin.subtitle')}
        badge={<DemoDataBadge label={t('common.simulated')} title={t('common.simulatedTooltip')} />}
      />

      {/* Mobile is a reduced experience by design (§70): the scene and the readings work
          on a phone, the composition tools want a desktop, and saying so is better than
          shipping a cramped canvas nobody can use. */}
      <p className="mb-4 rounded-lg border border-border bg-surface-2/50 px-3 py-2 text-[11px] leading-relaxed text-text-muted xl:hidden">
        {t('twin.mobileNote')}
      </p>

      <TwinWorkbench
        twins={twins}
        initial={payload}
        deviations={deviations}
        presets={scenarios.map((scenario) => ({
          code: scenario.code,
          name: scenario.name,
          nameAr: scenario.nameAr,
          description: scenario.description,
          descriptionAr: scenario.descriptionAr,
          isPreset: scenario.isPreset,
          events: scenario.events.map((event) => ({
            kind: event.kind,
            label: event.label,
            labelAr: event.labelAr,
            magnitude: event.magnitude,
            unit: event.unit,
            offsetMin: event.offsetMin,
            durationMin: event.durationMin,
            regionCode: event.regionCode,
            targetCode: event.targetCode,
          })),
        }))}
        regions={REGIONS.map((region) => ({
          code: region.code,
          name: region.name,
          nameAr: region.nameAr,
        }))}
        simulations={simulations.map((simulation) => ({
          code: simulation.code,
          createdAt: simulation.createdAt.getTime(),
          riskBefore: simulation.riskBefore,
          riskAfter: simulation.riskAfter,
          summary: simulation.summary,
          summaryAr: simulation.summaryAr,
        }))}
        snapshots={snapshots.map((snapshot) => ({
          code: snapshot.code,
          ts: snapshot.ts.getTime(),
          reason: snapshot.reason,
          peakRisk: snapshot.peakRisk,
        }))}
        canSimulate={user.permissions.has('twin.simulate')}
      />

      {/* 4.0: two questions a person can put to the twin directly (§106, §107). Both run
          in the sandbox and both report their own uncertainty rather than an answer
          alone. */}
      <div className="mt-6 grid gap-4 xl:grid-cols-2">
        <div className="min-w-0">
          <AskTheFuture assetCode={target.assetCode ?? state.assets[0]?.code ?? 'T-108'} />
        </div>
        <div className="min-w-0">
          <WhatBreaksFirst assetCode={target.assetCode ?? state.assets[0]?.code ?? 'T-108'} />
        </div>
      </div>

      <div className="mt-4">
        <TrustDialog
          assetCode={target.assetCode ?? state.assets[0]?.code ?? 'T-108'}
          twinCode={target.code}
          label={t('common.proveIt')}
        />
      </div>

      <p className="mt-4 text-[11px] leading-relaxed text-text-faint">
        {locale === 'ar'
          ? 'كل ما يظهر هنا محسوب على التوأم الرقمي. لا شيء في هذه الصفحة يصل إلى حالة تشغيل حقيقية.'
          : 'Everything here is computed on the digital twin. Nothing on this page reaches a live operational state.'}
      </p>
    </>
  )
}
