import { apiRoute } from '@/lib/api/handler'
import { ApiError, ERROR_CODES } from '@/lib/api/errors'
import { toPerturbation } from '@/lib/api/overlay'
import { scenarioParamsSchema } from '@/lib/api/schemas'
import { analyseAsset } from '@/lib/services/intelligence-service'
import { flattenTree } from '@/lib/engine/cascade-tree'

export const dynamic = 'force-dynamic'

/**
 * The propagation tree and the cheapest place to cut it (§43, §44, §45).
 *
 * The tree is derived from the same cascade walk the timeline shows, so the two can never
 * disagree about what happens.
 */
export const GET = apiRoute({ permission: 'cascade.run' }, async ({ searchParams }) => {
  const assetCode = searchParams.get('asset')
  if (!assetCode) throw new ApiError(ERROR_CODES.validationFailed, { details: { asset: 'required' } })

  const overlayRaw = searchParams.get('overlay')
  const overlay = overlayRaw ? scenarioParamsSchema.safeParse(JSON.parse(overlayRaw)) : null
  if (overlay && !overlay.success) {
    throw new ApiError(ERROR_CODES.validationFailed, { details: { overlay: 'invalid' } })
  }

  const intel = await analyseAsset(assetCode, {
    perturbation: overlay?.success ? toPerturbation(overlay.data) : undefined,
  })
  if (!intel) throw new ApiError(ERROR_CODES.notFound)

  return {
    assetCode,
    ts: intel.ts,
    tree: intel.cascadeTree,
    nodes: flattenTree(intel.cascadeTree).map((node) => ({
      assetCode: node.assetCode,
      assetName: node.assetName,
      assetNameAr: node.assetNameAr,
      depth: node.depth,
      offsetMin: node.offsetMin,
      hopProbability: node.hopProbability,
      probability: node.probability,
      confidence: node.confidence,
      delayMin: node.delayMin,
      outcome: node.outcome,
      severity: node.severity,
      subtreeCustomers: node.subtreeCustomers,
      subtreeNodes: node.subtreeNodes,
    })),
    breakpoints: intel.breakpoints,
    contained: intel.cascade.affectedAssets <= 1,
  }
})
