import { AUDIT_ACTIONS, writeAudit } from '@/lib/audit'
import { apiRoute } from '@/lib/api/handler'
import { ApiError, ERROR_CODES } from '@/lib/api/errors'
import { toPerturbation } from '@/lib/api/overlay'
import { compareFuturesSchema, type CompareFuturesInput } from '@/lib/api/schemas'
import { demoBaseTimestamp } from '@/lib/demo/config'
import { compareFutures } from '@/lib/services/compare-service'

export const dynamic = 'force-dynamic'

/**
 * Split future and three futures (§11–§12).
 *
 * Solves the same grid at the same instant under two or three decisions and returns all of
 * them, with the differences already computed. Every pane is a sandbox solve; the route
 * takes `twin.simulate` rather than any control permission because there is no control
 * here to permit — nothing it produces is applied anywhere.
 */
export const POST = apiRoute<Record<string, string>, CompareFuturesInput>(
  { permission: 'twin.simulate', bodySchema: compareFuturesSchema, limit: 20 },
  async ({ body, user, request }) => {
    const result = await compareFutures({
      ts: body.demoClock ? demoBaseTimestamp() : undefined,
      twinCode: body.twinCode,
      scenario: body.scenario ?? null,
      overlay: toPerturbation(body.overlay),
      assetCode: body.assetCode ?? null,
      offsetMin: body.offsetMin ?? 0,
      includeAlternative: body.includeAlternative ?? false,
    })
    if (!result) throw new ApiError(ERROR_CODES.notFound)

    const applied = result.futures.filter((future) => future.available && future.strategy)
    await writeAudit({
      action: AUDIT_ACTIONS.futuresCompared,
      entity: 'live_grid',
      entityId: result.assetCode ?? result.twinCode,
      user,
      request,
      detail: `${result.futures.length} futures compared for ${result.assetCode ?? result.twinCode}: ${
        applied.map((future) => future.strategy!.label).join(', ') || 'baseline only'
      } (simulated)`,
    })

    return result
  },
)
