import type { IValueObject } from '@core/shared/domain';

export type SessionStateValue =
  | 'PENDING'
  | 'IN_PROGRESS'
  | 'PAUSED'
  | 'COMPLETED'
  | 'FAILED'
  | 'STOPPED_AT_STEP_18'
  | 'AWAITING_CHECKOUT_CONFIRMATION'
  | 'CANCELLED';

const VALID_STATES: SessionStateValue[] = [
  'PENDING',
  'IN_PROGRESS',
  'PAUSED',
  'COMPLETED',
  'FAILED',
  'STOPPED_AT_STEP_18',
  'AWAITING_CHECKOUT_CONFIRMATION',
  'CANCELLED',
];

const VALID_TRANSITIONS: Record<SessionStateValue, SessionStateValue[]> = {
  PENDING: ['IN_PROGRESS', 'FAILED'],
  IN_PROGRESS: ['PAUSED', 'COMPLETED', 'FAILED', 'STOPPED_AT_STEP_18', 'AWAITING_CHECKOUT_CONFIRMATION'],
  PAUSED: ['IN_PROGRESS', 'FAILED'],
  COMPLETED: [],
  FAILED: [],
  STOPPED_AT_STEP_18: [],
  AWAITING_CHECKOUT_CONFIRMATION: ['COMPLETED', 'CANCELLED', 'FAILED'],
  CANCELLED: [],
};

export interface SessionStateProps {
  value: SessionStateValue;
}

export class SessionState implements IValueObject<SessionStateProps> {
  private readonly _value: SessionStateValue;

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

  static create(value: SessionStateValue): SessionState {
    if (!VALID_STATES.includes(value)) {
      throw new Error('Invalid session state');
    }
    return new SessionState(value);
  }

  get value(): SessionStateValue {
    return this._value;
  }

  isPending(): boolean {
    return this._value === 'PENDING';
  }

  isInProgress(): boolean {
    return this._value === 'IN_PROGRESS';
  }

  isCompleted(): boolean {
    return this._value === 'COMPLETED';
  }

  isFailed(): boolean {
    return this._value === 'FAILED';
  }

  isStoppedAtStep18(): boolean {
    return this._value === 'STOPPED_AT_STEP_18';
  }

  isAwaitingCheckoutConfirmation(): boolean {
    return this._value === 'AWAITING_CHECKOUT_CONFIRMATION';
  }

  isCancelled(): boolean {
    return this._value === 'CANCELLED';
  }

  canTransitionTo(targetState: SessionState): boolean {
    const allowedTransitions = VALID_TRANSITIONS[this._value];
    return allowedTransitions.includes(targetState._value);
  }

  isTerminal(): boolean {
    return (
      this._value === 'COMPLETED' ||
      this._value === 'FAILED' ||
      this._value === 'STOPPED_AT_STEP_18' ||
      this._value === 'CANCELLED'
    );
  }

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

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