import { AUDIT_ACTIONS, writeAudit } from '@/lib/audit'
import { apiRoute } from '@/lib/api/handler'
import { ApiError, ERROR_CODES } from '@/lib/api/errors'
import { optimizationSchema, type OptimizationInput } from '@/lib/api/schemas'
import { toPerturbation } from '@/lib/api/overlay'
import {
  listOptimizationRuns,
  persistOptimization,
  runSelfHealing,
} from '@/lib/services/optimization-service'
import { strategyDto } from '@/lib/services/intelligence-dto'

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 listOptimizationRuns(limit)
  return {
    runs: runs.map((run) => ({
      code: run.code,
      assetCode: run.assetCode,
      objectiveKey: run.objectiveKey,
      candidateCount: run.candidateCount,
      bestScore: run.bestScore,
      createdAt: run.createdAt.getTime(),
      strategies: run.strategies.map((strategy) => ({
        code: strategy.code,
        label: strategy.label,
        labelAr: strategy.labelAr,
        kind: strategy.kind,
        rank: strategy.rank,
        score: strategy.score,
        riskBefore: strategy.riskBefore,
        riskAfter: strategy.riskAfter,
        costSar: strategy.costSar,
        executionMin: strategy.executionMin,
        customerImpact: strategy.customerImpact,
        confidence: strategy.confidence,
        isRecommended: strategy.isRecommended,
        actions: strategy.actions,
        results: strategy.results,
      })),
    })),
  }
})

/** Rank candidate strategies under a stated objective (§11). */
export const POST = apiRoute<Record<string, string>, OptimizationInput>(
  { permission: 'optimization.run', bodySchema: optimizationSchema, limit: 30 },
  async ({ body, user, request }) => {
    const result = await runSelfHealing(body.assetCode, {
      perturbation: toPerturbation(body.overlay),
      objectiveKey: body.objectiveKey,
    })
    if (!result) throw new ApiError(ERROR_CODES.notFound)

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

    await writeAudit({
      action: AUDIT_ACTIONS.optimizationRun,
      entity: 'asset',
      entityId: body.assetCode,
      user,
      request,
      detail: `${result.strategies.length} strategies under ${result.objectiveKey}; best ${result.best?.label ?? 'none'}`,
    })

    return {
      code,
      assetCode: result.assetCode,
      objectiveKey: result.objectiveKey,
      riskBefore: result.riskBefore,
      strategies: result.strategies.map(strategyDto),
      best: result.best ? strategyDto(result.best) : null,
    }
  },
)
