import { MoneyValue, MoneyValueProps, Percentage, Quantity } from "@repo/rdx-ddd";
import { Result } from "@repo/rdx-utils";

type InvoiceAmountProps = Pick<MoneyValueProps, "value" | "currency_code">;

export class InvoiceAmount extends MoneyValue {
  public static DEFAULT_SCALE = 2;

  static create({ value, currency_code }: InvoiceAmountProps) {
    const props = {
      value: Number(value),
      scale: InvoiceAmount.DEFAULT_SCALE,
      currency_code,
    };
    return Result.ok(new InvoiceAmount(props));
  }

  static zero(currency_code: string) {
    const props = {
      value: 0,
      currency_code,
    };
    return InvoiceAmount.create(props).data;
  }

  toObjectString() {
    return {
      value: String(this.value),
      scale: String(this.scale),
      currency_code: this.currencyCode,
    };
  }

  // Ensure fluent operations keep the subclass type
  convertScale(newScale: number) {
    const mv = super.convertScale(newScale);
    const p = mv.toPrimitive();
    return new InvoiceAmount({
      value: p.value,
      currency_code: p.currency_code,
      scale: InvoiceAmount.DEFAULT_SCALE,
    });
  }

  add(addend: MoneyValue) {
    const mv = super.add(addend);
    const p = mv.toPrimitive();
    return new InvoiceAmount({
      value: p.value,
      currency_code: p.currency_code,
      scale: InvoiceAmount.DEFAULT_SCALE,
    });
  }

  subtract(subtrahend: MoneyValue) {
    const mv = super.subtract(subtrahend);
    const p = mv.toPrimitive();
    return new InvoiceAmount({
      value: p.value,
      currency_code: p.currency_code,
      scale: InvoiceAmount.DEFAULT_SCALE,
    });
  }

  multiply(multiplier: number | Quantity) {
    const mv = super.multiply(multiplier);
    const p = mv.toPrimitive();
    return new InvoiceAmount({
      value: p.value,
      currency_code: p.currency_code,
      scale: InvoiceAmount.DEFAULT_SCALE,
    });
  }

  divide(divisor: number | Quantity) {
    const mv = super.divide(divisor);
    const p = mv.toPrimitive();
    return new InvoiceAmount({
      value: p.value,
      currency_code: p.currency_code,
      scale: InvoiceAmount.DEFAULT_SCALE,
    });
  }

  percentage(percentage: number | Percentage) {
    const mv = super.percentage(percentage);
    const p = mv.toPrimitive();
    return new InvoiceAmount({
      value: p.value,
      currency_code: p.currency_code,
      scale: InvoiceAmount.DEFAULT_SCALE,
    });
  }
}
