/**
 * Domain Value Object: LeagueName
 *
 * Represents a valid league name with validation rules.
 */
 
import { RacingDomainValidationError } from '../errors/RacingDomainError';
import type { IValueObject } from '@core/shared/domain';

export interface LeagueNameValidationResult {
  valid: boolean;
  error?: string;
}

export const LEAGUE_NAME_CONSTRAINTS = {
  minLength: 3,
  maxLength: 64,
  pattern: /^[a-zA-Z0-9].*$/, // Must start with alphanumeric
  forbiddenPatterns: [
    /^\s/,      // No leading whitespace
    /\s$/,      // No trailing whitespace
    /\s{2,}/,   // No multiple consecutive spaces
  ],
} as const;

export interface LeagueNameProps {
  value: string;
}
 
export class LeagueName implements IValueObject<LeagueNameProps> {
  readonly value: string;

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

  /**
   * Validate a league name without creating the value object
   */
  static validate(value: string): LeagueNameValidationResult {
    const trimmed = value?.trim() ?? '';

    if (!trimmed) {
      return { valid: false, error: 'League name is required' };
    }

    if (trimmed.length < LEAGUE_NAME_CONSTRAINTS.minLength) {
      return {
        valid: false,
        error: `League name must be at least ${LEAGUE_NAME_CONSTRAINTS.minLength} characters`,
      };
    }

    if (trimmed.length > LEAGUE_NAME_CONSTRAINTS.maxLength) {
      return {
        valid: false,
        error: `League name must be ${LEAGUE_NAME_CONSTRAINTS.maxLength} characters or less`,
      };
    }

    if (!LEAGUE_NAME_CONSTRAINTS.pattern.test(trimmed)) {
      return {
        valid: false,
        error: 'League name must start with a letter or number',
      };
    }

    for (const forbidden of LEAGUE_NAME_CONSTRAINTS.forbiddenPatterns) {
      if (forbidden.test(value)) {
        return {
          valid: false,
          error: 'League name cannot have leading/trailing spaces or multiple consecutive spaces',
        };
      }
    }

    return { valid: true };
  }

  /**
   * Create a LeagueName from a string value
   */
  static create(value: string): LeagueName {
    const validation = this.validate(value);
    if (!validation.valid) {
      throw new RacingDomainValidationError(validation.error ?? 'Invalid league name');
    }
    return new LeagueName(value.trim());
  }

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

  /**
   * Try to create a LeagueName, returning null if invalid
   */
  static tryCreate(value: string): LeagueName | null {
    const validation = this.validate(value);
    if (!validation.valid) {
      return null;
    }
    return new LeagueName(value.trim());
  }

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