import { describe, it, expectTypeOf } from "vitest";
import type { AuditEntry, AuditAction, AuditFrom } from "./audit-entry";

describe("AuditAction", () => {
  it("is a closed enum of 10 values", () => {
    expectTypeOf<AuditAction>().toEqualTypeOf<
      | "VIEW"
      | "CREATE"
      | "UPDATE"
      | "DELETE"
      | "EXPORT"
      | "PERMISSION_CHANGE"
      | "CONSENT_GRANT"
      | "CONSENT_WITHDRAW"
      | "RESTRICT"
      | "UNRESTRICT"
    >();
  });
});

describe("AuditFrom", () => {
  it("requires ipTruncated and userAgent", () => {
    expectTypeOf<AuditFrom>().toEqualTypeOf<{
      ipTruncated: string;
      userAgent: string;
    }>();
  });
});

describe("AuditEntry", () => {
  it("requires the WHO/WHAT/WHEN/SCOPE/FROM/PII/OUTCOME fields", () => {
    const entry: AuditEntry = {
      actorId: "user_1",
      actorType: "user",
      actorRoles: ["admin"],
      action: "VIEW",
      resource: { type: "articles" },
      at: new Date(),
      scope: { feature: "blog", environment: "test", tenant: "default" },
      from: { ipTruncated: "10.0.0.0", userAgent: "test" },
      containsPii: false,
      outcome: "success",
    };
    expectTypeOf(entry).toMatchTypeOf<AuditEntry>();
  });

  it("makes optional fields actually optional", () => {
    type Entry = AuditEntry;
    type OptionalKeys =
      | "changedFields"
      | "reason"
      | "correlationId"
      | "requestId"
      | "piiCategories"
      | "errorCode";
    expectTypeOf<Pick<Entry, OptionalKeys>>().toEqualTypeOf<
      Partial<Pick<Entry, OptionalKeys>>
    >();
  });
});
