/**
 * @jest-environment node
 */

import {
  validateEnv,
  validateEnvironment,
  isFeatureConfigured,
} from "../../lib/env-validation";

describe("Environment Validation", () => {
  const originalEnv = process.env;

  beforeEach(() => {
    jest.resetModules();
    process.env = { ...originalEnv };
  });

  afterAll(() => {
    process.env = originalEnv;
  });

  describe("validateEnv", () => {
    it("should return errors when critical variables are missing", () => {
      delete process.env.NEXT_PUBLIC_CONVEX_URL;
      delete process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY;
      delete process.env.CLERK_SECRET_KEY;
      delete process.env.NEXTAUTH_SECRET;
      delete process.env.ENCRYPTION_KEY;

      const result = validateEnv();

      expect(result.valid).toBe(false);
      expect(result.errors.length).toBeGreaterThan(0);
    });

    it("should validate NEXTAUTH_SECRET length", () => {
      process.env.NEXT_PUBLIC_CONVEX_URL = "https://test.convex.cloud";
      process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY = "pk_test_123";
      process.env.CLERK_SECRET_KEY = "sk_test_123";
      process.env.NEXTAUTH_SECRET = "tooshort";
      process.env.ENCRYPTION_KEY = "0".repeat(64);

      const result = validateEnv();

      expect(result.valid).toBe(false);
      expect(
        result.errors.some((e: string) => e.includes("NEXTAUTH_SECRET")),
      ).toBe(true);
    });

    it("should validate ENCRYPTION_KEY format (64 hex characters)", () => {
      process.env.NEXT_PUBLIC_CONVEX_URL = "https://test.convex.cloud";
      process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY = "pk_test_123";
      process.env.CLERK_SECRET_KEY = "sk_test_123";
      process.env.NEXTAUTH_SECRET = "a".repeat(32);
      process.env.ENCRYPTION_KEY = "invalid";

      const result = validateEnv();

      expect(result.valid).toBe(false);
      expect(
        result.errors.some((e: string) => e.includes("ENCRYPTION_KEY")),
      ).toBe(true);
    });

    it("should return warnings for missing recommended variables", () => {
      process.env.NEXT_PUBLIC_CONVEX_URL = "https://test.convex.cloud";
      process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY = "pk_test_123";
      process.env.CLERK_SECRET_KEY = "sk_test_123";
      process.env.NEXTAUTH_SECRET = "a".repeat(32);
      process.env.ENCRYPTION_KEY = "0".repeat(64);

      delete process.env.STRIPE_SECRET_KEY;
      delete process.env.SMTP_HOST;

      const result = validateEnv();

      expect(result.valid).toBe(true);
      expect(result.warnings.length).toBeGreaterThan(0);
    });

    it("should pass with all critical variables correctly set", () => {
      process.env.NEXT_PUBLIC_CONVEX_URL = "https://test.convex.cloud";
      process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY = "pk_test_123";
      process.env.CLERK_SECRET_KEY = "sk_test_123";
      process.env.NEXTAUTH_SECRET = "a".repeat(32);
      process.env.ENCRYPTION_KEY = "0".repeat(64);

      const result = validateEnv();

      expect(result.valid).toBe(true);
      expect(result.errors.length).toBe(0);
    });

    it("should validate STRIPE_SECRET_KEY format when present", () => {
      process.env.NEXT_PUBLIC_CONVEX_URL = "https://test.convex.cloud";
      process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY = "pk_test_123";
      process.env.CLERK_SECRET_KEY = "sk_test_123";
      process.env.NEXTAUTH_SECRET = "a".repeat(32);
      process.env.ENCRYPTION_KEY = "0".repeat(64);
      process.env.STRIPE_SECRET_KEY = "invalid_key";

      const result = validateEnv();

      expect(result.valid).toBe(true); // Still valid as Stripe is recommended
      expect(
        result.warnings.some((w: string) => w.includes("STRIPE_SECRET_KEY")),
      ).toBe(true);
    });

    it("should accept valid STRIPE_SECRET_KEY formats", () => {
      process.env.NEXT_PUBLIC_CONVEX_URL = "https://test.convex.cloud";
      process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY = "pk_test_123";
      process.env.CLERK_SECRET_KEY = "sk_test_123";
      process.env.NEXTAUTH_SECRET = "a".repeat(32);
      process.env.ENCRYPTION_KEY = "0".repeat(64);
      process.env.STRIPE_SECRET_KEY = "sk_test_1234567890";

      const result = validateEnv();

      expect(result.valid).toBe(true);
      expect(
        result.warnings.some((w: string) => w.includes("STRIPE_SECRET_KEY")),
      ).toBe(false);
    });
  });

  describe("validateEnvironment", () => {
    it("should not throw in test environment", () => {
      expect(() => validateEnvironment()).not.toThrow();
    });
  });

  describe("isFeatureConfigured", () => {
    beforeEach(() => {
      delete process.env.STRIPE_SECRET_KEY;
      delete process.env.SMTP_HOST;
      delete process.env.SMTP_PORT;
      delete process.env.UPSTASH_REDIS_REST_URL;
      delete process.env.REDIS_URL;
      delete process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY;
      delete process.env.CLERK_SECRET_KEY;
      delete process.env.NEXT_PUBLIC_CONVEX_URL;
      delete process.env.RECAPTCHA_SECRET_KEY;
    });

    it("should detect when Stripe is configured", () => {
      process.env.STRIPE_SECRET_KEY = "sk_test_1234567890";
      expect(isFeatureConfigured("stripe")).toBe(true);
    });

    it("should detect when Stripe is not configured", () => {
      expect(isFeatureConfigured("stripe")).toBe(false);
    });

    it("should detect when Email is configured", () => {
      process.env.SMTP_HOST = "smtp.example.com";
      process.env.SMTP_PORT = "587";
      expect(isFeatureConfigured("email")).toBe(true);
    });

    it("should detect when Email is not configured", () => {
      expect(isFeatureConfigured("email")).toBe(false);
    });

    it("should detect when BullMQ/Redis is configured via Upstash", () => {
      process.env.UPSTASH_REDIS_REST_URL = "https://example.upstash.io";
      expect(isFeatureConfigured("bullmq")).toBe(true);
    });

    it("should detect when BullMQ/Redis is configured via REDIS_URL", () => {
      process.env.REDIS_URL = "redis://localhost:6379";
      expect(isFeatureConfigured("bullmq")).toBe(true);
    });

    it("should detect when Clerk is configured", () => {
      process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY = "pk_test_123";
      process.env.CLERK_SECRET_KEY = "sk_test_123";
      expect(isFeatureConfigured("clerk")).toBe(true);
    });

    it("should detect when Convex is configured", () => {
      process.env.NEXT_PUBLIC_CONVEX_URL = "https://test.convex.cloud";
      expect(isFeatureConfigured("convex")).toBe(true);
    });

    it("should detect when reCAPTCHA is configured", () => {
      process.env.RECAPTCHA_SECRET_KEY = "secret123";
      expect(isFeatureConfigured("recaptcha")).toBe(true);
    });
  });
});
