import { AUDIT_ACTIONS, writeAudit } from '@/lib/audit'
import { apiRoute } from '@/lib/api/handler'
import { ApiError, ERROR_CODES } from '@/lib/api/errors'
import { twinSimulateSchema, type TwinSimulateInput } from '@/lib/api/schemas'
import { runTwinSimulation, saveScenario } from '@/lib/services/twin-service'

export const dynamic = 'force-dynamic'

/**
 * Run a composed scenario against the twin (§35, §79).
 *
 * The response is explicitly marked simulated. Nothing on this path can write telemetry
 * or change an asset, and the snapshot taken first means the run can be reproduced.
 */
export const POST = apiRoute<{ code: string }, TwinSimulateInput>(
  { permission: 'twin.simulate', bodySchema: twinSimulateSchema, limit: 24 },
  async ({ params, body, user, request }) => {
    let scenarioCode = body.scenarioCode ?? null
    if (body.saveAs) {
      scenarioCode = await saveScenario({
        twinCode: params.code,
        name: body.saveAs,
        nameAr: body.saveAs,
        origin: 'manual',
        events: body.events,
        userId: user.id,
      })
    }

    const result = await runTwinSimulation(params.code, {
      events: body.events,
      horizonMin: body.horizonMin,
      scenarioCode,
      userId: user.id,
    })
    if (!result) throw new ApiError(ERROR_CODES.notFound)

    await writeAudit({
      action: AUDIT_ACTIONS.twinSimulated,
      entity: 'digital_twin',
      entityId: params.code,
      user,
      request,
      detail: `${result.code}: risk ${result.riskBefore} % → ${result.riskAfter} % over ${body.events.length} event(s)`,
    })

    return { ...result, scenarioCode }
  },
)
