import { AUDIT_ACTIONS, writeAudit } from '@/lib/audit'
import { apiRoute } from '@/lib/api/handler'
import { ApiError, ERROR_CODES } from '@/lib/api/errors'
import { verificationRecordSchema, type VerificationRecordInput } from '@/lib/api/schemas'
import {
  getVerificationReport,
  listVerifications,
  predictAndRecord,
  verifyPending,
} from '@/lib/services/verification-service'
import { getTwinState } from '@/lib/services/twin-service'

export const dynamic = 'force-dynamic'

/** Predicted versus observed, with the roll-up (§7, §63). */
export const GET = apiRoute({ permission: 'verification.read' }, async ({ searchParams }) => {
  const assetCode = searchParams.get('asset') ?? undefined
  const status = searchParams.get('status') ?? undefined
  const limit = Math.min(100, Math.max(1, Number(searchParams.get('limit')) || 30))

  const [verifications, report] = await Promise.all([
    listVerifications({ assetCode, status, limit }),
    getVerificationReport({ assetCode }),
  ])

  return { verifications, ...report }
})

/**
 * Record a prediction against a horizon, then close whatever is already due.
 *
 * Both halves in one call because they are one loop: a client that could record without
 * ever closing would quietly build a backlog of unverified claims, which is the exact
 * failure the verification page exists to make visible.
 */
export const POST = apiRoute<Record<string, string>, VerificationRecordInput>(
  { permission: 'verification.run', bodySchema: verificationRecordSchema, limit: 30 },
  async ({ body, user, request }) => {
    const state = await getTwinState(body.twinCode)
    if (!state) throw new ApiError(ERROR_CODES.notFound)

    const code = await predictAndRecord({
      assetCode: body.assetCode,
      twinCode: body.twinCode,
      horizonMin: body.horizonMin,
      fidelity: state.fidelity.score,
      twinVersion: state.twin.code,
    })
    if (!code) throw new ApiError(ERROR_CODES.notFound)

    const closed = await verifyPending({ limit: 10 })

    await writeAudit({
      action: AUDIT_ACTIONS.verificationRecorded,
      entity: 'asset',
      entityId: body.assetCode,
      user,
      request,
      detail: `recorded ${code} at +${body.horizonMin} min; closed ${closed.length}`,
    })

    return { code, closed: closed.length, outcomes: closed }
  },
)
