import type { IValueObject } from '@core/shared/domain';

/**
 * Incident types that can occur during a race
 */
export type IncidentType =
  | 'track_limits'        // Driver went off track and gained advantage
  | 'contact'             // Physical contact with another car
  | 'unsafe_rejoin'       // Unsafe rejoining of the track
  | 'aggressive_driving'  // Aggressive defensive or overtaking maneuvers
  | 'false_start'         // Started before green flag
  | 'collision'           // Major collision involving multiple cars
  | 'spin'                // Driver spun out
  | 'mechanical'          // Mechanical failure (not driver error)
  | 'other';              // Other incident types

/**
 * Individual incident record
 */
export interface IncidentRecord {
  type: IncidentType;
  lap: number;
  description?: string;
  penaltyPoints?: number; // Points deducted for this incident
}

/**
 * Value Object: RaceIncidents
 *
 * Encapsulates all incidents that occurred during a driver's race.
 * Provides methods to calculate total penalty points and incident severity.
 */
export class RaceIncidents implements IValueObject<IncidentRecord[]> {
  private readonly incidents: IncidentRecord[];

  constructor(incidents: IncidentRecord[] = []) {
    this.incidents = [...incidents];
  }

  get props(): IncidentRecord[] {
    return [...this.incidents];
  }

  /**
   * Add a new incident
   */
  addIncident(incident: IncidentRecord): RaceIncidents {
    return new RaceIncidents([...this.incidents, incident]);
  }

  /**
   * Get all incidents
   */
  getAllIncidents(): IncidentRecord[] {
    return [...this.incidents];
  }

  /**
   * Get total number of incidents
   */
  getTotalCount(): number {
    return this.incidents.length;
  }

  /**
   * Get total penalty points from all incidents
   */
  getTotalPenaltyPoints(): number {
    return this.incidents.reduce((total, incident) => total + (incident.penaltyPoints || 0), 0);
  }

  /**
   * Get incidents by type
   */
  getIncidentsByType(type: IncidentType): IncidentRecord[] {
    return this.incidents.filter(incident => incident.type === type);
  }

  /**
   * Check if driver had any incidents
   */
  hasIncidents(): boolean {
    return this.incidents.length > 0;
  }

  /**
   * Check if driver had a clean race (no incidents)
   */
  isClean(): boolean {
    return this.incidents.length === 0;
  }

  // Removed getSeverityScore, getSummary, and getIncidentTypeLabel to eliminate static data in core

  equals(other: IValueObject<IncidentRecord[]>): boolean {
    const otherIncidents = other.props;
    if (this.incidents.length !== otherIncidents.length) {
      return false;
    }

    // Sort both arrays and compare
    const sortedThis = [...this.incidents].sort((a, b) => a.lap - b.lap);
    const sortedOther = [...otherIncidents].sort((a, b) => a.lap - b.lap);

    return sortedThis.every((incident, index) => {
      const otherIncident = sortedOther[index];
      return incident.type === otherIncident.type &&
             incident.lap === otherIncident.lap &&
             incident.description === otherIncident.description &&
             incident.penaltyPoints === otherIncident.penaltyPoints;
    });
  }

}