import { IPresenterRegistry, ITransactionManager } from "@erp/core/api";
import { Criteria } from "@repo/rdx-criteria/server";
import { UniqueID } from "@repo/rdx-ddd";
import { Result } from "@repo/rdx-utils";
import { Transaction } from "sequelize";
import { ListCustomerInvoicesResponseDTO } from "../../../common/dto";
import { CustomerInvoiceApplicationService } from "../../application";
import { ListCustomerInvoicesPresenter } from "../presenters";

type ListCustomerInvoicesUseCaseInput = {
  companyId: UniqueID;
  criteria: Criteria;
};

export class ListCustomerInvoicesUseCase {
  constructor(
    private readonly service: CustomerInvoiceApplicationService,
    private readonly transactionManager: ITransactionManager,
    private readonly presenterRegistry: IPresenterRegistry
  ) {}

  public execute(
    params: ListCustomerInvoicesUseCaseInput
  ): Promise<Result<ListCustomerInvoicesResponseDTO, Error>> {
    const { criteria, companyId } = params;
    const presenter = this.presenterRegistry.getPresenter({
      resource: "customer-invoice",
      projection: "LIST",
    }) as ListCustomerInvoicesPresenter;

    return this.transactionManager.complete(async (transaction: Transaction) => {
      try {
        const result = await this.service.findInvoiceByCriteriaInCompany(
          companyId,
          criteria,
          transaction
        );

        if (result.isFailure) {
          return Result.fail(result.error);
        }

        const customerInvoices = result.data;
        const dto = presenter.toOutput({
          customerInvoices,
          criteria,
        });

        return Result.ok(dto);
      } catch (error: unknown) {
        return Result.fail(error as Error);
      }
    });
  }
}
