import { Email } from './Email';

describe('Email', () => {
  describe('TDD - Test First', () => {
    it('should create a valid email from string', () => {
      // Arrange & Act
      const email = Email.fromString('test@example.com');

      // Assert
      expect(email.value).toBe('test@example.com');
    });

    it('should trim whitespace', () => {
      // Arrange & Act
      const email = Email.fromString('  test@example.com  ');

      // Assert
      expect(email.value).toBe('test@example.com');
    });

    it('should throw error for empty string', () => {
      // Arrange & Act & Assert
      expect(() => Email.fromString('')).toThrow('Email cannot be empty');
      expect(() => Email.fromString('   ')).toThrow('Email cannot be empty');
    });

    it('should throw error for null or undefined', () => {
      // Arrange & Act & Assert
      expect(() => Email.fromString(null as unknown as string)).toThrow('Email cannot be empty');
      expect(() => Email.fromString(undefined as unknown as string)).toThrow('Email cannot be empty');
    });

    it('should handle various email formats', () => {
      // Arrange & Act
      const email1 = Email.fromString('user@example.com');
      const email2 = Email.fromString('user.name@example.com');
      const email3 = Email.fromString('user+tag@example.co.uk');

      // Assert
      expect(email1.value).toBe('user@example.com');
      expect(email2.value).toBe('user.name@example.com');
      expect(email3.value).toBe('user+tag@example.co.uk');
    });

    it('should support equals comparison', () => {
      // Arrange
      const email1 = Email.fromString('test@example.com');
      const email2 = Email.fromString('test@example.com');
      const email3 = Email.fromString('other@example.com');

      // Assert
      expect(email1.equals(email2)).toBe(true);
      expect(email1.equals(email3)).toBe(false);
    });

    it('should support toString', () => {
      // Arrange
      const email = Email.fromString('test@example.com');

      // Assert
      expect(email.toString()).toBe('test@example.com');
    });

    it('should handle case sensitivity', () => {
      // Arrange & Act
      const email1 = Email.fromString('Test@Example.com');
      const email2 = Email.fromString('test@example.com');

      // Assert - Should preserve case but compare as-is
      expect(email1.value).toBe('Test@Example.com');
      expect(email2.value).toBe('test@example.com');
    });

    it('should handle international characters', () => {
      // Arrange & Act
      const email = Email.fromString('tëst@ëxample.com');

      // Assert
      expect(email.value).toBe('tëst@ëxample.com');
    });

    it('should handle very long emails', () => {
      // Arrange
      const longLocal = 'a'.repeat(100);
      const longDomain = 'b'.repeat(100);
      const longEmail = `${longLocal}@${longDomain}.com`;

      // Act
      const email = Email.fromString(longEmail);

      // Assert
      expect(email.value).toBe(longEmail);
    });
  });
});