/**
 * Domain Value Object: ParticipantCount
 * 
 * Represents the number of participants in a league or race.
 * Enforces constraints based on league visibility and other business rules.
 */

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

export interface ParticipantCountProps {
  value: number;
}

export class ParticipantCount implements IValueObject<ParticipantCountProps> {
  readonly value: number;

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

  static create(value: number): ParticipantCount {
    if (!Number.isInteger(value) || value < 0) {
      throw new RacingDomainValidationError('Participant count must be a non-negative integer');
    }
    return new ParticipantCount(value);
  }

  /**
   * Validate against minimum requirements for ranked leagues
   */
  validateForRankedLeague(): { valid: boolean; error?: string } {
    if (this.value < 10) {
      return {
        valid: false,
        error: 'Ranked leagues require at least 10 participants'
      };
    }
    return { valid: true };
  }

  /**
   * Validate against minimum requirements for unranked leagues
   */
  validateForUnrankedLeague(): { valid: boolean; error?: string } {
    if (this.value < 2) {
      return {
        valid: false,
        error: 'Unranked leagues require at least 2 participants'
      };
    }
    return { valid: true };
  }

  /**
   * Validate against maximum capacity
   */
  validateAgainstMax(maxParticipants: number): { valid: boolean; error?: string } {
    if (this.value > maxParticipants) {
      return {
        valid: false,
        error: `Participant count (${this.value}) exceeds maximum capacity (${maxParticipants})`
      };
    }
    return { valid: true };
  }

  /**
   * Check if count meets minimum for given visibility type
   */
  meetsMinimumForVisibility(isRanked: boolean): boolean {
    return isRanked ? this.value >= 10 : this.value >= 2;
  }

  /**
   * Increment count by 1
   */
  increment(): ParticipantCount {
    return new ParticipantCount(this.value + 1);
  }

  /**
   * Decrement count by 1 (if > 0)
   */
  decrement(): ParticipantCount {
    if (this.value === 0) {
      throw new RacingDomainValidationError('Cannot decrement below zero');
    }
    return new ParticipantCount(this.value - 1);
  }

  /**
   * Check if count is zero
   */
  isZero(): boolean {
    return this.value === 0;
  }

  /**
   * Check if count is at least the given minimum
   */
  isAtLeast(min: number): boolean {
    return this.value >= min;
  }

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

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

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

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