import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import {
  getBaseDomain,
  getCurrentSubdomain,
  isRootDomain,
  isPlatformDomain,
  isBusinessSubdomain,
  buildSubdomainUrl,
  getCookieDomain,
  getWebSocketUrl,
} from '../domain';

// Helper to mock window.location
const mockLocation = (hostname: string, protocol = 'https:', port = '') => {
  Object.defineProperty(window, 'location', {
    value: {
      hostname,
      protocol,
      port,
    },
    writable: true,
  });
};

describe('domain utilities', () => {
  describe('getBaseDomain', () => {
    it('returns localhost for localhost', () => {
      mockLocation('localhost');
      expect(getBaseDomain()).toBe('localhost');
    });

    it('returns localhost for 127.0.0.1', () => {
      mockLocation('127.0.0.1');
      expect(getBaseDomain()).toBe('localhost');
    });

    it('returns base domain for two-part hostname', () => {
      mockLocation('lvh.me');
      expect(getBaseDomain()).toBe('lvh.me');
    });

    it('extracts base domain from subdomain', () => {
      mockLocation('platform.lvh.me');
      expect(getBaseDomain()).toBe('lvh.me');
    });

    it('extracts base domain from production subdomain', () => {
      mockLocation('demo.smoothschedule.com');
      expect(getBaseDomain()).toBe('smoothschedule.com');
    });

    it('handles deeply nested subdomains', () => {
      mockLocation('api.v2.smoothschedule.com');
      expect(getBaseDomain()).toBe('smoothschedule.com');
    });
  });

  describe('getCurrentSubdomain', () => {
    it('returns null for localhost', () => {
      mockLocation('localhost');
      expect(getCurrentSubdomain()).toBeNull();
    });

    it('returns null for 127.0.0.1', () => {
      mockLocation('127.0.0.1');
      expect(getCurrentSubdomain()).toBeNull();
    });

    it('returns null for root domain', () => {
      mockLocation('lvh.me');
      expect(getCurrentSubdomain()).toBeNull();
    });

    it('returns subdomain for platform.lvh.me', () => {
      mockLocation('platform.lvh.me');
      expect(getCurrentSubdomain()).toBe('platform');
    });

    it('returns subdomain for demo.smoothschedule.com', () => {
      mockLocation('demo.smoothschedule.com');
      expect(getCurrentSubdomain()).toBe('demo');
    });

    it('returns first part for deeply nested subdomains', () => {
      mockLocation('api.v2.smoothschedule.com');
      expect(getCurrentSubdomain()).toBe('api');
    });
  });

  describe('isRootDomain', () => {
    it('returns true for localhost', () => {
      mockLocation('localhost');
      expect(isRootDomain()).toBe(true);
    });

    it('returns true for 127.0.0.1', () => {
      mockLocation('127.0.0.1');
      expect(isRootDomain()).toBe(true);
    });

    it('returns true for two-part domain', () => {
      mockLocation('lvh.me');
      expect(isRootDomain()).toBe(true);
    });

    it('returns false for subdomain', () => {
      mockLocation('platform.lvh.me');
      expect(isRootDomain()).toBe(false);
    });
  });

  describe('isPlatformDomain', () => {
    it('returns true for platform subdomain', () => {
      mockLocation('platform.lvh.me');
      expect(isPlatformDomain()).toBe(true);
    });

    it('returns true for platform.smoothschedule.com', () => {
      mockLocation('platform.smoothschedule.com');
      expect(isPlatformDomain()).toBe(true);
    });

    it('returns false for other subdomains', () => {
      mockLocation('demo.lvh.me');
      expect(isPlatformDomain()).toBe(false);
    });

    it('returns false for root domain', () => {
      mockLocation('lvh.me');
      expect(isPlatformDomain()).toBe(false);
    });

    it('returns false for localhost', () => {
      mockLocation('localhost');
      expect(isPlatformDomain()).toBe(false);
    });
  });

  describe('isBusinessSubdomain', () => {
    it('returns true for business subdomain', () => {
      mockLocation('demo.lvh.me');
      expect(isBusinessSubdomain()).toBe(true);
    });

    it('returns true for custom business subdomain', () => {
      mockLocation('acme-corp.smoothschedule.com');
      expect(isBusinessSubdomain()).toBe(true);
    });

    it('returns false for platform subdomain', () => {
      mockLocation('platform.lvh.me');
      expect(isBusinessSubdomain()).toBe(false);
    });

    it('returns false for api subdomain', () => {
      mockLocation('api.lvh.me');
      expect(isBusinessSubdomain()).toBe(false);
    });

    it('returns false for root domain', () => {
      mockLocation('lvh.me');
      expect(isBusinessSubdomain()).toBe(false);
    });

    it('returns false for localhost', () => {
      mockLocation('localhost');
      expect(isBusinessSubdomain()).toBe(false);
    });
  });

  describe('buildSubdomainUrl', () => {
    it('builds URL with subdomain in dev', () => {
      mockLocation('lvh.me', 'http:', '5173');
      const url = buildSubdomainUrl('platform');
      expect(url).toBe('http://platform.lvh.me:5173/');
    });

    it('builds URL with custom path', () => {
      mockLocation('lvh.me', 'http:', '5173');
      const url = buildSubdomainUrl('demo', '/dashboard');
      expect(url).toBe('http://demo.lvh.me:5173/dashboard');
    });

    it('builds root URL when subdomain is null', () => {
      mockLocation('lvh.me', 'http:', '5173');
      const url = buildSubdomainUrl(null);
      expect(url).toBe('http://lvh.me:5173/');
    });

    it('builds production URL without port', () => {
      mockLocation('smoothschedule.com', 'https:', '');
      const url = buildSubdomainUrl('demo');
      expect(url).toBe('https://demo.smoothschedule.com/');
    });
  });

  describe('getCookieDomain', () => {
    it('returns localhost for localhost', () => {
      mockLocation('localhost');
      expect(getCookieDomain()).toBe('localhost');
    });

    it('returns dotted domain for lvh.me', () => {
      mockLocation('platform.lvh.me');
      expect(getCookieDomain()).toBe('.lvh.me');
    });

    it('returns dotted domain for production', () => {
      mockLocation('demo.smoothschedule.com');
      expect(getCookieDomain()).toBe('.smoothschedule.com');
    });
  });

  describe('getWebSocketUrl', () => {
    it('returns ws URL for development http', () => {
      mockLocation('lvh.me', 'http:', '5173');
      const url = getWebSocketUrl('calendar');
      expect(url).toBe('ws://lvh.me:8000/ws/calendar');
    });

    it('returns wss URL for https', () => {
      mockLocation('smoothschedule.com', 'https:', '');
      const url = getWebSocketUrl('calendar');
      expect(url).toBe('wss://smoothschedule.com/ws/calendar');
    });

    it('includes port 8000 for localhost', () => {
      mockLocation('localhost', 'http:', '5173');
      const url = getWebSocketUrl('');
      expect(url).toBe('ws://localhost:8000/ws/');
    });

    it('excludes port for production', () => {
      mockLocation('smoothschedule.com', 'https:', '');
      const url = getWebSocketUrl('events');
      expect(url).not.toContain(':8000');
    });
  });
});
