import type { PoolClient } from "pg";
import { pool } from "../db/client.js";
import { clientIp } from "./crypto.js";

export interface AuditEvent {
  actorUserId?: number | null;
  action: string;
  entityType?: string | null;
  entityId?: number | null;
  changedFields?: Record<string, unknown> | null;
  context?: Record<string, unknown> | null;
  ip?: string | null;
  userAgent?: string | null;
}

/**
 * Append-only audit trail. Never throws upward: an audit failure must not break the
 * request, but it is logged loudly so it is noticed during operations.
 */
export async function audit(event: AuditEvent, client?: PoolClient): Promise<void> {
  const executor = client ?? pool;
  try {
    await executor.query(
      `INSERT INTO audit_logs (actor_user_id, action, entity_type, entity_id, changed_fields, ip_address, user_agent, context)
       VALUES ($1, $2, $3, $4, $5::jsonb, $6::inet, $7, $8::jsonb)`,
      [
        event.actorUserId ?? null,
        event.action,
        event.entityType ?? null,
        event.entityId ?? null,
        event.changedFields ? JSON.stringify(event.changedFields) : null,
        event.ip ?? null,
        event.userAgent?.slice(0, 255) ?? null,
        event.context ? JSON.stringify(event.context) : null,
      ],
    );
  } catch (error) {
    console.error("[audit] FAILED to write audit entry:", event.action, error);
  }
}

export { clientIp };
