import { mkdtemp, readFile, stat } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { describe, expect, test } from "bun:test";
import {
  JsonlVoiceAuditStore,
  reconcileAuditLog,
  reconcileRecord,
} from "./audit-store.ts";
import type { VoiceCallAuditRecord } from "./types.ts";

describe("JsonlVoiceAuditStore", () => {
  test("appends private JSONL audit records", async () => {
    const dir = await mkdtemp(join(tmpdir(), "voice-audit-"));
    const auditPath = join(dir, "nested", "audit.jsonl");
    const store = new JsonlVoiceAuditStore(auditPath);

    await store.append(auditRecord({ callId: "call-1" }));

    expect(await store.readAll()).toMatchObject([{ callId: "call-1" }]);
    expect((await stat(join(dir, "nested"))).mode & 0o777).toBe(0o700);
    expect((await stat(auditPath)).mode & 0o777).toBe(0o600);
  });
});

describe("RingCentral audit reconciliation", () => {
  test("matches nested detailed call-log legs and extracts recording metadata", () => {
    const result = reconcileRecord(
      auditRecord({
        callId: "bridge-call",
        ringCentral: { telephonySessionId: "tel-session-123" },
      }),
      [
        {
          id: "top-record",
          legs: [
            {
              id: "leg-record",
              sessionId: "rc-session-123",
              telephonySessionId: "tel-session-123",
              recording: { contentUri: "https://example.invalid/recording" },
            },
          ],
        },
      ],
    );

    expect(result).toMatchObject({
      matched: true,
      matchedBy: "telephonySessionId",
      callLogId: "leg-record",
      sessionId: "rc-session-123",
      telephonySessionId: "tel-session-123",
      recordingContentUri: "https://example.invalid/recording",
    });
  });

  test("writes reconciled audit log with RingCentral metadata", async () => {
    const dir = await mkdtemp(join(tmpdir(), "voice-audit-reconcile-"));
    const auditPath = join(dir, "audit.jsonl");
    const outputPath = join(dir, "audit.reconciled.jsonl");
    const store = new JsonlVoiceAuditStore(auditPath);
    await store.append(
      auditRecord({
        callId: "bridge-call",
        ringCentral: { sessionId: "rc-session-456" },
      }),
    );

    const result = await reconcileAuditLog({
      auditPath,
      outputPath,
      dateFrom: "2026-06-01T00:00:00.000Z",
      dateTo: "2026-06-02T00:00:00.000Z",
      ringCentral: {
        async callTool(name, args) {
          expect(name).toBe("pull_call_log");
          expect(args).toMatchObject({ max_pages: 3 });
          return {
            records: [
              {
                id: "call-log-record",
                sessionId: "rc-session-456",
                telephonySessionId: "tel-session-456",
              },
            ],
          };
        },
      },
    });

    expect(result).toMatchObject({ total: 1, matched: 1, outputPath });
    const [line] = (await readFile(outputPath, "utf8")).trim().split("\n");
    const record = JSON.parse(line!) as VoiceCallAuditRecord;
    expect(record.ringCentral).toMatchObject({
      callLogId: "call-log-record",
      sessionId: "rc-session-456",
      telephonySessionId: "tel-session-456",
    });
    expect((await stat(outputPath)).mode & 0o777).toBe(0o600);
  });
});

function auditRecord(
  overrides: Partial<VoiceCallAuditRecord> = {},
): VoiceCallAuditRecord {
  const { ringCentral, ...rest } = overrides;
  return {
    callId: "call",
    telephonyProvider: "ringcentral",
    voiceProvider: "openai_realtime",
    disposition: "resolved_by_ai",
    startedAt: "2026-06-01T12:00:00.000Z",
    ...rest,
    ringCentral: {
      ...(ringCentral ?? {}),
    },
  };
}
