import { describe, it, expect } from "vitest";
import { InMemoryConsent } from "@/in-memory-consent";

describe("InMemoryConsent.isGranted", () => {
  it("returns false for an unknown category", async () => {
    const consent = new InMemoryConsent();
    expect(consent.isGranted("analytics")).toBe(false);
  });

  it("returns true after grant", async () => {
    const consent = new InMemoryConsent();
    await consent.grant("analytics");
    expect(consent.isGranted("analytics")).toBe(true);
  });

  it("returns false after withdraw", async () => {
    const consent = new InMemoryConsent();
    await consent.grant("analytics");
    await consent.withdraw("analytics");
    expect(consent.isGranted("analytics")).toBe(false);
  });
});

describe("InMemoryConsent.grant", () => {
  it("stores bannerVersion, policyVersion, method in state", async () => {
    const consent = new InMemoryConsent();
    await consent.grant("marketing", {
      bannerVersion: "v2",
      policyVersion: "2026-01",
      method: "banner-accept",
    });
    const cats = consent.getCategories();
    expect(cats).toHaveLength(1);
    expect(cats[0]!.bannerVersion).toBe("v2");
    expect(cats[0]!.policyVersion).toBe("2026-01");
    expect(cats[0]!.method).toBe("banner-accept");
    expect(cats[0]!.grantedAt).toBeInstanceOf(Date);
  });

  it("preserves withdrawnAt across regrant", async () => {
    const consent = new InMemoryConsent();
    await consent.grant("analytics");
    await consent.withdraw("analytics");
    const withdrawnAt = consent.getCategories()[0]!.withdrawnAt;
    await consent.grant("analytics");
    const cats = consent.getCategories();
    expect(cats[0]!.withdrawnAt).toBe(withdrawnAt);
  });
});

describe("InMemoryConsent.withdraw", () => {
  it("sets withdrawnAt on an existing entry", async () => {
    const consent = new InMemoryConsent();
    await consent.grant("functional");
    await consent.withdraw("functional");
    const cats = consent.getCategories();
    expect(cats[0]!.state).toBe("denied");
    expect(cats[0]!.withdrawnAt).toBeInstanceOf(Date);
  });

  it("can withdraw a category that was never granted", async () => {
    const consent = new InMemoryConsent();
    await consent.withdraw("analytics");
    expect(consent.isGranted("analytics")).toBe(false);
    const cats = consent.getCategories();
    expect(cats[0]!.state).toBe("denied");
  });
});

describe("InMemoryConsent.getCategories", () => {
  it("returns all granted and denied categories", async () => {
    const consent = new InMemoryConsent();
    await consent.grant("necessary");
    await consent.grant("analytics");
    await consent.withdraw("analytics");

    const cats = consent.getCategories();
    expect(cats).toHaveLength(2);
  });
});
