import type { Metadata } from 'next'
import { redirect } from 'next/navigation'

import { ImmersiveDemo, type ImmersivePayload } from '@/components/demo/immersive-demo'
import { getCurrentUser } from '@/lib/auth/current-user'
import { PermissionGate } from '@/components/console/permission-gate'
import { demoBaseTimestamp, demoPerturbation, DEMO_ASSET_CODE } from '@/lib/demo/config'
import { getRegion } from '@/lib/data/regions'
import { analyseAsset, futureBranches } from '@/lib/services/intelligence-service'
import { getMapData } from '@/lib/services/map-service'
import { runCounterfactual } from '@/lib/services/counterfactual-service'
import { getGhostFuture, getTwinState } from '@/lib/services/twin-service'

export const metadata: Metadata = { title: 'NABDH — Immersive' }
export const dynamic = 'force-dynamic'

/**
 * The immersive demo route (§63).
 *
 * Deliberately outside the console layout: no sidebar, no command bar, nothing to click
 * by accident during a presentation. Everything is computed on the server before the
 * first frame so the sequence never pauses to fetch — a demo that buffers between steps
 * loses the room.
 */
export default async function ImmersiveDemoPage() {
  const user = await getCurrentUser()
  if (!user) redirect('/login')
  if (!user.permissions.has('presentation.use')) return <PermissionGate />

  const ts = demoBaseTimestamp()
  const perturbation = demoPerturbation()

  const intel = await analyseAsset(DEMO_ASSET_CODE, { ts, perturbation, includeLeadTime: true })
  if (!intel) return <PermissionGate />

  const region = getRegion(intel.focus.profile.regionCode)
  const siteTwinCode = 'TWIN-SITE-SS-RYD-01'

  const [map, branches, counterfactual, twinState, ghost] = await Promise.all([
    getMapData({ ts, includeForecast: false }),
    futureBranches(intel),
    runCounterfactual({
      assetCode: DEMO_ASSET_CODE,
      objective: 'risk_below',
      targetValue: 12,
      ts,
      perturbation,
    }),
    getTwinState(siteTwinCode, { ts, perturbation }),
    getGhostFuture(DEMO_ASSET_CODE, { ts, perturbation, offsetMin: 30 }),
  ])

  const payload: ImmersivePayload = {
    assetCode: DEMO_ASSET_CODE,
    regionName: region.name,
    regionNameAr: region.nameAr,
    stabilityIndex: intel.snapshot.stabilityIndex,
    gridState: intel.snapshot.state,
    map,
    scene: {
      nodes: twinState?.scene.nodes ?? [],
      edges: twinState?.scene.edges ?? [],
    },
    assets: twinState?.assets ?? [],
    weakSignal: {
      combinedScore: intel.weakSignals.combinedScore,
      traditionalAlarm: intel.weakSignals.traditionalAlarm,
      leadMinutes: intel.leadTime?.leadMinutes ?? null,
    },
    dna: intel.dnaMatches[0]
      ? {
          code: intel.dnaMatches[0].pattern.code,
          similarity: intel.dnaMatches[0].similarity,
          name: intel.dnaMatches[0].pattern.name,
          nameAr: intel.dnaMatches[0].pattern.nameAr,
        }
      : null,
    prediction: {
      etaMinutes: intel.prediction.etaMinutes,
      peakRisk: intel.prediction.peakRisk,
      currentRisk: intel.prediction.currentRisk,
      confidence: intel.prediction.confidence,
    },
    cascade: intel.cascade.steps.map((step) => ({
      assetCode: step.assetCode,
      offsetMin: step.offsetMin,
      outcome: step.outcome,
      probability: step.probability,
    })),
    branches,
    strategies: intel.optimisation.strategies.map((strategy) => ({
      label: strategy.label,
      labelAr: strategy.labelAr,
      riskBefore: strategy.evaluation.riskBefore,
      riskAfter: strategy.evaluation.riskAfter,
      score: strategy.score,
      isRecommended: strategy.isRecommended,
    })),
    counterfactual: counterfactual
      ? {
          achieved: counterfactual.result.achieved,
          riskBefore: counterfactual.riskBefore,
          riskAfter: counterfactual.riskAfter,
          doses: counterfactual.result.doses.map((dose) => ({
            label: dose.label,
            labelAr: dose.labelAr,
          })),
        }
      : null,
    ghost: ghost
      ? {
          nowLoad: ghost.present.loadPct,
          futureLoad: ghost.future.loadPct,
          nowTemp: ghost.present.tempC,
          futureTemp: ghost.future.tempC,
          offsetMin: ghost.offsetMin,
        }
      : null,
  }

  return <ImmersiveDemo payload={payload} />
}
