/**
 * Value Object: BreakageRate
 * Encapsulates a breakage rate as a decimal between 0 and 1 (0% - 100%).
 * Stored as a string to match DB numeric(5,4) precision.
 */
export class BreakageRate {
  private constructor(private readonly _value: string) {}

  /**
   * Create a BreakageRate from a numeric value (0..1 range, representing 0%-100%).
   */
  static create(value: number): BreakageRate {
    if (isNaN(value)) {
      throw new Error('Breakage rate must be a valid number');
    }
    if (value < 0) {
      throw new Error(`Breakage rate cannot be negative, got: ${value}`);
    }
    if (value > 1) {
      throw new Error(
        `Breakage rate cannot exceed 1.0 (100%), got: ${value}`,
      );
    }
    return new BreakageRate(String(value));
  }

  /**
   * Reconstruct from a persisted string value (no validation, trusted source).
   */
  static fromPersisted(value: string): BreakageRate {
    return new BreakageRate(value);
  }

  /**
   * Calculate breakage rate from issued and redeemed counts.
   * breakageRate = (totalIssued - totalRedeemed) / totalIssued
   */
  static calculate(totalIssued: number, totalRedeemed: number): BreakageRate {
    if (totalIssued < 0 || totalRedeemed < 0) {
      throw new Error('Counts cannot be negative');
    }
    if (totalRedeemed > totalIssued) {
      throw new Error('Redeemed count cannot exceed issued count');
    }
    if (totalIssued === 0) {
      return new BreakageRate('0');
    }
    const rate = (totalIssued - totalRedeemed) / totalIssued;
    return new BreakageRate(String(rate));
  }

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

  toNumber(): number {
    return parseFloat(this._value);
  }

  /** Return the rate as a percentage string, e.g. "25.00%" */
  toPercentageString(): string {
    return `${(this.toNumber() * 100).toFixed(2)}%`;
  }

  equals(other: BreakageRate): boolean {
    return this._value === other._value;
  }

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