/**
 * Environment Configuration Validation Tests
 *
 * These tests validate that critical environment variables are properly configured.
 * Running these tests during CI/CD prevents deployment with misconfigured services.
 *
 * Issue this prevents:
 * - Missing or incorrectly formatted Redis URL
 * - Missing Redis password when authentication is required
 * - Incorrect SMTP configuration (Docker vs localhost hostnames)
 * - Missing critical secrets that cause silent failures
 */

// Requires live environment with all env vars configured
describe.skip("Environment Configuration Validation", () => {
  describe("Redis Configuration", () => {
    test("REDIS_URL should be defined", () => {
      const redisUrl = process.env.REDIS_URL;
      expect(redisUrl).toBeDefined();
      expect(redisUrl?.length).toBeGreaterThan(0);
    });

    test("REDIS_URL should be a valid Redis URL", () => {
      const redisUrl = process.env.REDIS_URL;

      if (redisUrl) {
        expect(redisUrl).toMatch(/^redis:\/\//);

        // Should be parseable as URL
        expect(() => new URL(redisUrl)).not.toThrow();
      }
    });

    test("REDIS_URL should include password when REDIS_PASSWORD is set", () => {
      const redisUrl = process.env.REDIS_URL;
      const redisPassword = process.env.REDIS_PASSWORD;

      if (redisPassword && redisPassword.length > 0 && redisUrl) {
        // Password should be in URL format: redis://:password@host:port
        expect(redisUrl).toContain("@");

        const url = new URL(redisUrl);
        expect(url.password).toBe(redisPassword);
      }
    });

    test("REDIS_PASSWORD should match password in REDIS_URL", () => {
      const redisUrl = process.env.REDIS_URL;
      const redisPassword = process.env.REDIS_PASSWORD;

      if (redisUrl && redisPassword) {
        const url = new URL(redisUrl);
        expect(url.password).toBe(redisPassword);
      }
    });

    test("should not use Upstash credentials in development", () => {
      if (process.env.NODE_ENV !== "production") {
        // In development, should use local Redis, not Upstash
        const upstashUrl = process.env.UPSTASH_REDIS_REST_URL;

        // Upstash URL should either be undefined or not contain "upstash.io" in dev
        if (upstashUrl) {
          // This is a warning - Upstash in dev may be intentional
          console.warn(
            "UPSTASH_REDIS_REST_URL is set in development environment",
          );
        }
      }
    });

    test("Redis should use valid hostname (localhost or Docker)", () => {
      const redisUrl = process.env.REDIS_URL;

      if (redisUrl && process.env.NODE_ENV !== "production") {
        const url = new URL(redisUrl);

        // In development, should use either:
        // - localhost (when running npm run dev locally)
        // - mawidi-redis (when running in Docker Compose)
        expect(["localhost", "mawidi-redis"]).toContain(url.hostname);
      }
    });
  });

  describe("SMTP/Email Configuration", () => {
    test("SMTP_HOST should be defined", () => {
      const smtpHost = process.env.SMTP_HOST;
      expect(smtpHost).toBeDefined();
    });

    test("SMTP_PORT should be defined and numeric", () => {
      const smtpPort = process.env.SMTP_PORT;
      expect(smtpPort).toBeDefined();

      if (smtpPort) {
        expect(parseInt(smtpPort)).toBeGreaterThan(0);
        expect(parseInt(smtpPort)).toBeLessThan(65536);
      }
    });

    test("SMTP should use valid hostname (localhost or Docker)", () => {
      const smtpHost = process.env.SMTP_HOST;

      if (process.env.NODE_ENV !== "production") {
        // In development, should use either:
        // - localhost (when running npm run dev locally)
        // - mawidi-mailhog (when running in Docker Compose)
        expect(["localhost", "mawidi-mailhog"]).toContain(smtpHost);
      }
    });

    test("SMTP_FROM should be defined", () => {
      const smtpFrom = process.env.SMTP_FROM;
      expect(smtpFrom).toBeDefined();
    });

    test("development should use port 1025 for MailHog", () => {
      const smtpPort = process.env.SMTP_PORT;

      if (process.env.NODE_ENV !== "production") {
        expect(smtpPort).toBe("1025");
      }
    });
  });

  describe("Application URLs", () => {
    test("NEXT_PUBLIC_APP_URL should be defined", () => {
      const appUrl = process.env.NEXT_PUBLIC_APP_URL;
      expect(appUrl).toBeDefined();
    });

    test("NEXT_PUBLIC_APP_URL should be valid URL", () => {
      const appUrl = process.env.NEXT_PUBLIC_APP_URL;

      if (appUrl) {
        expect(() => new URL(appUrl)).not.toThrow();
      }
    });

    test("development should use port 9000", () => {
      const appUrl = process.env.NEXT_PUBLIC_APP_URL;

      if (process.env.NODE_ENV !== "production" && appUrl) {
        expect(appUrl).toContain(":9000");
      }
    });

    test("NEXTAUTH_URL should match APP_URL", () => {
      const appUrl = process.env.NEXT_PUBLIC_APP_URL;
      const nextAuthUrl = process.env.NEXTAUTH_URL;

      if (appUrl && nextAuthUrl) {
        expect(nextAuthUrl).toBe(appUrl);
      }
    });
  });

  describe("Database Configuration", () => {
    test("CONVEX_URL or NEXT_PUBLIC_CONVEX_URL should be defined", () => {
      const convexUrl =
        process.env.CONVEX_URL || process.env.NEXT_PUBLIC_CONVEX_URL;
      expect(convexUrl).toBeDefined();
    });
  });

  describe("Security Secrets", () => {
    test("NEXTAUTH_SECRET should be defined", () => {
      const secret = process.env.NEXTAUTH_SECRET;
      expect(secret).toBeDefined();
      expect(secret?.length).toBeGreaterThan(0);
    });

    test("NEXTAUTH_SECRET should not be the default development value in production", () => {
      const secret = process.env.NEXTAUTH_SECRET;

      if (process.env.NODE_ENV === "production" && secret) {
        expect(secret).not.toContain("development");
        expect(secret.length).toBeGreaterThanOrEqual(32);
      }
    });

    test("AUTH_SECRET should be defined", () => {
      const secret = process.env.AUTH_SECRET;
      expect(secret).toBeDefined();
    });

    test("ENCRYPTION_KEY should be defined and correct length", () => {
      const key = process.env.ENCRYPTION_KEY;
      expect(key).toBeDefined();

      if (key) {
        // Should be 64 hex characters (32 bytes)
        expect(key.length).toBe(64);
        expect(key).toMatch(/^[a-fA-F0-9]+$/);
      }
    });
  });

  describe("Stripe Configuration", () => {
    test("STRIPE_SECRET_KEY should be defined", () => {
      const key = process.env.STRIPE_SECRET_KEY;
      expect(key).toBeDefined();
    });

    test("NEXT_PUBLIC_STRIPE_PUBLIC_KEY should be defined", () => {
      const key = process.env.NEXT_PUBLIC_STRIPE_PUBLIC_KEY;
      expect(key).toBeDefined();
    });

    test("development should use test mode Stripe keys", () => {
      const secretKey = process.env.STRIPE_SECRET_KEY;
      const publicKey = process.env.NEXT_PUBLIC_STRIPE_PUBLIC_KEY;

      if (process.env.NODE_ENV !== "production") {
        if (secretKey) {
          expect(secretKey).toMatch(/^sk_test_/);
        }
        if (publicKey) {
          expect(publicKey).toMatch(/^pk_test_/);
        }
      }
    });

    test("production should NOT use test mode Stripe keys", () => {
      const secretKey = process.env.STRIPE_SECRET_KEY;
      const publicKey = process.env.NEXT_PUBLIC_STRIPE_PUBLIC_KEY;

      if (process.env.NODE_ENV === "production") {
        if (secretKey) {
          expect(secretKey).not.toMatch(/^sk_test_/);
          expect(secretKey).toMatch(/^sk_live_/);
        }
        if (publicKey) {
          expect(publicKey).not.toMatch(/^pk_test_/);
          expect(publicKey).toMatch(/^pk_live_/);
        }
      }
    });
  });
});

// Requires live environment with all env vars configured
describe.skip("Configuration Consistency", () => {
  test("all services should use consistent hostname style", () => {
    const redisUrl = process.env.REDIS_URL;
    const smtpHost = process.env.SMTP_HOST;

    if (redisUrl && smtpHost && process.env.NODE_ENV !== "production") {
      const redisHost = new URL(redisUrl).hostname;

      // Both should either use localhost (local dev) or Docker hostnames
      const redisIsLocal = redisHost === "localhost";
      const smtpIsLocal = smtpHost === "localhost";
      const redisIsDocker = redisHost === "mawidi-redis";
      const smtpIsDocker = smtpHost === "mawidi-mailhog";

      // Either both are local or both are Docker
      const bothLocal = redisIsLocal && smtpIsLocal;
      const bothDocker = redisIsDocker && smtpIsDocker;

      // Both should be valid hostnames (either local or Docker)
      expect(redisIsLocal || redisIsDocker).toBe(true);
      expect(smtpIsLocal || smtpIsDocker).toBe(true);

      // Ideally consistent, but mixed is OK too (warning only)
      if (!bothLocal && !bothDocker) {
        console.warn(
          "Mixed hostname styles detected - Redis and SMTP use different styles",
        );
      }
    }
  });

  test("environment variables should be properly defined", () => {
    // Essential variables must be defined
    expect(process.env.REDIS_URL).toBeDefined();
    expect(process.env.SMTP_HOST).toBeDefined();
    // DATABASE_URL removed - Convex is the primary database
    expect(process.env.NEXTAUTH_SECRET).toBeDefined();
  });
});
