/**
 * Phishing Audit Trail (Phase 20)
 *
 * Single, append-only audit-event writer used by every state-changing
 * phishing-triage service call (remediation-service.ts). Every write is a
 * parameterized INSERT into `audit_events` — no ON CONFLICT, no updates,
 * no deletes. This is the ONLY place that inserts into `audit_events`.
 *
 * Canonical `event_type` strings emitted across this phase (Phase 19 + 20):
 *   - 'campaign_classified'               (Phase 19 — not emitted by this file)
 *   - 'remediation_approved'              (remediation-service.ts, Task 2)
 *   - 'remediation_completed'             (remediation-service.ts, Task 2)
 *   - 'campaign_marked_false_positive'    (remediation-service.ts, Task 3)
 *
 * `writeAuditEvent` accepts an optional transaction `client` so a caller can
 * write its state change and its audit row inside the SAME
 * `postgresClient.transaction(...)` block — a rollback discards both
 * together, guaranteeing no state change can commit without its audit row
 * (REMED-06 / T-20-03).
 */

import { postgresClient } from './postgres-client';

export interface AuditEventInput {
  campaignId: string;
  actor: string | null;
  eventType: string;
  payload: Record<string, unknown>;
}

/**
 * Minimal shape shared by both `postgresClient` and a transaction `PoolClient`
 * — only the `query` method this module needs, so a fake test client or a
 * real `pg.PoolClient` both satisfy it without importing `pg` here.
 */
export interface AuditQueryClient {
  query: (text: string, params?: unknown[]) => Promise<{ rows: Array<{ id: string }> }>;
}

/**
 * Inserts one row into `audit_events` and returns its id. Pass `client`
 * (a transaction client) to make the write commit/rollback atomically with
 * the caller's own state change; omit it to write standalone via the
 * `postgresClient` singleton.
 */
export async function writeAuditEvent(input: AuditEventInput, client?: AuditQueryClient): Promise<string> {
  const target = client ?? postgresClient;
  const result = await target.query(
    `INSERT INTO audit_events (campaign_id, actor, event_type, payload)
     VALUES ($1, $2, $3, $4::jsonb)
     RETURNING id::text AS id`,
    [input.campaignId, input.actor, input.eventType, JSON.stringify(input.payload)]
  );
  return result.rows[0].id;
}
