import type { Querier } from '@platform-modules/db'
import { auditLog } from './schema.js'
import type { AuditSchema } from './schema.js'
import type { AuditEvent, LogAuditResult } from './types.js'

/**
 * Append an audit record. **Never throws** — a write failure is swallowed and
 * returned as `{ logged: false, error }` so it cannot break the operation being logged.
 *
 * CONTRACT (boundary spec amendment B): because failures are swallowed, this is the
 * *decoupled* form — call it **after the business commit, or fire-and-forget**.
 * Do NOT call it inside the caller's business transaction: a failed insert aborts the
 * whole Postgres tx while the swallow hides it, so the mutation can commit with the
 * audit row silently dropped. For transaction-atomic audit, insert into the exported
 * `auditLog` schema directly within your own tx (a throw there correctly rolls back).
 */
export async function logAudit<S extends AuditSchema>(
  db: Querier<S>,
  event: AuditEvent,
): Promise<LogAuditResult> {
  try {
    const [row] = await db
      .insert(auditLog)
      .values({
        actorId: event.actorId ?? null,
        actorType: event.actorType ?? null,
        actorLabel: event.actorLabel ?? null,
        action: event.action,
        entityType: event.entityType,
        entityId: event.entityId,
        metadata: event.metadata ?? null,
        ip: event.ip ?? null,
        tenantId: event.tenantId ?? null,
      })
      .returning({ id: auditLog.id })

    return { logged: true, id: row!.id }
  } catch (error) {
    return { logged: false, error }
  }
}
