import {
  RegisterDto,
  LoginDto,
  RefreshTokenDto,
  ChangePasswordDto,
} from '../auth.dto';

describe('Auth DTOs', () => {
  describe('RegisterDto', () => {
    it('should validate valid registration data', () => {
      const validData = {
        email: 'test@example.com',
        password: 'StrongPass123!',
        username: 'testuser',
      };

      const result = RegisterDto.safeParse(validData);
      expect(result.success).toBe(true);
      if (result.success) {
        expect(result.data).toEqual(validData);
      }
    });

    it('should validate registration data without username', () => {
      const validData = {
        email: 'test@example.com',
        password: 'StrongPass123!',
      };

      const result = RegisterDto.safeParse(validData);
      expect(result.success).toBe(true);
      if (result.success) {
        expect(result.data.email).toBe(validData.email);
        expect(result.data.password).toBe(validData.password);
        expect(result.data.username).toBeUndefined();
      }
    });

    it('should reject invalid email', () => {
      const invalidData = {
        email: 'invalid-email',
        password: 'StrongPass123!',
      };

      const result = RegisterDto.safeParse(invalidData);
      expect(result.success).toBe(false);
      if (!result.success) {
        expect(result.error.issues[0].path).toContain('email');
        expect(result.error.issues[0].message).toContain('Invalid email format');
      }
    });

    it('should reject password without uppercase letter', () => {
      const invalidData = {
        email: 'test@example.com',
        password: 'strongpass123!',
      };

      const result = RegisterDto.safeParse(invalidData);
      expect(result.success).toBe(false);
      if (!result.success) {
        expect(result.error.issues[0].path).toContain('password');
        expect(result.error.issues[0].message).toContain('uppercase letter');
      }
    });

    it('should reject password without lowercase letter', () => {
      const invalidData = {
        email: 'test@example.com',
        password: 'STRONGPASS123!',
      };

      const result = RegisterDto.safeParse(invalidData);
      expect(result.success).toBe(false);
      if (!result.success) {
        expect(result.error.issues[0].path).toContain('password');
        expect(result.error.issues[0].message).toContain('lowercase letter');
      }
    });

    it('should reject password without number', () => {
      const invalidData = {
        email: 'test@example.com',
        password: 'StrongPass!',
      };

      const result = RegisterDto.safeParse(invalidData);
      expect(result.success).toBe(false);
      if (!result.success) {
        expect(result.error.issues[0].path).toContain('password');
        expect(result.error.issues[0].message).toContain('number');
      }
    });

    it('should reject password without special character', () => {
      const invalidData = {
        email: 'test@example.com',
        password: 'StrongPass123',
      };

      const result = RegisterDto.safeParse(invalidData);
      expect(result.success).toBe(false);
      if (!result.success) {
        expect(result.error.issues[0].path).toContain('password');
        expect(result.error.issues[0].message).toContain('special character');
      }
    });

    it('should reject password shorter than 8 characters', () => {
      const invalidData = {
        email: 'test@example.com',
        password: 'Str123!',
      };

      const result = RegisterDto.safeParse(invalidData);
      expect(result.success).toBe(false);
      if (!result.success) {
        expect(result.error.issues[0].path).toContain('password');
        expect(result.error.issues[0].message).toContain('at least 8 characters');
      }
    });

    it('should reject username shorter than 3 characters', () => {
      const invalidData = {
        email: 'test@example.com',
        password: 'StrongPass123!',
        username: 'ab',
      };

      const result = RegisterDto.safeParse(invalidData);
      expect(result.success).toBe(false);
      if (!result.success) {
        expect(result.error.issues[0].path).toContain('username');
      }
    });

    it('should reject username longer than 50 characters', () => {
      const longUsername = 'a'.repeat(51);
      const invalidData = {
        email: 'test@example.com',
        password: 'StrongPass123!',
        username: longUsername,
      };

      const result = RegisterDto.safeParse(invalidData);
      expect(result.success).toBe(false);
      if (!result.success) {
        expect(result.error.issues[0].path).toContain('username');
      }
    });
  });

  describe('LoginDto', () => {
    it('should validate valid login data', () => {
      const validData = {
        email: 'test@example.com',
        password: 'password123',
      };

      const result = LoginDto.safeParse(validData);
      expect(result.success).toBe(true);
      if (result.success) {
        expect(result.data).toEqual(validData);
      }
    });

    it('should reject invalid email', () => {
      const invalidData = {
        email: 'invalid-email',
        password: 'password123',
      };

      const result = LoginDto.safeParse(invalidData);
      expect(result.success).toBe(false);
      if (!result.success) {
        expect(result.error.issues[0].path).toContain('email');
      }
    });

    it('should reject empty password', () => {
      const invalidData = {
        email: 'test@example.com',
        password: '',
      };

      const result = LoginDto.safeParse(invalidData);
      expect(result.success).toBe(false);
      if (!result.success) {
        expect(result.error.issues[0].path).toContain('password');
        expect(result.error.issues[0].message).toContain('required');
      }
    });
  });

  describe('RefreshTokenDto', () => {
    it('should validate valid refresh token data', () => {
      const validData = {
        refreshToken: 'valid-refresh-token-123',
      };

      const result = RefreshTokenDto.safeParse(validData);
      expect(result.success).toBe(true);
      if (result.success) {
        expect(result.data).toEqual(validData);
      }
    });

    it('should reject empty refresh token', () => {
      const invalidData = {
        refreshToken: '',
      };

      const result = RefreshTokenDto.safeParse(invalidData);
      expect(result.success).toBe(false);
      if (!result.success) {
        expect(result.error.issues[0].path).toContain('refreshToken');
        expect(result.error.issues[0].message).toContain('required');
      }
    });
  });

  describe('ChangePasswordDto', () => {
    it('should validate valid change password data', () => {
      const validData = {
        currentPassword: 'CurrentPass123!',
        newPassword: 'NewStrongPass456!',
      };

      const result = ChangePasswordDto.safeParse(validData);
      expect(result.success).toBe(true);
      if (result.success) {
        expect(result.data).toEqual(validData);
      }
    });

    it('should reject empty current password', () => {
      const invalidData = {
        currentPassword: '',
        newPassword: 'NewStrongPass456!',
      };

      const result = ChangePasswordDto.safeParse(invalidData);
      expect(result.success).toBe(false);
      if (!result.success) {
        expect(result.error.issues[0].path).toContain('currentPassword');
        expect(result.error.issues[0].message).toContain('required');
      }
    });

    it('should reject weak new password', () => {
      const invalidData = {
        currentPassword: 'CurrentPass123!',
        newPassword: 'weak',
      };

      const result = ChangePasswordDto.safeParse(invalidData);
      expect(result.success).toBe(false);
      if (!result.success) {
        expect(result.error.issues[0].path).toContain('newPassword');
      }
    });

    it('should validate strong new password', () => {
      const validData = {
        currentPassword: 'CurrentPass123!',
        newPassword: 'VeryStrongNewPass999!',
      };

      const result = ChangePasswordDto.safeParse(validData);
      expect(result.success).toBe(true);
    });
  });
});