/**
 * Domain Entity: RaceRegistration
 *
 * Represents a registration of a driver for a specific race.
 */

import { Entity } from '@core/shared/domain/Entity';
import { RacingDomainValidationError } from '../errors/RacingDomainError';
import { DriverId } from './DriverId';
import { RaceId } from './RaceId';
import { RegisteredAt } from './RegisteredAt';

export interface RaceRegistrationProps {
   id?: string;
   raceId: string;
   driverId: string;
   registeredAt?: Date;
}

export class RaceRegistration extends Entity<string> {
    readonly raceId: RaceId;
   readonly driverId: DriverId;
   readonly registeredAt: RegisteredAt;

   private constructor(props: {
      id: string;
      raceId: RaceId;
      driverId: DriverId;
      registeredAt: RegisteredAt;
   }) {
    super(props.id);
      
      this.raceId = props.raceId;
      this.driverId = props.driverId;
      this.registeredAt = props.registeredAt;
   }

   static create(props: RaceRegistrationProps): RaceRegistration {
      RaceRegistration.validate(props);

      const raceId = RaceId.create(props.raceId);
      const driverId = DriverId.create(props.driverId);
      const registeredAt = RegisteredAt.create(props.registeredAt ?? new Date());

      const id =
         props.id && props.id.trim().length > 0
            ? props.id
            : `${raceId.toString()}:${driverId.toString()}`;

      return new RaceRegistration({
         id,
         raceId,
         driverId,
         registeredAt,
      });
   }

   static rehydrate(props: { id: string; raceId: string; driverId: string; registeredAt: Date }): RaceRegistration {
      return new RaceRegistration({
         id: props.id,
         raceId: RaceId.create(props.raceId),
         driverId: DriverId.create(props.driverId),
         registeredAt: RegisteredAt.create(props.registeredAt),
      });
   }

   private static validate(props: RaceRegistrationProps): void {
      if (!props.raceId || props.raceId.trim().length === 0) {
         throw new RacingDomainValidationError('Race ID is required');
      }

      if (!props.driverId || props.driverId.trim().length === 0) {
         throw new RacingDomainValidationError('Driver ID is required');
      }
   }

   equals(other: Entity<string>): boolean {
      if (!(other instanceof RaceRegistration)) {
         return false;
      }
      return this.id === other.id;
   }
}