import {
  CreateAccessRequestDto,
  ApproveAccessRequestDto,
  RejectAccessRequestDto,
  CreateAccessReviewDto,
  UpdateAccessReviewDto,
  ReviewAccessItemDto,
  DateRangeDto,
  RiskFiltersDto,
} from '../access.dto';

describe('Access DTOs', () => {
  describe('CreateAccessRequestDto', () => {
    it('should validate valid create access request data', () => {
      const validData = {
        resource: 'users',
        action: 'write',
        reason: 'Need to update user profiles',
        expiresAt: '2024-12-31T23:59:59.999Z',
        metadata: { priority: 'high' },
      };

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

    it('should validate minimal create access request data', () => {
      const validData = {
        resource: 'users',
        action: 'read',
      };

      const result = CreateAccessRequestDto.safeParse(validData);
      expect(result.success).toBe(true);
      if (result.success) {
        expect(result.data.resource).toBe(validData.resource);
        expect(result.data.action).toBe(validData.action);
        expect(result.data.reason).toBeUndefined();
      }
    });

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

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

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

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

  describe('ApproveAccessRequestDto', () => {
    it('should validate valid approve access request data', () => {
      const validData = {
        comments: 'Approved for project requirements',
      };

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

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

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

  describe('RejectAccessRequestDto', () => {
    it('should validate valid reject access request data', () => {
      const validData = {
        comments: 'Request denied due to security policy',
      };

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

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

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

  describe('CreateAccessReviewDto', () => {
    it('should validate valid create access review data', () => {
      const validData = {
        name: 'Quarterly Access Review',
        description: 'Review user access permissions',
        type: 'PERIODIC' as const,
        startDate: '2024-01-01T00:00:00.000Z',
        endDate: '2024-01-31T23:59:59.999Z',
      };

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

    it('should reject invalid review type', () => {
      const invalidData = {
        name: 'Review',
        type: 'INVALID' as any,
        startDate: '2024-01-01T00:00:00.000Z',
        endDate: '2024-01-31T23:59:59.999Z',
      };

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

    it('should reject invalid datetime format', () => {
      const invalidData = {
        name: 'Review',
        type: 'PERIODIC' as const,
        startDate: 'invalid-date',
        endDate: '2024-01-31T23:59:59.999Z',
      };

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

  describe('UpdateAccessReviewDto', () => {
    it('should validate valid update access review data', () => {
      const validData = {
        name: 'Updated Review Name',
        description: 'Updated description',
        startDate: '2024-02-01T00:00:00.000Z',
        endDate: '2024-02-28T23:59:59.999Z',
      };

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

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

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

  describe('ReviewAccessItemDto', () => {
    it('should validate valid review access item data', () => {
      const validData = {
        status: 'APPROVED' as const,
        comments: 'Access approved for continued role',
      };

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

    it('should allow empty comments', () => {
      const validData = {
        status: 'REVOKED' as const,
      };

      const result = ReviewAccessItemDto.safeParse(validData);
      expect(result.success).toBe(true);
      if (result.success) {
        expect(result.data.status).toBe(validData.status);
        expect(result.data.comments).toBeUndefined();
      }
    });

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

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

  describe('DateRangeDto', () => {
    it('should validate valid date range data', () => {
      const validData = {
        startDate: '2024-01-01T00:00:00.000Z',
        endDate: '2024-01-31T23:59:59.999Z',
      };

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

    it('should reject invalid start date', () => {
      const invalidData = {
        startDate: 'invalid-date',
        endDate: '2024-01-31T23:59:59.999Z',
      };

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

    it('should reject invalid end date', () => {
      const invalidData = {
        startDate: '2024-01-01T00:00:00.000Z',
        endDate: 'invalid-date',
      };

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

  describe('RiskFiltersDto', () => {
    it('should validate valid risk filters data', () => {
      const validData = {
        minScore: 25,
        maxScore: 75,
        level: 'MEDIUM' as const,
        userId: 'user-123',
      };

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

    it('should validate partial risk filters', () => {
      const validData = {
        level: 'HIGH' as const,
      };

      const result = RiskFiltersDto.safeParse(validData);
      expect(result.success).toBe(true);
      if (result.success) {
        expect(result.data.level).toBe(validData.level);
        expect(result.data.minScore).toBeUndefined();
      }
    });

    it('should reject minScore out of range', () => {
      const invalidData = {
        minScore: -1,
      };

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

    it('should reject maxScore out of range', () => {
      const invalidData = {
        maxScore: 150,
      };

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

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

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