import { AUDIT_ACTIONS, writeAudit } from '@/lib/audit'
import { apiRoute } from '@/lib/api/handler'
import { ApiError, ERROR_CODES } from '@/lib/api/errors'
import { counterfactualSchema, type CounterfactualRequest } from '@/lib/api/schemas'
import { toPerturbation } from '@/lib/api/overlay'
import {
  listCounterfactualRuns,
  persistCounterfactual,
  runCounterfactual,
} from '@/lib/services/counterfactual-service'

export const dynamic = 'force-dynamic'

export const GET = apiRoute({ permission: 'simulations.read' }, async ({ searchParams }) => {
  const limit = Math.min(50, Math.max(1, Number(searchParams.get('limit')) || 20))
  const runs = await listCounterfactualRuns(limit)
  return {
    runs: runs.map((run) => ({
      code: run.code,
      assetCode: run.assetCode,
      objective: run.objective,
      targetValue: run.targetValue,
      riskBefore: run.riskBefore,
      riskAfter: run.riskAfter,
      achieved: run.achieved,
      totalMw: run.totalMw,
      totalCostSar: run.totalCostSar,
      confidence: run.confidence,
      summary: run.summary,
      summaryAr: run.summaryAr,
      createdAt: run.createdAt.getTime(),
      actions: run.actions.map((action) => ({
        actionKey: action.actionKey,
        actionType: action.actionType,
        magnitudeMw: action.magnitudeMw,
        unit: action.unit,
        label: action.label,
        labelAr: action.labelAr,
        contribution: action.contribution,
      })),
    })),
  }
})

/** Search for the smallest intervention that reaches the stated target (§9, §10). */
export const POST = apiRoute<Record<string, string>, CounterfactualRequest>(
  { permission: 'counterfactual.run', bodySchema: counterfactualSchema, limit: 20 },
  async ({ body, user, request }) => {
    const outcome = await runCounterfactual({
      assetCode: body.assetCode,
      objective: body.objective,
      targetValue: body.targetValue,
      perturbation: toPerturbation(body.overlay),
    })
    if (!outcome) throw new ApiError(ERROR_CODES.notFound)

    let code: string | null = null
    if (body.persist) code = await persistCounterfactual(outcome, { userId: user.id })

    await writeAudit({
      action: AUDIT_ACTIONS.counterfactualRun,
      entity: 'asset',
      entityId: body.assetCode,
      user,
      request,
      detail: `${body.objective} ${body.targetValue}: ${outcome.result.achieved ? 'reached' : 'not reachable'} with ${outcome.result.doses.length} lever(s)`,
    })

    return { code, ...outcome }
  },
)
