import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
import { isOidcEnabled, validateOidcConfig } from "./auth.config";

describe("auth.config", () => {
  // Store original env vars to restore after each test
  const originalEnv = { ...process.env };

  beforeEach(() => {
    // Clear relevant env vars before each test
    delete process.env.OIDC_ENABLED;
    delete process.env.OIDC_ISSUER;
    delete process.env.OIDC_CLIENT_ID;
    delete process.env.OIDC_CLIENT_SECRET;
  });

  afterEach(() => {
    // Restore original env vars
    process.env = { ...originalEnv };
  });

  describe("isOidcEnabled", () => {
    it("should return false when OIDC_ENABLED is not set", () => {
      expect(isOidcEnabled()).toBe(false);
    });

    it("should return false when OIDC_ENABLED is 'false'", () => {
      process.env.OIDC_ENABLED = "false";
      expect(isOidcEnabled()).toBe(false);
    });

    it("should return false when OIDC_ENABLED is '0'", () => {
      process.env.OIDC_ENABLED = "0";
      expect(isOidcEnabled()).toBe(false);
    });

    it("should return false when OIDC_ENABLED is empty string", () => {
      process.env.OIDC_ENABLED = "";
      expect(isOidcEnabled()).toBe(false);
    });

    it("should return true when OIDC_ENABLED is 'true'", () => {
      process.env.OIDC_ENABLED = "true";
      expect(isOidcEnabled()).toBe(true);
    });

    it("should return true when OIDC_ENABLED is '1'", () => {
      process.env.OIDC_ENABLED = "1";
      expect(isOidcEnabled()).toBe(true);
    });
  });

  describe("validateOidcConfig", () => {
    describe("when OIDC is disabled", () => {
      it("should not throw when OIDC_ENABLED is not set", () => {
        expect(() => validateOidcConfig()).not.toThrow();
      });

      it("should not throw when OIDC_ENABLED is false even if vars are missing", () => {
        process.env.OIDC_ENABLED = "false";
        // Intentionally not setting any OIDC vars
        expect(() => validateOidcConfig()).not.toThrow();
      });
    });

    describe("when OIDC is enabled", () => {
      beforeEach(() => {
        process.env.OIDC_ENABLED = "true";
      });

      it("should throw when OIDC_ISSUER is missing", () => {
        process.env.OIDC_CLIENT_ID = "test-client-id";
        process.env.OIDC_CLIENT_SECRET = "test-client-secret";

        expect(() => validateOidcConfig()).toThrow("OIDC_ISSUER");
        expect(() => validateOidcConfig()).toThrow("OIDC authentication is enabled");
      });

      it("should throw when OIDC_CLIENT_ID is missing", () => {
        process.env.OIDC_ISSUER = "https://auth.example.com/";
        process.env.OIDC_CLIENT_SECRET = "test-client-secret";

        expect(() => validateOidcConfig()).toThrow("OIDC_CLIENT_ID");
      });

      it("should throw when OIDC_CLIENT_SECRET is missing", () => {
        process.env.OIDC_ISSUER = "https://auth.example.com/";
        process.env.OIDC_CLIENT_ID = "test-client-id";

        expect(() => validateOidcConfig()).toThrow("OIDC_CLIENT_SECRET");
      });

      it("should throw when all required vars are missing", () => {
        expect(() => validateOidcConfig()).toThrow(
          "OIDC_ISSUER, OIDC_CLIENT_ID, OIDC_CLIENT_SECRET"
        );
      });

      it("should throw when vars are empty strings", () => {
        process.env.OIDC_ISSUER = "";
        process.env.OIDC_CLIENT_ID = "";
        process.env.OIDC_CLIENT_SECRET = "";

        expect(() => validateOidcConfig()).toThrow(
          "OIDC_ISSUER, OIDC_CLIENT_ID, OIDC_CLIENT_SECRET"
        );
      });

      it("should throw when vars are whitespace only", () => {
        process.env.OIDC_ISSUER = "   ";
        process.env.OIDC_CLIENT_ID = "test-client-id";
        process.env.OIDC_CLIENT_SECRET = "test-client-secret";

        expect(() => validateOidcConfig()).toThrow("OIDC_ISSUER");
      });

      it("should throw when OIDC_ISSUER does not end with trailing slash", () => {
        process.env.OIDC_ISSUER = "https://auth.example.com/application/o/mosaic";
        process.env.OIDC_CLIENT_ID = "test-client-id";
        process.env.OIDC_CLIENT_SECRET = "test-client-secret";

        expect(() => validateOidcConfig()).toThrow("OIDC_ISSUER must end with a trailing slash");
        expect(() => validateOidcConfig()).toThrow("https://auth.example.com/application/o/mosaic");
      });

      it("should not throw with valid complete configuration", () => {
        process.env.OIDC_ISSUER = "https://auth.example.com/application/o/mosaic-stack/";
        process.env.OIDC_CLIENT_ID = "test-client-id";
        process.env.OIDC_CLIENT_SECRET = "test-client-secret";

        expect(() => validateOidcConfig()).not.toThrow();
      });

      it("should suggest disabling OIDC in error message", () => {
        expect(() => validateOidcConfig()).toThrow("OIDC_ENABLED=false");
      });
    });
  });
});
