import type { ValueObject } from '@core/shared/domain/ValueObject';
import { RacingDomainValidationError } from '../errors/RacingDomainError';

/**
 * Value Object: SessionType
 *
 * Represents the type of racing session within a race event.
 * Immutable value object with domain validation.
 */
export type SessionTypeValue = 'practice' | 'qualifying' | 'q1' | 'q2' | 'q3' | 'sprint' | 'main' | 'timeTrial';

export class SessionType implements ValueObject<SessionTypeValue> {
  readonly value: SessionTypeValue;

  constructor(value: SessionTypeValue) {
    if (!value || !this.isValidSessionType(value)) {
      throw new RacingDomainValidationError(`Invalid session type: ${value}`);
    }
    this.value = value;
  }

  private isValidSessionType(value: string): value is SessionTypeValue {
    const validTypes: SessionTypeValue[] = ['practice', 'qualifying', 'q1', 'q2', 'q3', 'sprint', 'main', 'timeTrial'];
    return validTypes.includes(value as SessionTypeValue);
  }

  get props(): SessionTypeValue {
    return this.value;
  }

  equals(other: ValueObject<SessionTypeValue>): boolean {
    return this.value === other.props;
  }

  /**
   * Check if this session type counts for championship points
   */
  countsForPoints(): boolean {
    return this.value === 'main' || this.value === 'sprint';
  }

  /**
   * Check if this session type determines grid positions
   */
  determinesGrid(): boolean {
    return this.value === 'qualifying' || this.value.startsWith('q');
  }

  /**
   * Get human-readable display name
   */
  getDisplayName(): string {
    const names: Record<SessionTypeValue, string> = {
      practice: 'Practice',
      qualifying: 'Qualifying',
      q1: 'Q1',
      q2: 'Q2',
      q3: 'Q3',
      sprint: 'Sprint Race',
      main: 'Main Race',
      timeTrial: 'Time Trial',
    };
    return names[this.value];
  }

  /**
   * Get short display name for UI
   */
  getShortName(): string {
    const names: Record<SessionTypeValue, string> = {
      practice: 'P',
      qualifying: 'Q',
      q1: 'Q1',
      q2: 'Q2',
      q3: 'Q3',
      sprint: 'SPR',
      main: 'RACE',
      timeTrial: 'TT',
    };
    return names[this.value];
  }

  // Static factory methods for common types
  static practice(): SessionType {
    return new SessionType('practice');
  }

  static qualifying(): SessionType {
    return new SessionType('qualifying');
  }

  static sprint(): SessionType {
    return new SessionType('sprint');
  }

  static main(): SessionType {
    return new SessionType('main');
  }

  static timeTrial(): SessionType {
    return new SessionType('timeTrial');
  }
}