import { RaceRegistration } from './RaceRegistration';
import { RacingDomainValidationError } from '../errors/RacingDomainError';
import { RaceId } from './RaceId';
import { DriverId } from './DriverId';
import { RegisteredAt } from './RegisteredAt';

describe('RaceRegistration', () => {
  const validRaceId = 'race-123';
  const validDriverId = 'driver-456';
  const validDate = new Date('2023-01-01T00:00:00Z');

  describe('create', () => {
    it('should create a RaceRegistration with valid props', () => {
      const props = {
        raceId: validRaceId,
        driverId: validDriverId,
        registeredAt: validDate,
      };

      const registration = RaceRegistration.create(props);

      expect(registration.id).toBe(`${validRaceId}:${validDriverId}`);
      expect(registration.raceId.toString()).toBe(validRaceId);
      expect(registration.driverId.toString()).toBe(validDriverId);
      expect(registration.registeredAt.toDate()).toEqual(validDate);
    });

    it('should create with default registeredAt if not provided', () => {
      const props = {
        raceId: validRaceId,
        driverId: validDriverId,
      };

      const registration = RaceRegistration.create(props);

      expect(registration.registeredAt).toBeDefined();
      expect(registration.registeredAt.toDate()).toBeInstanceOf(Date);
    });

    it('should use provided id if given', () => {
      const customId = 'custom-id';
      const props = {
        id: customId,
        raceId: validRaceId,
        driverId: validDriverId,
      };

      const registration = RaceRegistration.create(props);

      expect(registration.id).toBe(customId);
    });

    it('should throw error for empty raceId', () => {
      const props = {
        raceId: '',
        driverId: validDriverId,
      };

      expect(() => RaceRegistration.create(props)).toThrow(RacingDomainValidationError);
    });

    it('should throw error for empty driverId', () => {
      const props = {
        raceId: validRaceId,
        driverId: '',
      };

      expect(() => RaceRegistration.create(props)).toThrow(RacingDomainValidationError);
    });

    it('should throw error for invalid raceId', () => {
      const props = {
        raceId: '   ',
        driverId: validDriverId,
      };

      expect(() => RaceRegistration.create(props)).toThrow(RacingDomainValidationError);
    });

    it('should throw error for invalid driverId', () => {
      const props = {
        raceId: validRaceId,
        driverId: '   ',
      };

      expect(() => RaceRegistration.create(props)).toThrow(RacingDomainValidationError);
    });
  });

  describe('entity properties', () => {
    let registration: RaceRegistration;

    beforeEach(() => {
      registration = RaceRegistration.create({
        raceId: validRaceId,
        driverId: validDriverId,
        registeredAt: validDate,
      });
    });

    it('should have readonly id', () => {
      expect(registration.id).toBe(`${validRaceId}:${validDriverId}`);
    });

    it('should have readonly raceId as RaceId', () => {
      expect(registration.raceId).toBeInstanceOf(RaceId);
      expect(registration.raceId.toString()).toBe(validRaceId);
    });

    it('should have readonly driverId as DriverId', () => {
      expect(registration.driverId).toBeInstanceOf(DriverId);
      expect(registration.driverId.toString()).toBe(validDriverId);
    });

    it('should have readonly registeredAt as RegisteredAt', () => {
      expect(registration.registeredAt).toBeInstanceOf(RegisteredAt);
      expect(registration.registeredAt.toDate()).toEqual(validDate);
    });
  });
});