/**
 * Value Object: Money
 * Represents a monetary amount with currency and platform fee calculation
 */
 
import { RacingDomainValidationError } from '../errors/RacingDomainError';
import type { IValueObject } from '@core/shared/domain';

export type Currency = 'USD' | 'EUR' | 'GBP';

export interface MoneyProps {
  amount: number;
  currency: Currency;
}

export class Money implements IValueObject<MoneyProps> {
  private static readonly PLATFORM_FEE_PERCENTAGE = 0.10;

  readonly amount: number;
  readonly currency: Currency;

  private constructor(amount: number, currency: Currency) {
    this.amount = amount;
    this.currency = currency;
  }

  static create(amount: number, currency: Currency = 'USD'): Money {
    if (amount < 0) {
      throw new RacingDomainValidationError('Money amount cannot be negative');
    }
    if (!Number.isFinite(amount)) {
      throw new RacingDomainValidationError('Money amount must be a finite number');
    }
    return new Money(amount, currency);
  }

  /**
   * Calculate platform fee (10%)
   */
  calculatePlatformFee(): Money {
    const feeAmount = this.amount * Money.PLATFORM_FEE_PERCENTAGE;
    return new Money(feeAmount, this.currency);
  }

  /**
   * Calculate net amount after platform fee
   */
  calculateNetAmount(): Money {
    const platformFee = this.calculatePlatformFee();
    return new Money(this.amount - platformFee.amount, this.currency);
  }

  /**
   * Add two money amounts
   */
  add(other: Money): Money {
    if (this.currency !== other.currency) {
      throw new RacingDomainValidationError('Cannot add money with different currencies');
    }
    return new Money(this.amount + other.amount, this.currency);
  }

  /**
   * Subtract two money amounts
   */
  subtract(other: Money): Money {
    if (this.currency !== other.currency) {
      throw new RacingDomainValidationError('Cannot subtract money with different currencies');
    }
    const result = this.amount - other.amount;
    if (result < 0) {
      throw new RacingDomainValidationError('Subtraction would result in negative amount');
    }
    return new Money(result, this.currency);
  }

  /**
   * Check if this money is greater than another
   */
  isGreaterThan(other: Money): boolean {
    if (this.currency !== other.currency) {
      throw new RacingDomainValidationError('Cannot compare money with different currencies');
    }
    return this.amount > other.amount;
  }

  get props(): MoneyProps {
    return {
      amount: this.amount,
      currency: this.currency,
    };
  }

  /**
    * Check if this money equals another
    */
   equals(other: IValueObject<MoneyProps>): boolean {
     const a = this.props;
     const b = other.props;
     return a.amount === b.amount && a.currency === b.currency;
   }
}