/**
 * Domain Entity: Driver
 *
 * Represents a driver profile in the GridPilot platform.
 * Immutable entity with factory methods and domain validation.
 */

import { RacingDomainValidationError } from '../errors/RacingDomainError';
import type { IEntity } from '@core/shared/domain';
import { IRacingId } from '../value-objects/IRacingId';
import { DriverName } from '../value-objects/driver/DriverName';
import { CountryCode } from '../value-objects/CountryCode';
import { DriverBio } from '../value-objects/driver/DriverBio';
import { JoinedAt } from '../value-objects/JoinedAt';

export class Driver implements IEntity<string> {
  readonly id: string;
  readonly iracingId: IRacingId;
  readonly name: DriverName;
  readonly country: CountryCode;
  readonly bio: DriverBio | undefined;
  readonly joinedAt: JoinedAt;

  private constructor(props: {
    id: string;
    iracingId: IRacingId;
    name: DriverName;
    country: CountryCode;
    bio?: DriverBio;
    joinedAt: JoinedAt;
  }) {
    this.id = props.id;
    this.iracingId = props.iracingId;
    this.name = props.name;
    this.country = props.country;
    this.bio = props.bio;
    this.joinedAt = props.joinedAt;
  }

  /**
   * Factory method to create a new Driver entity
   */
  static create(props: {
    id: string;
    iracingId: string;
    name: string;
    country: string;
    bio?: string;
    joinedAt?: Date;
  }): Driver {
    if (!props.id || props.id.trim().length === 0) {
      throw new RacingDomainValidationError('Driver ID is required');
    }

    return new Driver({
      id: props.id,
      iracingId: IRacingId.create(props.iracingId),
      name: DriverName.create(props.name),
      country: CountryCode.create(props.country),
      ...(props.bio !== undefined ? { bio: DriverBio.create(props.bio) } : {}),
      joinedAt: JoinedAt.create(props.joinedAt ?? new Date()),
    });
  }

  /**
   * Create a copy with updated properties
   */
  update(props: Partial<{
    name: string;
    country: string;
    bio: string | undefined;
  }>): Driver {
    const nextName = 'name' in props ? DriverName.create(props.name!) : this.name;
    const nextCountry = 'country' in props ? CountryCode.create(props.country!) : this.country;
    const nextBio = 'bio' in props ? (props.bio ? DriverBio.create(props.bio) : undefined) : this.bio;

    return new Driver({
      id: this.id,
      iracingId: this.iracingId,
      name: nextName,
      country: nextCountry,
      ...(nextBio !== undefined ? { bio: nextBio } : {}),
      joinedAt: this.joinedAt,
    });
  }
}