/**
 * Domain Value Object: LeagueVisibility
 *
 * Represents the visibility and ranking status of a league.
 *
 * - 'ranked' (public): Competitive leagues visible to everyone, affects driver ratings.
 *   Requires minimum 10 players to ensure competitive integrity.
 * - 'unranked' (private): Casual leagues for friends/private groups, no rating impact.
 *   Can have any number of players.
 */
 
import type { IValueObject } from '@core/shared/domain';
import { RacingDomainValidationError } from '../errors/RacingDomainError';

export type LeagueVisibilityType = 'ranked' | 'unranked';

export interface LeagueVisibilityConstraints {
  readonly minDrivers: number;
  readonly isPubliclyVisible: boolean;
  readonly affectsRatings: boolean;
  readonly requiresApproval: boolean;
}

const VISIBILITY_CONSTRAINTS: Record<LeagueVisibilityType, LeagueVisibilityConstraints> = {
  ranked: {
    minDrivers: 10,
    isPubliclyVisible: true,
    affectsRatings: true,
    requiresApproval: false, // Anyone can join public leagues
  },
  unranked: {
    minDrivers: 2,
    isPubliclyVisible: false,
    affectsRatings: false,
    requiresApproval: true, // Private leagues require invite/approval
  },
};

export interface LeagueVisibilityProps {
  type: LeagueVisibilityType;
}
 
export class LeagueVisibility implements IValueObject<LeagueVisibilityProps> {
  readonly type: LeagueVisibilityType;
  readonly constraints: LeagueVisibilityConstraints;

  private constructor(type: LeagueVisibilityType) {
    this.type = type;
    this.constraints = VISIBILITY_CONSTRAINTS[type];
  }

  static ranked(): LeagueVisibility {
    return new LeagueVisibility('ranked');
  }

  static unranked(): LeagueVisibility {
    return new LeagueVisibility('unranked');
  }

  static fromString(value: string): LeagueVisibility {
    // Support both old ('public'/'private') and new ('ranked'/'unranked') terminology
    if (value === 'ranked' || value === 'public') {
      return LeagueVisibility.ranked();
    }
    if (value === 'unranked' || value === 'private') {
      return LeagueVisibility.unranked();
    }
    throw new RacingDomainValidationError(`Invalid league visibility: ${value}`);
  }

  /**
   * Validates that the given driver count meets the minimum requirement
   * for this visibility type.
   */
  validateDriverCount(driverCount: number): { valid: boolean; error?: string } {
    if (driverCount < this.constraints.minDrivers) {
      return {
        valid: false,
        error: `${this.type === 'ranked' ? 'Ranked' : 'Unranked'} leagues require at least ${this.constraints.minDrivers} drivers`,
      };
    }
    return { valid: true };
  }

  /**
   * Returns true if this is a ranked/public league
   */
  isRanked(): boolean {
    return this.type === 'ranked';
  }

  /**
   * Returns true if this is an unranked/private league
   */
  isUnranked(): boolean {
    return this.type === 'unranked';
  }


  /**
   * Convert to string for serialization
   */
  toString(): LeagueVisibilityType {
    return this.type;
  }

  get props(): LeagueVisibilityProps {
    return { type: this.type };
  }

  /**
   * For backward compatibility with existing 'public'/'private' terminology
   */
  toLegacyString(): 'public' | 'private' {
    return this.type === 'ranked' ? 'public' : 'private';
  }

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

// Export constants for validation
export const MIN_RANKED_LEAGUE_DRIVERS = VISIBILITY_CONSTRAINTS.ranked.minDrivers;
export const MIN_UNRANKED_LEAGUE_DRIVERS = VISIBILITY_CONSTRAINTS.unranked.minDrivers;