import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { getWebsiteApiBaseUrl } from './apiBaseUrl';

describe('getWebsiteApiBaseUrl', () => {
  const originalEnv = process.env;

  beforeEach(() => {
    vi.resetModules();
    process.env = { ...originalEnv };
    // Clear window mock
    if (typeof window !== 'undefined') {
      delete (window as any).__NEXT_PUBLIC_API_BASE_URL__;
    }
  });

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

  describe('with environment variables', () => {
    it('should return configured NEXT_PUBLIC_API_BASE_URL in browser', () => {
      // Mock browser environment
      vi.stubGlobal('window', { location: {} } as any);
      
      process.env.NEXT_PUBLIC_API_BASE_URL = 'https://api.example.com';
      
      const result = getWebsiteApiBaseUrl();
      expect(result).toBe('https://api.example.com');
    });

    it('should return configured API_BASE_URL in Node.js', () => {
      // Ensure we're not in browser
      vi.stubGlobal('window', undefined as any);
      
      process.env.API_BASE_URL = 'https://api.example.com';
      
      const result = getWebsiteApiBaseUrl();
      expect(result).toBe('https://api.example.com');
    });

    it('should prefer API_BASE_URL over NEXT_PUBLIC_API_BASE_URL in Node.js', () => {
      vi.stubGlobal('window', undefined as any);
      
      process.env.API_BASE_URL = 'https://api-server.com';
      process.env.NEXT_PUBLIC_API_BASE_URL = 'https://api-client.com';
      
      const result = getWebsiteApiBaseUrl();
      expect(result).toBe('https://api-server.com');
    });

    it('should fallback to NEXT_PUBLIC_API_BASE_URL if API_BASE_URL is not set', () => {
      vi.stubGlobal('window', undefined as any);
      
      delete process.env.API_BASE_URL;
      process.env.NEXT_PUBLIC_API_BASE_URL = 'https://api-fallback.com';
      
      const result = getWebsiteApiBaseUrl();
      expect(result).toBe('https://api-fallback.com');
    });
  });

  describe('normalization', () => {
    it('should trim whitespace from URL', () => {
      vi.stubGlobal('window', undefined as any);
      
      process.env.API_BASE_URL = '  https://api.example.com  ';
      
      const result = getWebsiteApiBaseUrl();
      expect(result).toBe('https://api.example.com');
    });

    it('should remove trailing slash', () => {
      vi.stubGlobal('window', undefined as any);
      
      process.env.API_BASE_URL = 'https://api.example.com/';
      
      const result = getWebsiteApiBaseUrl();
      expect(result).toBe('https://api.example.com');
    });

    it('should handle multiple trailing slashes', () => {
      vi.stubGlobal('window', undefined as any);
      
      process.env.API_BASE_URL = 'https://api.example.com///';
      
      const result = getWebsiteApiBaseUrl();
      // normalizeBaseUrl only removes one trailing slash
      expect(result).toBe('https://api.example.com//');
    });

    it('should handle URL with path and trailing slash', () => {
      vi.stubGlobal('window', undefined as any);
      
      process.env.API_BASE_URL = 'https://api.example.com/v1/';
      
      const result = getWebsiteApiBaseUrl();
      expect(result).toBe('https://api.example.com/v1');
    });
  });

  describe('fallback behavior', () => {
    it('should fallback to localhost in development when no env vars set', () => {
      vi.stubGlobal('window', undefined as any);
      
      process.env.NODE_ENV = 'development';
      delete process.env.API_BASE_URL;
      delete process.env.NEXT_PUBLIC_API_BASE_URL;
      delete process.env.CI;
      delete process.env.DOCKER;
      
      const result = getWebsiteApiBaseUrl();
      expect(result).toBe('http://localhost:3001');
    });

    it('should fallback to api:3000 in production when no env vars set', () => {
      vi.stubGlobal('window', undefined as any);
      
      process.env.NODE_ENV = 'production';
      delete process.env.API_BASE_URL;
      delete process.env.NEXT_PUBLIC_API_BASE_URL;
      delete process.env.CI;
      delete process.env.DOCKER;
      
      const result = getWebsiteApiBaseUrl();
      expect(result).toBe('http://api:3000');
    });
  });

  describe('test-like environment', () => {
    it('should throw error in test environment when no URL configured', () => {
      vi.stubGlobal('window', undefined as any);
      
      process.env.NODE_ENV = 'test';
      delete process.env.API_BASE_URL;
      delete process.env.NEXT_PUBLIC_API_BASE_URL;
      
      expect(() => getWebsiteApiBaseUrl()).toThrow(
        'Missing API_BASE_URL. In Docker/CI/test we do not allow falling back to localhost.'
      );
    });

    it('should throw error in CI environment when no URL configured', () => {
      vi.stubGlobal('window', undefined as any);
      
      process.env.CI = 'true';
      delete process.env.API_BASE_URL;
      delete process.env.NEXT_PUBLIC_API_BASE_URL;
      
      expect(() => getWebsiteApiBaseUrl()).toThrow(
        'Missing API_BASE_URL. In Docker/CI/test we do not allow falling back to localhost.'
      );
    });

    it('should throw error in Docker environment when no URL configured', () => {
      vi.stubGlobal('window', undefined as any);
      
      process.env.DOCKER = 'true';
      delete process.env.API_BASE_URL;
      delete process.env.NEXT_PUBLIC_API_BASE_URL;
      
      expect(() => getWebsiteApiBaseUrl()).toThrow(
        'Missing API_BASE_URL. In Docker/CI/test we do not allow falling back to localhost.'
      );
    });

    it('should throw browser-specific error in test environment when in browser', () => {
      vi.stubGlobal('window', { location: {} } as any);
      
      process.env.NODE_ENV = 'test';
      delete process.env.API_BASE_URL;
      delete process.env.NEXT_PUBLIC_API_BASE_URL;
      
      expect(() => getWebsiteApiBaseUrl()).toThrow(
        'Missing NEXT_PUBLIC_API_BASE_URL. In Docker/CI/test we do not allow falling back to localhost.'
      );
    });

    it('should work in test environment when URL is configured', () => {
      vi.stubGlobal('window', undefined as any);
      
      process.env.NODE_ENV = 'test';
      process.env.API_BASE_URL = 'https://test-api.example.com';
      
      const result = getWebsiteApiBaseUrl();
      expect(result).toBe('https://test-api.example.com');
    });
  });

  describe('empty string handling', () => {
    it('should treat empty string as not configured', () => {
      vi.stubGlobal('window', undefined as any);
      
      process.env.NODE_ENV = 'development';
      process.env.API_BASE_URL = '';
      delete process.env.NEXT_PUBLIC_API_BASE_URL;
      
      const result = getWebsiteApiBaseUrl();
      expect(result).toBe('http://localhost:3001');
    });

    it('should treat whitespace-only string as not configured', () => {
      vi.stubGlobal('window', undefined as any);
      
      process.env.NODE_ENV = 'development';
      process.env.API_BASE_URL = '   ';
      delete process.env.NEXT_PUBLIC_API_BASE_URL;
      
      const result = getWebsiteApiBaseUrl();
      expect(result).toBe('http://localhost:3001');
    });
  });
});