import { describe, test, expect } from 'vitest';
import { CookieConfiguration } from 'apps/companion/main/automation/domain/value-objects/CookieConfiguration';

describe('CookieConfiguration', () => {
  const validTargetUrl = 'https://members-ng.iracing.com/jjwtauth/success';

  describe('domain validation', () => {
    test('should accept exact domain match', () => {
      const config = {
        name: 'test_cookie',
        value: 'test_value',
        domain: 'members-ng.iracing.com',
        path: '/',
      };

      expect(() => new CookieConfiguration(config, validTargetUrl)).not.toThrow();
    });

    test('should accept wildcard domain for subdomain match', () => {
      const config = {
        name: 'test_cookie',
        value: 'test_value',
        domain: '.iracing.com',
        path: '/',
      };

      expect(() => new CookieConfiguration(config, validTargetUrl)).not.toThrow();
    });

    test('should accept wildcard domain for base domain match', () => {
      const config = {
        name: 'test_cookie',
        value: 'test_value',
        domain: '.iracing.com',
        path: '/',
      };

      const baseUrl = 'https://iracing.com/';
      expect(() => new CookieConfiguration(config, baseUrl)).not.toThrow();
    });

    test('should match wildcard domain with multiple subdomain levels', () => {
      const config = {
        name: 'test_cookie',
        value: 'test_value',
        domain: '.iracing.com',
        path: '/',
      };

      const deepUrl = 'https://api.members-ng.iracing.com/endpoint';
      expect(() => new CookieConfiguration(config, deepUrl)).not.toThrow();
    });

    test('should throw error when domain does not match target', () => {
      const config = {
        name: 'test_cookie',
        value: 'test_value',
        domain: 'example.com',
        path: '/',
      };

      expect(() => new CookieConfiguration(config, validTargetUrl))
        .toThrow(/domain mismatch/i);
    });

    test('should throw error when wildcard domain does not match target', () => {
      const config = {
        name: 'test_cookie',
        value: 'test_value',
        domain: '.example.com',
        path: '/',
      };

      expect(() => new CookieConfiguration(config, validTargetUrl))
        .toThrow(/domain mismatch/i);
    });

    test('should throw error when subdomain does not match wildcard', () => {
      const config = {
        name: 'test_cookie',
        value: 'test_value',
        domain: '.racing.com',
        path: '/',
      };

      expect(() => new CookieConfiguration(config, validTargetUrl))
        .toThrow(/domain mismatch/i);
    });

    test('should accept cookies from related subdomains with same base domain', () => {
      const cookie = {
        name: 'XSESSIONID',
        value: 'session_value',
        domain: 'members.iracing.com',
        path: '/',
      };
      
      // Should work: members.iracing.com → members-ng.iracing.com
      // Both share base domain "iracing.com"
      expect(() =>
        new CookieConfiguration(cookie, 'https://members-ng.iracing.com/web/racing')
      ).not.toThrow();
      
      const config = new CookieConfiguration(cookie, 'https://members-ng.iracing.com/web/racing');
      expect(config.getValidatedCookie().name).toBe('XSESSIONID');
    });

    test('should reject cookies from different base domains', () => {
      const cookie = {
        name: 'SESSION',
        value: 'session_value',
        domain: 'example.com',
        path: '/',
      };
      
      // Should fail: example.com ≠ iracing.com
      expect(() =>
        new CookieConfiguration(cookie, 'https://members.iracing.com/web/racing')
      ).toThrow(/domain mismatch/i);
    });

    test('should accept cookies from exact subdomain match', () => {
      const cookie = {
        name: 'SESSION',
        value: 'session_value',
        domain: 'members-ng.iracing.com',
        path: '/',
      };
      
      // Exact match should always work
      expect(() =>
        new CookieConfiguration(cookie, 'https://members-ng.iracing.com/web/racing')
      ).not.toThrow();
    });

    test('should accept cookies between different subdomains of same base domain', () => {
      const cookie = {
        name: 'AUTH_TOKEN',
        value: 'token_value',
        domain: 'api.iracing.com',
        path: '/',
      };
      
      // Should work: api.iracing.com → members-ng.iracing.com
      expect(() =>
        new CookieConfiguration(cookie, 'https://members-ng.iracing.com/api')
      ).not.toThrow();
    });

    test('should reject subdomain cookies when base domain has insufficient parts', () => {
      const cookie = {
        name: 'TEST',
        value: 'test_value',
        domain: 'localhost',
        path: '/',
      };
      
      // Single-part domain should not match different single-part domain
      expect(() =>
        new CookieConfiguration(cookie, 'https://example/path')
      ).toThrow(/domain mismatch/i);
    });
  });

  describe('path validation', () => {
    test('should accept root path for any target path', () => {
      const config = {
        name: 'test_cookie',
        value: 'test_value',
        domain: 'members-ng.iracing.com',
        path: '/',
      };

      expect(() => new CookieConfiguration(config, validTargetUrl)).not.toThrow();
    });

    test('should accept path that is prefix of target path', () => {
      const config = {
        name: 'test_cookie',
        value: 'test_value',
        domain: 'members-ng.iracing.com',
        path: '/jjwtauth',
      };

      expect(() => new CookieConfiguration(config, validTargetUrl)).not.toThrow();
    });

    test('should throw error when path is not prefix of target path', () => {
      const config = {
        name: 'test_cookie',
        value: 'test_value',
        domain: 'members-ng.iracing.com',
        path: '/other/path',
      };

      expect(() => new CookieConfiguration(config, validTargetUrl))
        .toThrow(/path.*not valid/i);
    });

    test('should throw error when path is longer than target path', () => {
      const config = {
        name: 'test_cookie',
        value: 'test_value',
        domain: 'members-ng.iracing.com',
        path: '/jjwtauth/success/extra',
      };

      expect(() => new CookieConfiguration(config, validTargetUrl))
        .toThrow(/path.*not valid/i);
    });
  });

  describe('getValidatedCookie()', () => {
    test('should return cookie with validated domain and path', () => {
      const config = {
        name: 'test_cookie',
        value: 'test_value',
        domain: 'members-ng.iracing.com',
        path: '/',
      };

      const cookieConfig = new CookieConfiguration(config, validTargetUrl);
      const cookie = cookieConfig.getValidatedCookie();

      expect(cookie.name).toBe('test_cookie');
      expect(cookie.value).toBe('test_value');
      expect(cookie.domain).toBe('members-ng.iracing.com');
      expect(cookie.path).toBe('/');
    });

    test('should preserve all cookie properties', () => {
      const config = {
        name: 'test_cookie',
        value: 'test_value',
        domain: 'members-ng.iracing.com',
        path: '/',
        secure: true,
        httpOnly: true,
        sameSite: 'Lax' as const,
      };

      const cookieConfig = new CookieConfiguration(config, validTargetUrl);
      const cookie = cookieConfig.getValidatedCookie();

      expect(cookie.secure).toBe(true);
      expect(cookie.httpOnly).toBe(true);
      expect(cookie.sameSite).toBe('Lax');
    });
  });

  describe('edge cases', () => {
    test('should handle empty domain', () => {
      const config = {
        name: 'test_cookie',
        value: 'test_value',
        domain: '',
        path: '/',
      };

      expect(() => new CookieConfiguration(config, validTargetUrl))
        .toThrow(/domain mismatch/i);
    });

    test('should handle empty path', () => {
      const config = {
        name: 'test_cookie',
        value: 'test_value',
        domain: 'members-ng.iracing.com',
        path: '',
      };

      expect(() => new CookieConfiguration(config, validTargetUrl))
        .toThrow(/path.*not valid/i);
    });

    test('should handle malformed target URL', () => {
      const config = {
        name: 'test_cookie',
        value: 'test_value',
        domain: 'members-ng.iracing.com',
        path: '/',
      };

      expect(() => new CookieConfiguration(config, 'not-a-valid-url'))
        .toThrow();
    });
  });
});