import { DomainEntity, MoneyValue, Percentage, Quantity, UniqueID } from "core/common/domain";
import { Result } from "core/common/helpers";
import { InvoiceItemDescription } from "../../value-objects";

export interface IInvoiceItemProps {
  description: InvoiceItemDescription;
  quantity: Quantity; // Cantidad de unidades
  unitPrice: MoneyValue; // Precio unitario en la moneda de la factura
  //subtotalPrice?: MoneyValue; // Precio unitario * Cantidad
  discount: Percentage; // % descuento
  //totalPrice?: MoneyValue;
}

export interface IInvoiceItem {
  id: UniqueID;
  description: InvoiceItemDescription;
  quantity: Quantity;
  unitPrice: MoneyValue;
  subtotalPrice: MoneyValue;
  discount: Percentage;
  totalPrice: MoneyValue;
}

export class InvoiceItem extends DomainEntity<IInvoiceItemProps> implements IInvoiceItem {
  private _subtotalPrice!: MoneyValue;
  private _totalPrice!: MoneyValue;

  public static create(props: IInvoiceItemProps, id?: UniqueID): Result<InvoiceItem, Error> {
    const item = new InvoiceItem(props, id);

    // Reglas de negocio / validaciones
    // ...
    // ...

    // 🔹 Disparar evento de dominio "InvoiceItemCreatedEvent"
    //const { invoice } = props;
    //user.addDomainEvent(new InvoiceAuthenticatedEvent(id, invoice.toString()));

    return Result.ok(item);
  }

  get description(): InvoiceItemDescription {
    return this.props.description;
  }

  get quantity(): Quantity {
    return this.props.quantity;
  }

  get unitPrice(): MoneyValue {
    return this.props.unitPrice;
  }

  get subtotalPrice(): MoneyValue {
    if (!this._subtotalPrice) {
      this._subtotalPrice = this.calculateSubtotal();
    }
    return this._subtotalPrice;
  }

  get discount(): Percentage {
    return this.props.discount;
  }

  get totalPrice(): MoneyValue {
    if (!this._totalPrice) {
      this._totalPrice = this.calculateTotal();
    }
    return this._totalPrice;
  }

  getValue() {
    return this.props;
  }

  toPrimitive() {
    return {
      description: this.description.toPrimitive(),
      quantity: this.quantity.toPrimitive(),
      unit_price: this.unitPrice.toPrimitive(),
      subtotal_price: this.subtotalPrice.toPrimitive(),
      discount: this.discount.toPrimitive(),
      total_price: this.totalPrice.toPrimitive(),
    };
  }

  calculateSubtotal(): MoneyValue {
    return this.unitPrice.multiply(this.quantity.toNumber()); // Precio unitario * Cantidad
  }

  calculateTotal(): MoneyValue {
    return this.subtotalPrice.subtract(this.subtotalPrice.percentage(this.discount.toNumber()));
  }
}
