/**
 * Domain Entity: Team
 *
 * Represents a racing team in the GridPilot platform.
 * Implements the shared IEntity<string> contract and encapsulates
 * basic invariants around identity and core properties.
 */

import type { IEntity } from '@core/shared/domain';
import { RacingDomainValidationError } from '../errors/RacingDomainError';
import { TeamName } from '../value-objects/TeamName';
import { TeamTag } from '../value-objects/TeamTag';
import { TeamDescription } from '../value-objects/TeamDescription';
import { DriverId } from './DriverId';
import { LeagueId } from './LeagueId';
import { TeamCreatedAt } from '../value-objects/TeamCreatedAt';

export class Team implements IEntity<string> {
  readonly id: string;
  readonly name: TeamName;
  readonly tag: TeamTag;
  readonly description: TeamDescription;
  readonly ownerId: DriverId;
  readonly leagues: LeagueId[];
  readonly createdAt: TeamCreatedAt;

  private constructor(props: {
    id: string;
    name: TeamName;
    tag: TeamTag;
    description: TeamDescription;
    ownerId: DriverId;
    leagues: LeagueId[];
    createdAt: TeamCreatedAt;
  }) {
    this.id = props.id;
    this.name = props.name;
    this.tag = props.tag;
    this.description = props.description;
    this.ownerId = props.ownerId;
    this.leagues = props.leagues;
    this.createdAt = props.createdAt;
  }

  /**
   * Factory method to create a new Team entity.
   */
  static create(props: {
    id: string;
    name: string;
    tag: string;
    description: string;
    ownerId: string;
    leagues: string[];
    createdAt?: Date;
  }): Team {
    if (!props.id || props.id.trim().length === 0) {
      throw new RacingDomainValidationError('Team ID is required');
    }

    if (!Array.isArray(props.leagues)) {
      throw new RacingDomainValidationError('Team leagues must be an array');
    }

    return new Team({
      id: props.id,
      name: TeamName.create(props.name),
      tag: TeamTag.create(props.tag),
      description: TeamDescription.create(props.description),
      ownerId: DriverId.create(props.ownerId),
      leagues: props.leagues.map(leagueId => LeagueId.create(leagueId)),
      createdAt: TeamCreatedAt.create(props.createdAt ?? new Date()),
    });
  }

  /**
   * Create a copy with updated properties.
   */
  update(props: Partial<{
    name: string;
    tag: string;
    description: string;
    ownerId: string;
    leagues: string[];
  }>): Team {
    const nextName = 'name' in props ? TeamName.create(props.name!) : this.name;
    const nextTag = 'tag' in props ? TeamTag.create(props.tag!) : this.tag;
    const nextDescription = 'description' in props ? TeamDescription.create(props.description!) : this.description;
    const nextOwnerId = 'ownerId' in props ? DriverId.create(props.ownerId!) : this.ownerId;
    const nextLeagues = 'leagues' in props ? props.leagues!.map(leagueId => LeagueId.create(leagueId)) : this.leagues;

    return new Team({
      id: this.id,
      name: nextName,
      tag: nextTag,
      description: nextDescription,
      ownerId: nextOwnerId,
      leagues: nextLeagues,
      createdAt: this.createdAt,
    });
  }

}