import { describe, it, expect } from 'vitest';
import { createPgliteClient } from '@platform-modules/db/pglite';
import { auditSchema, listAudit } from '@platform-modules/audit';
import { auditTableSql, recordAudit } from './audit.js';

async function freshDb() {
  const db = createPgliteClient({ schema: auditSchema });
  for (const stmt of auditTableSql().split(';').map((s) => s.trim()).filter(Boolean)) {
    await db.execute(stmt);
  }
  return db;
}

describe('auditTableSql', () => {
  it('emits idempotent CREATE TABLE + tenant indexes', () => {
    const ddl = auditTableSql();
    expect(ddl).toContain('CREATE TABLE IF NOT EXISTS audit_log');
    for (const col of [
      'id',
      'actor_id',
      'actor_type',
      'actor_label',
      'action',
      'entity_type',
      'entity_id',
      'metadata',
      'ip',
      'tenant_id',
      'created_at',
    ]) {
      expect(ddl).toContain(col);
    }
    expect(ddl).toContain('audit_log_tenant_created_idx');
    expect(ddl).toContain('audit_log_tenant_entity_idx');
    expect(ddl).toContain('audit_log_tenant_actor_idx');
  });
});

describe('recordAudit', () => {
  it('writes an audit row mapping actor + ip + decoupled metadata', async () => {
    const db = await freshDb();
    await recordAudit(db, { actorId: 'u1', ip: '203.0.113.7' }, {
      action: 'content.publish',
      entityType: 'content',
      entityId: 'e1',
    });
    const { items } = await listAudit(db, {});
    expect(items).toHaveLength(1);
    expect(items[0]).toMatchObject({
      actorId: 'u1',
      actorType: 'admin',
      action: 'content.publish',
      entityType: 'content',
      entityId: 'e1',
      ip: '203.0.113.7',
      tenantId: null,
    });
  });

  it('never throws when the write fails (closed pool) — best-effort', async () => {
    const db = await freshDb();
    await db.execute('DROP TABLE audit_log');
    await expect(
      recordAudit(db, { actorId: 'u1', ip: null }, { action: 'x', entityType: 'content', entityId: 'e1' }),
    ).resolves.toBeUndefined();
  });
});