import type { IValueObject } from '@core/shared/domain';
import { IdentityDomainValidationError } from '../errors/IdentityDomainError';

/**
 * Driving Reason Code Value Object
 * 
 * Stable machine codes for driving rating events to support:
 * - Filtering and analytics
 * - i18n translations
 * - Consistent UI explanations
 * 
 * Based on ratings-architecture-concept.md section 5.1.2
 */

export type DrivingReasonCodeValue = 
  // Performance
  | 'DRIVING_FINISH_STRENGTH_GAIN'
  | 'DRIVING_POSITIONS_GAINED_BONUS'
  | 'DRIVING_PACE_RELATIVE_GAIN'
  // Clean driving
  | 'DRIVING_INCIDENTS_PENALTY'
  | 'DRIVING_MAJOR_CONTACT_PENALTY'
  | 'DRIVING_PENALTY_INVOLVEMENT_PENALTY'
  // Reliability
  | 'DRIVING_DNS_PENALTY'
  | 'DRIVING_DNF_PENALTY'
  | 'DRIVING_DSQ_PENALTY'
  | 'DRIVING_AFK_PENALTY'
  | 'DRIVING_SEASON_ATTENDANCE_BONUS';

export interface DrivingReasonCodeProps {
  value: DrivingReasonCodeValue;
}

const VALID_REASON_CODES: DrivingReasonCodeValue[] = [
  // Performance
  'DRIVING_FINISH_STRENGTH_GAIN',
  'DRIVING_POSITIONS_GAINED_BONUS',
  'DRIVING_PACE_RELATIVE_GAIN',
  // Clean driving
  'DRIVING_INCIDENTS_PENALTY',
  'DRIVING_MAJOR_CONTACT_PENALTY',
  'DRIVING_PENALTY_INVOLVEMENT_PENALTY',
  // Reliability
  'DRIVING_DNS_PENALTY',
  'DRIVING_DNF_PENALTY',
  'DRIVING_DSQ_PENALTY',
  'DRIVING_AFK_PENALTY',
  'DRIVING_SEASON_ATTENDANCE_BONUS',
];

export class DrivingReasonCode implements IValueObject<DrivingReasonCodeProps> {
  readonly value: DrivingReasonCodeValue;

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

  static create(value: string): DrivingReasonCode {
    if (!value || value.trim().length === 0) {
      throw new IdentityDomainValidationError('DrivingReasonCode cannot be empty');
    }

    const trimmed = value.trim() as DrivingReasonCodeValue;
    
    if (!VALID_REASON_CODES.includes(trimmed)) {
      throw new IdentityDomainValidationError(
        `Invalid driving reason code: ${value}. Valid options: ${VALID_REASON_CODES.join(', ')}`
      );
    }

    return new DrivingReasonCode(trimmed);
  }

  static fromValue(value: DrivingReasonCodeValue): DrivingReasonCode {
    return new DrivingReasonCode(value);
  }

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

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

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

  /**
   * Check if this is a performance-related reason code
   */
  isPerformance(): boolean {
    return this.value === 'DRIVING_FINISH_STRENGTH_GAIN' ||
           this.value === 'DRIVING_POSITIONS_GAINED_BONUS' ||
           this.value === 'DRIVING_PACE_RELATIVE_GAIN';
  }

  /**
   * Check if this is a clean driving-related reason code
   */
  isCleanDriving(): boolean {
    return this.value === 'DRIVING_INCIDENTS_PENALTY' ||
           this.value === 'DRIVING_MAJOR_CONTACT_PENALTY' ||
           this.value === 'DRIVING_PENALTY_INVOLVEMENT_PENALTY';
  }

  /**
   * Check if this is a reliability-related reason code
   */
  isReliability(): boolean {
    return this.value === 'DRIVING_DNS_PENALTY' ||
           this.value === 'DRIVING_DNF_PENALTY' ||
           this.value === 'DRIVING_DSQ_PENALTY' ||
           this.value === 'DRIVING_AFK_PENALTY' ||
           this.value === 'DRIVING_SEASON_ATTENDANCE_BONUS';
  }

  /**
   * Check if this is a penalty (negative impact)
   */
  isPenalty(): boolean {
    return this.value.endsWith('_PENALTY');
  }

  /**
   * Check if this is a bonus (positive impact)
   */
  isBonus(): boolean {
    return this.value.endsWith('_BONUS') || this.value.endsWith('_GAIN');
  }
}