import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import {
  listRegulationChangeAlerts,
  resetRegulationsStateForTests,
  runPeriodicNormativeVerification,
  verifyOfficialNormativeSources,
} from "@/lib/compliance/regulations";

function buildResponse(etag: string, status = 200) {
  return new Response("", {
    status,
    headers: {
      etag,
      "last-modified": "Thu, 02 Apr 2026 00:00:00 GMT",
      "content-length": "100",
      "content-type": "text/html",
    },
  });
}

describe("regulations verification", () => {
  beforeEach(async () => {
    await resetRegulationsStateForTests();
    vi.useFakeTimers();
    vi.setSystemTime(new Date("2026-04-02T10:00:00.000Z"));
  });

  afterEach(async () => {
    vi.unstubAllGlobals();
    vi.restoreAllMocks();
    vi.useRealTimers();
    await resetRegulationsStateForTests();
  });

  it("detects source changes and emits regulation update alerts", async () => {
    const fetchMock = vi
      .fn<(input: RequestInfo | URL, init?: RequestInit) => Promise<Response>>()
      .mockResolvedValueOnce(buildResponse("v1"))
      .mockResolvedValueOnce(buildResponse("v2"));

    vi.stubGlobal("fetch", fetchMock);

    await verifyOfficialNormativeSources(["nl-reglamento-adquisiciones-estatal"]);
    const changed = await verifyOfficialNormativeSources(["nl-reglamento-adquisiciones-estatal"]);

    expect(changed[0]?.status).toBe("warning");
    expect(changed[0]?.changed).toBe(true);

    const alerts = await listRegulationChangeAlerts(new Date("2026-04-02T10:30:00.000Z"), 30);
    expect(alerts.some((item) => item.kind === "normative_regulation_update" && item.severity === "high")).toBe(true);
  });

  it("records failed verifications and emits pending alerts", async () => {
    vi.stubGlobal(
      "fetch",
      vi.fn<(input: RequestInfo | URL, init?: RequestInit) => Promise<Response>>().mockRejectedValue(new Error("timeout")),
    );

    const result = await verifyOfficialNormativeSources(["spgg-reglamento-adquisiciones"]);
    expect(result[0]?.status).toBe("failed");

    const alerts = await listRegulationChangeAlerts(new Date("2026-04-02T11:00:00.000Z"), 30);
    expect(alerts.some((item) => item.kind === "normative_verification_pending")).toBe(true);
  });

  it("runs periodic verification only when due", async () => {
    vi.stubGlobal("fetch", vi.fn<(input: RequestInfo | URL, init?: RequestInit) => Promise<Response>>().mockResolvedValue(buildResponse("v1")));

    const first = await runPeriodicNormativeVerification(new Date("2026-04-02T10:00:00.000Z"));
    expect(first.checked).toBe(true);
    expect(first.dueCount).toBeGreaterThan(0);
    expect(first.results.length).toBe(first.dueCount);

    const second = await runPeriodicNormativeVerification(new Date("2026-04-02T10:05:00.000Z"));
    expect(second.checked).toBe(false);
    expect(second.dueCount).toBe(0);
  });
});
