import {
  CreateOrganizationDto,
  UpdateOrganizationDto,
  CreateGroupDto,
  UpdateGroupDto,
  AddGroupMemberDto,
  CreateUserProfileDto,
  UpdateUserProfileDto,
  VerificationRequestDto,
  VerifyCodeDto,
  VerifyEmailDto,
  VerifyPhoneDto,
  UpdateUserDto,
  BulkImportUsersDto,
  UserFiltersDto,
} from '../identity.dto';

describe('Identity DTOs', () => {
  describe('CreateOrganizationDto', () => {
    it('should validate valid create organization data', () => {
      const validData = {
        name: 'Test Organization',
        domain: 'test@example.com',
        parentId: 'parent-org-123',
        settings: { theme: 'dark' },
      };

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

    it('should validate minimal create organization data', () => {
      const validData = {
        name: 'Test Organization',
      };

      const result = CreateOrganizationDto.safeParse(validData);
      expect(result.success).toBe(true);
      if (result.success) {
        expect(result.data.name).toBe(validData.name);
        expect(result.data.domain).toBeUndefined();
        expect(result.data.parentId).toBeUndefined();
        expect(result.data.settings).toBeUndefined();
      }
    });

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

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

    it('should accept domain as string', () => {
      const validData = {
        name: 'Test Organization',
        domain: 'example.com',
      };

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

  describe('UpdateOrganizationDto', () => {
    it('should validate valid update organization data', () => {
      const validData = {
        name: 'Updated Organization',
        domain: 'updated@example.com',
        parentId: null,
        settings: { theme: 'light' },
        isActive: true,
      };

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

    it('should allow partial updates', () => {
      const validData = {
        name: 'Updated Name Only',
      };

      const result = UpdateOrganizationDto.safeParse(validData);
      expect(result.success).toBe(true);
      if (result.success) {
        expect(result.data.name).toBe(validData.name);
        expect(result.data.domain).toBeUndefined();
      }
    });
  });

  describe('CreateGroupDto', () => {
    it('should validate valid create group data', () => {
      const validData = {
        name: 'Test Group',
        organizationId: 'org-123',
        description: 'A test group',
      };

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

    it('should validate minimal create group data', () => {
      const validData = {
        name: 'Test Group',
      };

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

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

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

  describe('AddGroupMemberDto', () => {
    it('should validate valid add group member data', () => {
      const validData = {
        userId: 'user-123',
        role: 'admin' as const,
        expiresAt: '2024-12-31T23:59:59.999Z',
      };

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

    it('should default role to member', () => {
      const validData = {
        userId: 'user-123',
      };

      const result = AddGroupMemberDto.safeParse(validData);
      expect(result.success).toBe(true);
      if (result.success) {
        expect(result.data.role).toBe('member');
      }
    });

    it('should reject invalid role', () => {
      const invalidData = {
        userId: 'user-123',
        role: 'invalid-role' as any,
      };

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

  describe('CreateUserProfileDto', () => {
    it('should validate valid create user profile data', () => {
      const validData = {
        firstName: 'John',
        lastName: 'Doe',
        phone: '+1234567890',
        avatarUrl: 'https://example.com/avatar.jpg',
        customFields: { department: 'IT' },
        preferences: { theme: 'dark' },
        metadata: { source: 'web' },
      };

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

    it('should allow empty profile', () => {
      const validData = {};

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

    it('should reject invalid avatar URL', () => {
      const invalidData = {
        avatarUrl: 'invalid-url',
      };

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

  describe('VerificationRequestDto', () => {
    it('should validate valid verification request', () => {
      const validData = {
        type: 'EMAIL' as const,
        method: 'magic-link',
        metadata: { redirectUrl: 'https://example.com' },
      };

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

    it('should reject invalid verification type', () => {
      const invalidData = {
        type: 'INVALID' as any,
      };

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

  describe('VerifyCodeDto', () => {
    it('should validate valid verify code data', () => {
      const validData = {
        token: 'verification-token-123',
        code: '123456',
      };

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

    it('should allow verify code without code', () => {
      const validData = {
        token: 'verification-token-123',
      };

      const result = VerifyCodeDto.safeParse(validData);
      expect(result.success).toBe(true);
      if (result.success) {
        expect(result.data.code).toBeUndefined();
      }
    });

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

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

  describe('VerifyPhoneDto', () => {
    it('should validate valid verify phone data', () => {
      const validData = {
        token: 'verification-token-123',
        code: '1234',
      };

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

    it('should reject code shorter than 4 characters', () => {
      const invalidData = {
        token: 'verification-token-123',
        code: '123',
      };

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

  describe('UpdateUserDto', () => {
    it('should validate valid update user data', () => {
      const validData = {
        username: 'newusername',
        email: 'new@example.com',
        isActive: true,
        organizationId: 'org-123',
      };

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

    it('should allow partial updates', () => {
      const validData = {
        isActive: false,
      };

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

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

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

  describe('BulkImportUsersDto', () => {
    it('should validate valid bulk import data', () => {
      const validData = {
        organizationId: 'org-123',
        users: [
          {
            email: 'user1@example.com',
            username: 'user1',
            firstName: 'John',
            lastName: 'Doe',
            phone: '+1234567890',
          },
          {
            email: 'user2@example.com',
          },
        ],
      };

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

    it('should reject invalid email in users array', () => {
      const invalidData = {
        users: [
          {
            email: 'invalid-email',
          },
        ],
      };

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

  describe('UserFiltersDto', () => {
    it('should validate valid user filters', () => {
      const validData = {
        organizationId: 'org-123',
        isActive: true,
        emailVerified: false,
        search: 'john',
        skip: 10,
        take: 50,
      };

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

    it('should apply defaults for pagination', () => {
      const validData = {
        search: 'john',
      };

      const result = UserFiltersDto.safeParse(validData);
      expect(result.success).toBe(true);
      if (result.success) {
        expect(result.data.skip).toBe(0);
        expect(result.data.take).toBe(20);
      }
    });

    it('should reject take value over 100', () => {
      const invalidData = {
        take: 101,
      };

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