import { JsonTaxCatalogProvider } from "@erp/core";
import { MapperParamsType, SequelizeDomainMapper, Tax } from "@erp/core/api";
import { UniqueID, ValidationErrorDetail } from "@repo/rdx-ddd";

import { Result } from "@repo/rdx-utils";
import { CustomerInvoice, CustomerInvoiceItemProps, ItemAmount } from "../../../domain";
import { CustomerInvoiceTaxCreationAttributes, CustomerInvoiceTaxModel } from "../../sequelize";

export class TaxesDomainMapper extends SequelizeDomainMapper<
  CustomerInvoiceTaxModel,
  CustomerInvoiceTaxCreationAttributes,
  { taxableAmount: ItemAmount; tax: Tax; taxesAmount: ItemAmount }
> {
  private _taxCatalog: JsonTaxCatalogProvider;

  constructor(params: MapperParamsType) {
    super();
    const { taxCatalog } = params as {
      taxCatalog: JsonTaxCatalogProvider;
    };

    if (!taxCatalog) {
      throw new Error('taxCatalog not defined ("TaxesMapper")');
    }

    this._taxCatalog = taxCatalog;
  }

  public mapToDomain(
    source: CustomerInvoiceTaxModel,
    params?: MapperParamsType
  ): Result<
    {
      taxableAmount: ItemAmount;
      tax: Tax;
      taxesAmount: ItemAmount;
    },
    Error
  > {
    const { attributes } = params as {
      attributes: Partial<CustomerInvoiceItemProps>;
    };

    return Result.ok({
      taxableAmount: ItemAmount.create({
        value: source.taxable_amount_value,
        currency_code: attributes.currencyCode!.code,
      }).data,
      tax: Tax.createFromCode(source.tax_code, this._taxCatalog).data,
      taxesAmount: ItemAmount.create({
        value: source.taxes_amount_value,
        currency_code: attributes.currencyCode!.code,
      }).data,
    });
  }

  public mapToPersistence(
    source: {
      taxableAmount: ItemAmount;
      tax: Tax;
      taxesAmount: ItemAmount;
    },
    params?: MapperParamsType
  ): Result<CustomerInvoiceTaxCreationAttributes, Error> {
    const { errors, parent } = params as {
      parent: CustomerInvoice;
      errors: ValidationErrorDetail[];
    };

    source;

    return Result.ok({
      tax_id: UniqueID.generateNewID().toPrimitive(),
      invoice_id: parent.id.toPrimitive(),

      tax_code: source.tax.code,

      taxable_amount_value: source.taxableAmount.value,
      taxable_amount_scale: source.taxableAmount.scale,

      taxes_amount_value: source.taxesAmount.value,
      taxes_amount_scale: source.taxesAmount.scale,
    });
  }
}
