import 'server-only'

import { round } from '../engine/rng'
import type { AssetIntelligence } from './intelligence-service'

/**
 * API-facing shapes for the analysis pipeline.
 *
 * The internal `AssetIntelligence` object carries whole snapshots — every asset, every
 * forward frame — because the agents need them. Serialising that over the wire would put
 * megabytes on a page that wants a headline and a chain, so the boundary is explicit:
 * these are the fields the API promises, and they are trimmed on purpose.
 */

export function agentDto(intel: AssetIntelligence) {
  return intel.agents.map((agent) => ({
    key: agent.key,
    ordinal: agent.ordinal,
    status: agent.status,
    summary: agent.summary,
    summaryAr: agent.summaryAr,
    confidence: agent.confidence,
    dataQuality: agent.dataQuality,
    durationMs: agent.durationMs,
    inputs: agent.inputs,
    inputsAr: agent.inputsAr,
    findings: agent.findings,
  }))
}

export function orchestrationDto(intel: AssetIntelligence) {
  const { orchestration } = intel
  return {
    ts: orchestration.ts,
    assetCode: orchestration.assetCode,
    regionCode: orchestration.regionCode,
    unifiedRisk: orchestration.unifiedRisk,
    band: orchestration.band,
    rationale: orchestration.rationale,
    rationaleAr: orchestration.rationaleAr,
    confidence: orchestration.confidence,
    preventionWindow: orchestration.preventionWindow,
    uncertainty: orchestration.uncertainty,
    contributingAgents: orchestration.contributingAgents,
    dataWarning: orchestration.dataWarning,
    dataWarningAr: orchestration.dataWarningAr,
    flow: orchestration.flow,
    recommended: orchestration.recommended
      ? strategyDto(orchestration.recommended)
      : null,
    alternatives: orchestration.alternatives.map(strategyDto),
  }
}

export function strategyDto(strategy: AssetIntelligence['optimisation']['strategies'][number]) {
  return {
    key: strategy.key,
    kind: strategy.kind,
    label: strategy.label,
    labelAr: strategy.labelAr,
    rank: strategy.rank,
    score: strategy.score,
    confidence: strategy.confidence,
    riskBefore: round(strategy.evaluation.riskBefore, 1),
    riskAfter: round(strategy.evaluation.riskAfter, 1),
    riskReduction: round(strategy.evaluation.riskReduction, 1),
    loadAfterPct: round(strategy.evaluation.loadAfterPct, 1),
    tempAfterC: round(strategy.evaluation.tempAfterC, 1),
    totalMw: round(strategy.evaluation.totalMw, 1),
    costSar: strategy.costSar,
    executionMin: strategy.executionMin,
    customerImpact: strategy.customerImpact,
    isRecommended: strategy.isRecommended,
    actions: strategy.actions,
    metrics: strategy.metrics,
  }
}

export function predictionDto(intel: AssetIntelligence) {
  return {
    currentRisk: round(intel.prediction.currentRisk, 1),
    peakRisk: round(intel.prediction.peakRisk, 1),
    probability: round(intel.prediction.probability, 3),
    confidence: round(intel.prediction.confidence, 1),
    severity: intel.prediction.severity,
    eventType: intel.prediction.eventType,
    etaMinutes: intel.prediction.etaMinutes,
    etaAt: intel.prediction.etaAt,
    breachReason: intel.prediction.breachReason,
    horizonMin: intel.prediction.horizonMin,
    trendPerHour: round(intel.prediction.trendPerHour, 2),
  }
}

export function rootCauseDto(intel: AssetIntelligence) {
  const { rootCause } = intel
  return {
    primary: rootCause.primary,
    alternatives: rootCause.alternatives,
    candidates: rootCause.candidates,
    chain: rootCause.chain,
    confidence: rootCause.confidence,
    summary: rootCause.summary,
    summaryAr: rootCause.summaryAr,
    recommendedInvestigation: rootCause.recommendedInvestigation,
    recommendedInvestigationAr: rootCause.recommendedInvestigationAr,
  }
}

export function cascadeDto(intel: AssetIntelligence) {
  return {
    originCode: intel.cascade.originCode,
    horizonMin: intel.cascade.horizonMin,
    affectedAssets: intel.cascade.affectedAssets,
    affectedMw: intel.cascade.affectedMw,
    affectedCustomers: intel.cascade.affectedCustomers,
    unservedMw: intel.cascade.unservedMw,
    maxDepth: intel.cascade.maxDepth,
    regionalRisk: intel.cascade.regionalRisk,
    containedAtMin: intel.cascade.containedAtMin,
    steps: intel.cascade.steps,
  }
}

/** Everything an intelligence page needs, without the snapshots behind it. */
export function intelligenceDto(intel: AssetIntelligence) {
  return {
    ts: intel.ts,
    assetCode: intel.assetCode,
    regionCode: intel.focus.profile.regionCode,
    state: {
      loadPct: round(intel.focus.sample.loadPct, 1),
      loadMw: round(intel.focus.sample.loadMw, 1),
      tempC: round(intel.focus.sample.tempC, 1),
      voltageKv: round(intel.focus.sample.voltageKv, 2),
      voltageDeviationPct: round(intel.focus.sample.voltageDeviationPct, 2),
      effectiveHealth: round(intel.focus.sample.effectiveHealth, 1),
      capacityMw: intel.focus.profile.capacityMw,
      customersServed: intel.focus.profile.customersServed,
      riskScore: round(intel.focus.risk.score, 1),
      gridState: intel.focus.state,
      rulDays: Math.round(intel.rulDays),
    },
    prediction: predictionDto(intel),
    dnaMatches: intel.dnaMatches.map((match) => ({
      similarity: round(match.similarity, 1),
      code: match.pattern.code,
      name: match.pattern.name,
      nameAr: match.pattern.nameAr,
      eventType: match.pattern.eventType,
      severity: match.pattern.severity,
    })),
    weakSignals: intel.weakSignals,
    cascade: cascadeDto(intel),
    rootCause: rootCauseDto(intel),
    dataQuality: {
      score: intel.dataQuality.score,
      band: intel.dataQuality.band,
      sensorsExpected: intel.dataQuality.sensorsExpected,
      sensorsReporting: intel.dataQuality.sensorsReporting,
      staleSensors: intel.dataQuality.staleSensors,
      outlierCount: intel.dataQuality.outlierCount,
      warning: intel.dataQuality.warning,
      warningAr: intel.dataQuality.warningAr,
      untrusted: intel.dataQuality.untrusted,
    },
    resources: intel.resources,
    agents: agentDto(intel),
    orchestration: orchestrationDto(intel),
    strategies: intel.optimisation.strategies.map(strategyDto),
    objectiveKey: intel.optimisation.objectiveKey,
    leadTime: intel.leadTime,
  }
}
