/**
 * Value Object: SettlementAmount
 * Encapsulates a financial amount with validation.
 * Amounts are stored as strings to preserve precision (matches DB numeric type).
 */
export class SettlementAmount {
  private constructor(private readonly _value: string) {}

  /**
   * Create a SettlementAmount from a string value.
   * Validates that the value is a positive numeric string with up to 20 digits
   * and 8 decimal places.
   */
  static create(value: string): SettlementAmount {
    if (!value || value.trim() === '') {
      throw new Error('Settlement amount cannot be empty');
    }

    const numeric = parseFloat(value);
    if (isNaN(numeric)) {
      throw new Error(`Invalid settlement amount: "${value}" is not a valid number`);
    }

    if (numeric < 0) {
      throw new Error(`Settlement amount must be non-negative, got: ${value}`);
    }

    // Validate precision: up to 20 digits total, 8 decimal places
    const parts = value.split('.');
    const integerPart = parts[0].replace(/^-/, '');
    const decimalPart = parts[1] || '';

    if (integerPart.length > 12) {
      throw new Error(
        `Settlement amount integer part exceeds maximum 12 digits: ${integerPart.length}`,
      );
    }

    if (decimalPart.length > 8) {
      throw new Error(
        `Settlement amount decimal part exceeds maximum 8 digits: ${decimalPart.length}`,
      );
    }

    return new SettlementAmount(value);
  }

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

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

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

  /**
   * Subtract another amount and return the result.
   */
  subtract(other: SettlementAmount): SettlementAmount {
    const result = this.toNumber() - other.toNumber();
    return SettlementAmount.create(String(result));
  }

  /**
   * Add another amount and return the result.
   */
  add(other: SettlementAmount): SettlementAmount {
    const result = this.toNumber() + other.toNumber();
    return SettlementAmount.create(String(result));
  }

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

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