/**
 * Domain Value Object: SessionDuration
 * 
 * Represents the duration of a racing session in minutes.
 * Enforces reasonable limits for different session types.
 */

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

export interface SessionDurationProps {
  value: number;
}

export class SessionDuration implements ValueObject<SessionDurationProps> {
  readonly value: number;

  private constructor(value: number) {
    this.value = value;
  }

  static create(value: number): SessionDuration {
    if (!Number.isInteger(value) || value <= 0) {
      throw new RacingDomainValidationError('Session duration must be a positive integer');
    }

    // Enforce reasonable limits
    if (value < 15) {
      throw new RacingDomainValidationError('Session duration must be at least 15 minutes');
    }

    if (value > 240) {
      throw new RacingDomainValidationError('Session duration cannot exceed 240 minutes (4 hours)');
    }

    return new SessionDuration(value);
  }

  /**
   * Check if duration is suitable for sprint racing
   */
  isSprint(): boolean {
    return this.value >= 15 && this.value <= 45;
  }

  /**
   * Check if duration is suitable for standard racing
   */
  isStandard(): boolean {
    return this.value > 45 && this.value <= 90;
  }

  /**
   * Check if duration is suitable for endurance racing
   */
  isEndurance(): boolean {
    return this.value > 90;
  }

  /**
   * Get duration classification
   */
  getClassification(): 'sprint' | 'standard' | 'endurance' {
    if (this.isSprint()) return 'sprint';
    if (this.isStandard()) return 'standard';
    return 'endurance';
  }

  /**
   * Check if duration is within specified range
   */
  isWithinRange(min: number, max: number): boolean {
    return this.value >= min && this.value <= max;
  }

  /**
   * Get duration in hours
   */
  inHours(): number {
    return this.value / 60;
  }

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

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

  toString(): string {
    return `${this.value} minutes`;
  }

  toNumber(): number {
    return this.value;
  }
}