import { AUDIT_ACTIONS, writeAudit } from '@/lib/audit'
import { apiRoute } from '@/lib/api/handler'
import { ApiError, ERROR_CODES } from '@/lib/api/errors'
import { orchestratorSchema, type OrchestratorInput } from '@/lib/api/schemas'
import { toPerturbation } from '@/lib/api/overlay'
import { analyseAsset, persistOrchestration, pickFocusAsset } from '@/lib/services/intelligence-service'
import { agentDto, orchestrationDto } from '@/lib/services/intelligence-dto'

export const dynamic = 'force-dynamic'

/**
 * Run the agent panel over one asset (§3, §4).
 *
 * Rate limited well below the global default: a pass walks the twin forward, runs the
 * cascade and scores every candidate strategy, and it is the one endpoint in the build
 * where a careless loop would actually hurt.
 */
export const POST = apiRoute<Record<string, string>, OrchestratorInput>(
  { permission: 'agents.run', bodySchema: orchestratorSchema, limit: 30 },
  async ({ body, user, request }) => {
    const perturbation = toPerturbation(body.overlay)
    const assetCode = body.assetCode ?? (await pickFocusAsset({ perturbation }))
    if (!assetCode) throw new ApiError(ERROR_CODES.notFound)

    const intel = await analyseAsset(assetCode, {
      perturbation,
      objectiveKey: body.objectiveKey,
      includeLeadTime: body.includeLeadTime ?? false,
    })
    if (!intel) throw new ApiError(ERROR_CODES.notFound)

    let orchestrationId: string | null = null
    if (body.persist) orchestrationId = await persistOrchestration(intel)

    await writeAudit({
      action: AUDIT_ACTIONS.orchestrationRun,
      entity: 'asset',
      entityId: assetCode,
      user,
      request,
      detail: `Unified risk ${intel.orchestration.unifiedRisk} % across ${intel.agents.length} agents`,
    })

    return {
      assetCode,
      orchestrationId,
      agents: agentDto(intel),
      orchestration: orchestrationDto(intel),
    }
  },
)
