import { describe, it, expect } from "vitest";
import { licenseReducer, initialLicenseState } from "./LicenseContext";
import type { Edition, LicenseInfo } from "../services/licenseService";

const makeInfo = (edition: Exclude<Edition, "free">): LicenseInfo => ({
  edition,
  email: "max@example.com",
  features: [],
  machine_limit: 3,
  issued_at: 1,
  expires_at: 0,
});

// The CWE-703 retry loop arms exclusively on `status === "error"`, and its
// LOAD_START clears `error`. A rejected key must therefore never re-enter the
// load lifecycle: it would arm the auto refresh, which would wipe the very
// message the user is reading (~1s after submitting an invalid key).

const premiumReady = licenseReducer(
  licenseReducer(initialLicenseState, { type: "LOAD_START" }),
  { type: "LOAD_DONE", edition: "premium", info: makeInfo("premium") },
);

describe("licenseReducer — load lifecycle (CWE-703)", () => {
  it("LOAD_ERROR preserves the last-known edition and info", () => {
    const errored = licenseReducer(premiumReady, { type: "LOAD_ERROR", error: "ipc down" });
    expect(errored.status).toBe("error");
    expect(errored.error).toBe("ipc down");
    expect(errored.edition).toBe("premium");
    expect(errored.info).toEqual(makeInfo("premium"));
  });

  it("LOAD_START clears the load error but not a pending validation error", () => {
    const rejected = licenseReducer(
      licenseReducer(premiumReady, { type: "VALIDATE_START" }),
      { type: "VALIDATE_ERROR", error: "invalid key" },
    );
    const refreshed = licenseReducer(rejected, { type: "LOAD_START" });
    expect(refreshed.status).toBe("loading");
    expect(refreshed.error).toBeNull();
    expect(refreshed.validationError).toBe("invalid key");
  });
});

describe("licenseReducer — key validation is orthogonal to the load lifecycle", () => {
  it("VALIDATE_ERROR on a ready license keeps status ready (retry never arms)", () => {
    const validating = licenseReducer(premiumReady, { type: "VALIDATE_START" });
    expect(validating.status).toBe("ready");
    expect(validating.validating).toBe(true);

    const rejected = licenseReducer(validating, { type: "VALIDATE_ERROR", error: "invalid key" });
    expect(rejected.status).toBe("ready");
    expect(rejected.validating).toBe(false);
    expect(rejected.validationError).toBe("invalid key");
    expect(rejected.edition).toBe("premium");
    expect(rejected.info).toEqual(makeInfo("premium"));
  });

  it("VALIDATE_ERROR during a boot error keeps status error (load retry keeps running)", () => {
    const bootError = licenseReducer(
      licenseReducer(initialLicenseState, { type: "LOAD_START" }),
      { type: "LOAD_ERROR", error: "boot fail" },
    );
    const rejected = licenseReducer(
      licenseReducer(bootError, { type: "VALIDATE_START" }),
      { type: "VALIDATE_ERROR", error: "invalid key" },
    );
    expect(rejected.status).toBe("error");
    expect(rejected.error).toBe("boot fail");
    expect(rejected.validationError).toBe("invalid key");
    expect(rejected.edition).toBe("free");
  });

  it("VALIDATE_START clears the previous validation error", () => {
    const rejected = licenseReducer(
      licenseReducer(premiumReady, { type: "VALIDATE_START" }),
      { type: "VALIDATE_ERROR", error: "invalid key" },
    );
    const resubmit = licenseReducer(rejected, { type: "VALIDATE_START" });
    expect(resubmit.validating).toBe(true);
    expect(resubmit.validationError).toBeNull();
  });

  it("VALIDATE_DONE resets the full state, recovering from a boot error", () => {
    const bootError = licenseReducer(
      licenseReducer(initialLicenseState, { type: "LOAD_START" }),
      { type: "LOAD_ERROR", error: "boot fail" },
    );
    const done = licenseReducer(
      licenseReducer(bootError, { type: "VALIDATE_START" }),
      { type: "VALIDATE_DONE", info: makeInfo("base") },
    );
    expect(done).toEqual({
      status: "ready",
      edition: "base",
      info: makeInfo("base"),
      error: null,
      validating: false,
      validationError: null,
    });
  });
});
