import 'server-only'

import { prisma } from '../db'
import type { FutureBranch } from '../engine/orchestrator'
import type { Perturbation } from '../engine/telemetry'
import { round } from '../engine/rng'
import { analyseAsset, futureBranches, pickFocusAsset, type AssetIntelligence } from './intelligence-service'
import { matchPreventionPatterns } from './optimization-service'

/**
 * The AI War Room (§21–§23).
 *
 * A war room is not another dashboard: it is what the console collapses into when one
 * situation matters more than everything else on the screen. It opens on a single asset
 * and carries only what a decision about that asset needs — the clock, the chain, the
 * agents, the futures, and the approval the operator is being asked for.
 *
 * The threshold that opens one is configurable (`warroom.risk.threshold`) rather than
 * hard-coded, because what counts as a war-room event differs between a summer peak and
 * a maintenance weekend.
 */

const DEFAULT_THRESHOLD = 65
const THRESHOLD_SETTING_KEY = 'warroom.risk.threshold'

export async function warRoomThreshold(): Promise<number> {
  const setting = await prisma.appSetting.findUnique({ where: { key: THRESHOLD_SETTING_KEY } })
  const parsed = setting ? Number.parseFloat(setting.value) : Number.NaN
  return Number.isFinite(parsed) ? parsed : DEFAULT_THRESHOLD
}

export interface WarRoomState {
  active: boolean
  threshold: number
  intel: AssetIntelligence
  branches: FutureBranch[]
  patterns: Array<{ code: string; label: string; labelAr: string; similarity: number; successRate: number }>
  decisions: Array<{
    code: string
    title: string
    titleAr: string
    status: string
    riskBefore: number
    riskAfter: number
    createdAt: number
    approvals: Array<{ step: string; decision: string; userName: string; userNameAr: string }>
  }>
  /** Seconds to the predicted event, for the incident clock (§22). */
  secondsToEvent: number | null
  isEstimated: boolean
}

export async function getWarRoom(
  options: { assetCode?: string; ts?: number; perturbation?: Perturbation } = {},
): Promise<WarRoomState | null> {
  const ts = options.ts ?? Date.now()
  const assetCode =
    options.assetCode ?? (await pickFocusAsset({ ts, perturbation: options.perturbation }))
  if (!assetCode) return null

  const intel = await analyseAsset(assetCode, { ts, perturbation: options.perturbation })
  if (!intel) return null

  const [threshold, branches, patternMatches, decisionRows] = await Promise.all([
    warRoomThreshold(),
    futureBranches(intel),
    matchPreventionPatterns({
      eventType: intel.prediction.eventType,
      assetTypeKey: intel.focus.profile.assetTypeKey,
      loadPct: intel.focus.sample.loadPct,
      tempC: intel.focus.sample.tempC,
      dnaSimilarity: intel.focus.dnaSimilarity,
    }),
    prisma.decisionRecord.findMany({
      where: { assetCode },
      orderBy: { createdAt: 'desc' },
      take: 5,
      include: { approvals: { orderBy: { createdAt: 'asc' } } },
    }),
  ])

  return {
    active: intel.orchestration.unifiedRisk >= threshold,
    threshold,
    intel,
    branches,
    patterns: patternMatches.map((match) => ({
      code: match.pattern.code,
      label: match.pattern.strategyLabel,
      labelAr: match.pattern.strategyLabelAr,
      similarity: match.similarity,
      successRate: round(match.pattern.successRate, 1),
    })),
    decisions: decisionRows.map((record) => ({
      code: record.code,
      title: record.title,
      titleAr: record.titleAr,
      status: record.status,
      riskBefore: round(record.riskBefore, 1),
      riskAfter: round(record.riskAfter, 1),
      createdAt: record.createdAt.getTime(),
      approvals: record.approvals.map((approval) => ({
        step: approval.step,
        decision: approval.decision,
        userName: approval.userName,
        userNameAr: approval.userNameAr,
      })),
    })),
    // The clock counts to an *estimate*. It is labelled as one everywhere it appears,
    // because a countdown that looks certain invites the operator to trust it as one.
    secondsToEvent:
      intel.prediction.etaMinutes === null ? null : Math.round(intel.prediction.etaMinutes * 60),
    isEstimated: true,
  }
}
