import { ListUsersResult } from '@core/admin/application/use-cases/ListUsersUseCase';
import { AdminUser } from '@core/admin/domain/entities/AdminUser';
import { ListUsersPresenter } from './ListUsersPresenter';

describe('ListUsersPresenter', () => {
  describe('TDD - Test First', () => {
    it('should convert result to response DTO with all fields', () => {
      // Arrange - Create domain objects
      const user1 = AdminUser.create({
        id: 'user-1',
        email: 'user1@example.com',
        displayName: 'User One',
        roles: ['user'],
        status: 'active',
        createdAt: new Date('2024-01-01T00:00:00Z'),
        updatedAt: new Date('2024-01-02T00:00:00Z'),
        lastLoginAt: new Date('2024-01-03T00:00:00Z'),
        primaryDriverId: 'driver-1',
      });

      const user2 = AdminUser.create({
        id: 'user-2',
        email: 'user2@example.com',
        displayName: 'User Two',
        roles: ['owner'],
        status: 'active',
        createdAt: new Date('2024-01-04T00:00:00Z'),
        updatedAt: new Date('2024-01-05T00:00:00Z'),
        lastLoginAt: new Date('2024-01-06T00:00:00Z'),
        primaryDriverId: 'driver-2',
      });

      const result: ListUsersResult = {
        users: [user1, user2],
        total: 2,
        page: 1,
        limit: 10,
        totalPages: 1,
      };

      // Act
      const response = ListUsersPresenter.toResponse(result);

      // Assert
      expect(response.users).toHaveLength(2);
      expect(response.total).toBe(2);
      expect(response.page).toBe(1);
      expect(response.limit).toBe(10);
      expect(response.totalPages).toBe(1);

      // Check first user
      const user0 = response.users[0];
      expect(user0).toBeDefined();
      if (user0) {
        expect(user0.id).toBe('user-1');
        expect(user0.email).toBe('user1@example.com');
        expect(user0.displayName).toBe('User One');
        expect(user0.roles).toEqual(['user']);
        expect(user0.status).toBe('active');
        expect(user0.isSystemAdmin).toBe(false);
        expect(user0.createdAt).toEqual(new Date('2024-01-01T00:00:00Z'));
        expect(user0.updatedAt).toEqual(new Date('2024-01-02T00:00:00Z'));
        expect(user0.lastLoginAt).toEqual(new Date('2024-01-03T00:00:00Z'));
        expect(user0.primaryDriverId).toBe('driver-1');
      }

      // Check second user
      const user1Response = response.users[1];
      expect(user1Response).toBeDefined();
      if (user1Response) {
        expect(user1Response.id).toBe('user-2');
        expect(user1Response.email).toBe('user2@example.com');
        expect(user1Response.displayName).toBe('User Two');
        expect(user1Response.roles).toEqual(['owner']);
        expect(user1Response.status).toBe('active');
        expect(user1Response.isSystemAdmin).toBe(true);
        expect(user1Response.createdAt).toEqual(new Date('2024-01-04T00:00:00Z'));
        expect(user1Response.updatedAt).toEqual(new Date('2024-01-05T00:00:00Z'));
        expect(user1Response.lastLoginAt).toEqual(new Date('2024-01-06T00:00:00Z'));
        expect(user1Response.primaryDriverId).toBe('driver-2');
      }
    });

    it('should handle empty user list', () => {
      // Arrange
      const result: ListUsersResult = {
        users: [],
        total: 0,
        page: 1,
        limit: 10,
        totalPages: 0,
      };

      // Act
      const response = ListUsersPresenter.toResponse(result);

      // Assert
      expect(response.users).toEqual([]);
      expect(response.total).toBe(0);
      expect(response.page).toBe(1);
      expect(response.limit).toBe(10);
      expect(response.totalPages).toBe(0);
    });

    it('should handle users without optional fields', () => {
      // Arrange
      const user1 = AdminUser.create({
        id: 'user-1',
        email: 'user1@example.com',
        displayName: 'User One',
        roles: ['user'],
        status: 'active',
        createdAt: new Date('2024-01-01T00:00:00Z'),
        updatedAt: new Date('2024-01-02T00:00:00Z'),
      });

      const result: ListUsersResult = {
        users: [user1],
        total: 1,
        page: 1,
        limit: 10,
        totalPages: 1,
      };

      // Act
      const response = ListUsersPresenter.toResponse(result);

      // Assert
      expect(response.users).toHaveLength(1);
      const user0 = response.users[0];
      expect(user0).toBeDefined();
      if (user0) {
        expect(user0.lastLoginAt).toBeUndefined();
        expect(user0.primaryDriverId).toBeUndefined();
      }
    });

    it('should handle users with multiple roles', () => {
      // Arrange
      const user1 = AdminUser.create({
        id: 'user-1',
        email: 'user1@example.com',
        displayName: 'User One',
        roles: ['owner', 'admin'],
        status: 'active',
        createdAt: new Date('2024-01-01T00:00:00Z'),
        updatedAt: new Date('2024-01-02T00:00:00Z'),
      });

      const result: ListUsersResult = {
        users: [user1],
        total: 1,
        page: 1,
        limit: 10,
        totalPages: 1,
      };

      // Act
      const response = ListUsersPresenter.toResponse(result);

      // Assert
      const user0 = response.users[0];
      expect(user0).toBeDefined();
      if (user0) {
        expect(user0.roles).toEqual(['owner', 'admin']);
        expect(user0.isSystemAdmin).toBe(true);
      }
    });

    it('should handle suspended users', () => {
      // Arrange
      const user1 = AdminUser.create({
        id: 'user-1',
        email: 'user1@example.com',
        displayName: 'User One',
        roles: ['user'],
        status: 'suspended',
        createdAt: new Date('2024-01-01T00:00:00Z'),
        updatedAt: new Date('2024-01-02T00:00:00Z'),
      });

      const result: ListUsersResult = {
        users: [user1],
        total: 1,
        page: 1,
        limit: 10,
        totalPages: 1,
      };

      // Act
      const response = ListUsersPresenter.toResponse(result);

      // Assert
      const user0 = response.users[0];
      expect(user0).toBeDefined();
      if (user0) {
        expect(user0.status).toBe('suspended');
      }
    });

    it('should handle deleted users', () => {
      // Arrange
      const user1 = AdminUser.create({
        id: 'user-1',
        email: 'user1@example.com',
        displayName: 'User One',
        roles: ['user'],
        status: 'deleted',
        createdAt: new Date('2024-01-01T00:00:00Z'),
        updatedAt: new Date('2024-01-02T00:00:00Z'),
      });

      const result: ListUsersResult = {
        users: [user1],
        total: 1,
        page: 1,
        limit: 10,
        totalPages: 1,
      };

      // Act
      const response = ListUsersPresenter.toResponse(result);

      // Assert
      const user0 = response.users[0];
      expect(user0).toBeDefined();
      if (user0) {
        expect(user0.status).toBe('deleted');
      }
    });

    it('should handle pagination metadata correctly', () => {
      // Arrange
      const user1 = AdminUser.create({
        id: 'user-1',
        email: 'user1@example.com',
        displayName: 'User One',
        roles: ['user'],
        status: 'active',
        createdAt: new Date('2024-01-01T00:00:00Z'),
        updatedAt: new Date('2024-01-02T00:00:00Z'),
      });

      const result: ListUsersResult = {
        users: [user1],
        total: 15,
        page: 2,
        limit: 5,
        totalPages: 3,
      };

      // Act
      const response = ListUsersPresenter.toResponse(result);

      // Assert
      expect(response.total).toBe(15);
      expect(response.page).toBe(2);
      expect(response.limit).toBe(5);
      expect(response.totalPages).toBe(3);
    });

    it('should handle special characters in user data', () => {
      // Arrange
      const user1 = AdminUser.create({
        id: 'user-123',
        email: 'test+tag@example.co.uk',
        displayName: 'Tëst Ñame',
        roles: ['admin-steward'],
        status: 'under-review',
        createdAt: new Date('2024-01-01T00:00:00Z'),
        updatedAt: new Date('2024-01-02T00:00:00Z'),
        primaryDriverId: 'driver-123',
      });

      const result: ListUsersResult = {
        users: [user1],
        total: 1,
        page: 1,
        limit: 10,
        totalPages: 1,
      };

      // Act
      const response = ListUsersPresenter.toResponse(result);

      // Assert
      const user0 = response.users[0];
      expect(user0).toBeDefined();
      if (user0) {
        expect(user0.email).toBe('test+tag@example.co.uk');
        expect(user0.displayName).toBe('Tëst Ñame');
        expect(user0.roles).toEqual(['admin-steward']);
        expect(user0.status).toBe('under-review');
        expect(user0.primaryDriverId).toBe('driver-123');
      }
    });

    it('should handle very long display names', () => {
      // Arrange
      const longName = 'A'.repeat(100);
      const user1 = AdminUser.create({
        id: 'user-1',
        email: 'test@example.com',
        displayName: longName,
        roles: ['user'],
        status: 'active',
        createdAt: new Date('2024-01-01T00:00:00Z'),
        updatedAt: new Date('2024-01-02T00:00:00Z'),
      });

      const result: ListUsersResult = {
        users: [user1],
        total: 1,
        page: 1,
        limit: 10,
        totalPages: 1,
      };

      // Act
      const response = ListUsersPresenter.toResponse(result);

      // Assert
      const user0 = response.users[0];
      expect(user0).toBeDefined();
      if (user0) {
        expect(user0.displayName).toBe(longName);
      }
    });

    it('should handle UUID format for IDs', () => {
      // Arrange
      const uuid = '550e8400-e29b-41d4-a716-446655440000';
      const user1 = AdminUser.create({
        id: uuid,
        email: 'test@example.com',
        displayName: 'Test User',
        roles: ['user'],
        status: 'active',
        createdAt: new Date('2024-01-01T00:00:00Z'),
        updatedAt: new Date('2024-01-02T00:00:00Z'),
      });

      const result: ListUsersResult = {
        users: [user1],
        total: 1,
        page: 1,
        limit: 10,
        totalPages: 1,
      };

      // Act
      const response = ListUsersPresenter.toResponse(result);

      // Assert
      const user0 = response.users[0];
      expect(user0).toBeDefined();
      if (user0) {
        expect(user0.id).toBe(uuid);
      }
    });

    it('should handle very old and very new dates', () => {
      // Arrange
      const oldDate = new Date('1970-01-01T00:00:00Z');
      const newDate = new Date('2099-12-31T23:59:59Z');
      const user1 = AdminUser.create({
        id: 'user-1',
        email: 'test@example.com',
        displayName: 'Test User',
        roles: ['user'],
        status: 'active',
        createdAt: oldDate,
        updatedAt: newDate,
        lastLoginAt: newDate,
      });

      const result: ListUsersResult = {
        users: [user1],
        total: 1,
        page: 1,
        limit: 10,
        totalPages: 1,
      };

      // Act
      const response = ListUsersPresenter.toResponse(result);

      // Assert
      const user0 = response.users[0];
      expect(user0).toBeDefined();
      if (user0) {
        expect(user0.createdAt).toEqual(oldDate);
        expect(user0.updatedAt).toEqual(newDate);
        expect(user0.lastLoginAt).toEqual(newDate);
      }
    });
  });
});