import { describe, it, expect } from "vitest";
import { InMemoryDataExport } from "@/in-memory-data-export";
import { InMemoryDataDelete } from "@/in-memory-data-delete";
import { InMemoryDataRectify } from "@/in-memory-data-rectify";
import { InMemoryProcessingRestriction } from "@/in-memory-processing-restriction";

describe("InMemoryDataExport", () => {
  it("returns an empty bundle with the correct shape", async () => {
    const exporter = new InMemoryDataExport();
    const bundle = await exporter.exportSubjectData("alice", "json");

    expect(bundle.subjectId).toBe("alice");
    expect(bundle.format).toBe("json");
    expect(typeof bundle.exportedAt).toBe("string");
    expect(bundle.data).toEqual({});
  });

  it("preserves format in the returned bundle", async () => {
    const exporter = new InMemoryDataExport();
    const bundle = await exporter.exportSubjectData("bob", "json-ld");

    expect(bundle.format).toBe("json-ld");
  });
});

describe("InMemoryDataDelete", () => {
  it("returns a DeletionCertificate with the correct shape", async () => {
    const deleter = new InMemoryDataDelete();
    const cert = await deleter.deleteSubjectData("alice", "soft");

    expect(cert.subjectId).toBe("alice");
    expect(cert.mode).toBe("soft");
    expect(cert.reason).toBe("art-17-request");
    expect(cert.affected).toEqual([]);
    expect(typeof cert.auditEntryId).toBe("string");
    expect(typeof cert.timestamp).toBe("string");
  });

  it("preserves mode in the certificate", async () => {
    const deleter = new InMemoryDataDelete();
    const cert = await deleter.deleteSubjectData("alice", "cascade-hard");

    expect(cert.mode).toBe("cascade-hard");
  });
});

describe("InMemoryDataRectify", () => {
  it("resolves without error", async () => {
    const rectifier = new InMemoryDataRectify();
    await expect(
      rectifier.updateSubjectField("alice", "users", "name", "Alice New"),
    ).resolves.toBeUndefined();
  });
});

describe("InMemoryProcessingRestriction", () => {
  it("isRestricted returns false for unknown subjects", async () => {
    const restriction = new InMemoryProcessingRestriction();
    expect(await restriction.isRestricted("alice")).toBe(false);
  });

  it("setRestriction(true) makes isRestricted return true", async () => {
    const restriction = new InMemoryProcessingRestriction();
    await restriction.setRestriction("alice", true);
    expect(await restriction.isRestricted("alice")).toBe(true);
  });

  it("setRestriction(false) makes isRestricted return false", async () => {
    const restriction = new InMemoryProcessingRestriction();
    await restriction.setRestriction("alice", true);
    await restriction.setRestriction("alice", false);
    expect(await restriction.isRestricted("alice")).toBe(false);
  });

  it("tracks restriction per subject independently", async () => {
    const restriction = new InMemoryProcessingRestriction();
    await restriction.setRestriction("alice", true);
    await restriction.setRestriction("bob", false);

    expect(await restriction.isRestricted("alice")).toBe(true);
    expect(await restriction.isRestricted("bob")).toBe(false);
  });
});
