import { Presenter } from "@erp/core/api";
import { CustomerInvoiceListDTO } from "@erp/customer-invoices/api/infrastructure";
import { Criteria } from "@repo/rdx-criteria/server";
import { toEmptyString } from "@repo/rdx-ddd";
import { ArrayElement, Collection } from "@repo/rdx-utils";
import { ListCustomerInvoicesResponseDTO } from "../../../../common/dto";

export class ListCustomerInvoicesPresenter extends Presenter {
  protected _mapInvoice(invoice: CustomerInvoiceListDTO) {
    const recipientDTO = invoice.recipient.toObjectString();

    const invoiceDTO: ArrayElement<ListCustomerInvoicesResponseDTO["items"]> = {
      id: invoice.id.toString(),
      company_id: invoice.companyId.toString(),
      is_proforma: invoice.isProforma,
      customer_id: invoice.customerId.toString(),

      invoice_number: toEmptyString(invoice.invoiceNumber, (value) => value.toString()),
      status: invoice.status.toPrimitive(),
      series: toEmptyString(invoice.series, (value) => value.toString()),

      invoice_date: invoice.invoiceDate.toDateString(),
      operation_date: toEmptyString(invoice.operationDate, (value) => value.toDateString()),
      reference: toEmptyString(invoice.reference, (value) => value.toString()),
      description: toEmptyString(invoice.description, (value) => value.toString()),

      recipient: {
        customer_id: invoice.customerId.toString(),
        ...recipientDTO,
      },

      language_code: invoice.languageCode.code,
      currency_code: invoice.currencyCode.code,

      taxes: invoice.taxes,

      subtotal_amount: invoice.subtotalAmount.toObjectString(),
      discount_percentage: invoice.discountPercentage.toObjectString(),
      discount_amount: invoice.discountAmount.toObjectString(),
      taxable_amount: invoice.taxableAmount.toObjectString(),
      taxes_amount: invoice.taxesAmount.toObjectString(),
      total_amount: invoice.totalAmount.toObjectString(),

      metadata: {
        entity: "customer-invoice",
      },
    };

    return invoiceDTO;
  }

  toOutput(params: {
    customerInvoices: Collection<CustomerInvoiceListDTO>;
    criteria: Criteria;
  }): ListCustomerInvoicesResponseDTO {
    const { customerInvoices, criteria } = params;

    const invoices = customerInvoices.map((invoice) => this._mapInvoice(invoice));
    const totalItems = customerInvoices.total();

    return {
      page: criteria.pageNumber,
      per_page: criteria.pageSize,
      total_pages: Math.ceil(totalItems / criteria.pageSize),
      total_items: totalItems,
      items: invoices,
      metadata: {
        entity: "customer-invoices",
        criteria: criteria.toJSON(),
        //links: {
        //  self: `/api/customer-invoices?page=${criteria.pageNumber}&per_page=${criteria.pageSize}`,
        //  first: `/api/customer-invoices?page=1&per_page=${criteria.pageSize}`,
        //  last: `/api/customer-invoices?page=${Math.ceil(totalItems / criteria.pageSize)}&per_page=${criteria.pageSize}`,
        //},
      },
    };
  }
}
