import { IPresenterRegistry, ITransactionManager } from "@erp/core/api";
import { UniqueID } from "@repo/rdx-ddd";
import { Result } from "@repo/rdx-utils";
import { CustomerInvoiceApplicationService } from "../../../domain";
import { CustomerInvoiceReportPDFPresenter } from "./reporter";

type ReportCustomerInvoiceUseCaseInput = {
  companyId: UniqueID;
  invoice_id: string;
};

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

  public async execute(params: ReportCustomerInvoiceUseCaseInput) {
    const { invoice_id, companyId } = params;

    const idOrError = UniqueID.create(invoice_id);

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

    const invoiceId = idOrError.data;
    const pdfPresenter = this.presenterRegistry.getPresenter({
      resource: "customer-invoice",
      projection: "REPORT",
      format: "PDF",
    }) as CustomerInvoiceReportPDFPresenter;

    return this.transactionManager.complete(async (transaction) => {
      try {
        const invoiceOrError = await this.service.getInvoiceByIdInCompany(
          companyId,
          invoiceId,
          transaction
        );
        if (invoiceOrError.isFailure) {
          return Result.fail(invoiceOrError.error);
        }

        const invoice = invoiceOrError.data;
        const pdfData = await pdfPresenter.toOutput(invoice);
        return Result.ok({
          data: pdfData,
          filename: `invoice-${invoice.invoiceNumber}.pdf`,
        });
      } catch (error: unknown) {
        return Result.fail(error as Error);
      }
    });
  }
}
