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

export interface CheckoutPriceProps {
  amountUsd: number;
}

export class CheckoutPrice implements IValueObject<CheckoutPriceProps> {
  private constructor(private readonly amountUsd: number) {
    if (amountUsd < 0) {
      throw new Error('Price cannot be negative');
    }
    if (amountUsd > 10000) {
      throw new Error('Price exceeds maximum of $10,000');
    }
  }

  static fromString(priceStr: string): CheckoutPrice {
    const trimmed = priceStr.trim();

    if (!trimmed.startsWith('$')) {
      throw new Error('Invalid price format: missing dollar sign');
    }

    const dollarSignCount = (trimmed.match(/\$/g) || []).length;
    if (dollarSignCount > 1) {
      throw new Error('Invalid price format: multiple dollar signs');
    }

    const numericPart = trimmed.substring(1).replace(/,/g, '');

    if (numericPart === '') {
      throw new Error('Invalid price format: no numeric value');
    }

    const amount = parseFloat(numericPart);

    if (isNaN(amount)) {
      throw new Error('Invalid price format: not a valid number');
    }

    return new CheckoutPrice(amount);
  }

  /**
   * Factory for a neutral/zero checkout price.
   * Used when no explicit price can be extracted from the DOM.
   */
  static zero(): CheckoutPrice {
    return new CheckoutPrice(0);
  }

  toDisplayString(): string {
    return `$${this.amountUsd.toFixed(2)}`;
  }

  getAmount(): number {
    return this.amountUsd;
  }

  isZero(): boolean {
    return this.amountUsd < 0.001;
  }

  get props(): CheckoutPriceProps {
    return {
      amountUsd: this.amountUsd,
    };
  }

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