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

export interface SeasonStewardingConfigProps {
  decisionMode: StewardingDecisionMode;
  requiredVotes?: number | undefined;
  requireDefense: boolean;
  defenseTimeLimit: number;
  voteTimeLimit: number;
  protestDeadlineHours: number;
  stewardingClosesHours: number;
  notifyAccusedOnProtest: boolean;
  notifyOnVoteRequired: boolean;
}

/**
 * Value Object: SeasonStewardingConfig
 *
 * Encapsulates stewarding configuration owned by a Season.
 * Shape intentionally mirrors LeagueStewardingFormDTO used by the wizard.
 */
export class SeasonStewardingConfig
  implements IValueObject<SeasonStewardingConfigProps>
{
  readonly decisionMode: StewardingDecisionMode;
  readonly requiredVotes?: number;
  readonly requireDefense: boolean;
  readonly defenseTimeLimit: number;
  readonly voteTimeLimit: number;
  readonly protestDeadlineHours: number;
  readonly stewardingClosesHours: number;
  readonly notifyAccusedOnProtest: boolean;
  readonly notifyOnVoteRequired: boolean;

  constructor(props: SeasonStewardingConfigProps) {
    if (!props.decisionMode) {
      throw new RacingDomainValidationError(
        'SeasonStewardingConfig.decisionMode is required',
      );
    }

    if (
      (props.decisionMode === 'steward_vote' ||
        props.decisionMode === 'member_vote' ||
        props.decisionMode === 'steward_veto' ||
        props.decisionMode === 'member_veto') &&
      (props.requiredVotes === undefined ||
        !Number.isInteger(props.requiredVotes) ||
        props.requiredVotes <= 0)
    ) {
      throw new RacingDomainValidationError(
        'SeasonStewardingConfig.requiredVotes must be a positive integer for voting/veto modes',
      );
    }

    // For non-voting modes, requiredVotes should not be provided
    if (props.decisionMode !== 'steward_vote' &&
        props.decisionMode !== 'member_vote' &&
        props.decisionMode !== 'steward_veto' &&
        props.decisionMode !== 'member_veto' &&
        props.requiredVotes !== undefined) {
      throw new RacingDomainValidationError(
        'SeasonStewardingConfig.requiredVotes should only be provided for voting/veto modes',
      );
    }

    if (!Number.isInteger(props.defenseTimeLimit) || props.defenseTimeLimit < 0) {
      throw new RacingDomainValidationError(
        'SeasonStewardingConfig.defenseTimeLimit must be a non-negative integer (hours)',
      );
    }

    if (!Number.isInteger(props.voteTimeLimit) || props.voteTimeLimit <= 0) {
      throw new RacingDomainValidationError(
        'SeasonStewardingConfig.voteTimeLimit must be a positive integer (hours)',
      );
    }

    if (
      !Number.isInteger(props.protestDeadlineHours) ||
      props.protestDeadlineHours <= 0
    ) {
      throw new RacingDomainValidationError(
        'SeasonStewardingConfig.protestDeadlineHours must be a positive integer (hours)',
      );
    }

    if (
      !Number.isInteger(props.stewardingClosesHours) ||
      props.stewardingClosesHours <= 0
    ) {
      throw new RacingDomainValidationError(
        'SeasonStewardingConfig.stewardingClosesHours must be a positive integer (hours)',
      );
    }

    this.decisionMode = props.decisionMode;
    if (props.requiredVotes !== undefined) {
      this.requiredVotes = props.requiredVotes;
    }
    this.requireDefense = props.requireDefense;
    this.defenseTimeLimit = props.defenseTimeLimit;
    this.voteTimeLimit = props.voteTimeLimit;
    this.protestDeadlineHours = props.protestDeadlineHours;
    this.stewardingClosesHours = props.stewardingClosesHours;
    this.notifyAccusedOnProtest = props.notifyAccusedOnProtest;
    this.notifyOnVoteRequired = props.notifyOnVoteRequired;
  }

  get props(): SeasonStewardingConfigProps {
    return {
      decisionMode: this.decisionMode,
      ...(this.requiredVotes !== undefined
        ? { requiredVotes: this.requiredVotes }
        : {}),
      requireDefense: this.requireDefense,
      defenseTimeLimit: this.defenseTimeLimit,
      voteTimeLimit: this.voteTimeLimit,
      protestDeadlineHours: this.protestDeadlineHours,
      stewardingClosesHours: this.stewardingClosesHours,
      notifyAccusedOnProtest: this.notifyAccusedOnProtest,
      notifyOnVoteRequired: this.notifyOnVoteRequired,
    };
  }

  equals(other: IValueObject<SeasonStewardingConfigProps>): boolean {
    const a = this.props;
    const b = other.props;
    return (
      a.decisionMode === b.decisionMode &&
      a.requiredVotes === b.requiredVotes &&
      a.requireDefense === b.requireDefense &&
      a.defenseTimeLimit === b.defenseTimeLimit &&
      a.voteTimeLimit === b.voteTimeLimit &&
      a.protestDeadlineHours === b.protestDeadlineHours &&
      a.stewardingClosesHours === b.stewardingClosesHours &&
      a.notifyAccusedOnProtest === b.notifyAccusedOnProtest &&
      a.notifyOnVoteRequired === b.notifyOnVoteRequired
    );
  }
}