import { AUDIT_ACTIONS, writeAudit } from '@/lib/audit'
import { apiRoute } from '@/lib/api/handler'
import { ApiError, ERROR_CODES } from '@/lib/api/errors'
import { memoryOutcomeSchema, type MemoryOutcomeInput } from '@/lib/api/schemas'
import { listDecisionMemory, recordOutcome } from '@/lib/services/memory-service'

export const dynamic = 'force-dynamic'

/** Remembered decisions, with their outcomes and lessons (§27, §28). */
export const GET = apiRoute({ permission: 'memory.read' }, async ({ searchParams }) => {
  const limit = Math.min(60, Math.max(1, Number(searchParams.get('limit')) || 25))
  const assetCode = searchParams.get('asset') ?? undefined
  return { decisions: await listDecisionMemory({ limit, assetCode }) }
})

/**
 * Close the loop on a remembered decision (§54).
 *
 * `evidenceKind` defaults to simulated at the schema boundary. Recording a simulated
 * result as observed is the one mistake that would turn the whole learning loop into a
 * fabrication, so the client has to say so explicitly (§30).
 */
export const POST = apiRoute<Record<string, string>, MemoryOutcomeInput>(
  { permission: 'memory.write', bodySchema: memoryOutcomeSchema, limit: 30 },
  async ({ body, user, request }) => {
    const ok = await recordOutcome({
      memoryCode: body.memoryCode,
      result: body.result,
      observedRisk: body.observedRisk ?? null,
      evidenceKind: body.evidenceKind ?? 'simulated',
      notes: body.notes,
      notesAr: body.notesAr,
      userId: user.id,
    })
    if (!ok) throw new ApiError(ERROR_CODES.notFound)

    await writeAudit({
      action: AUDIT_ACTIONS.memoryOutcomeRecorded,
      entity: 'decision_memory',
      entityId: body.memoryCode,
      user,
      request,
      detail: `${body.result} (${body.evidenceKind ?? 'simulated'})`,
    })

    return { ok: true }
  },
)
