import { UniqueID } from "core/common/domain";
import { Collection, Result } from "core/common/helpers";
import { Transaction } from "sequelize";
import { IInvoiceProps, Invoice } from "../aggregates";
import { IInvoiceRepository } from "../repositories";
import { IInvoiceService } from "./invoice-service.interface";

export class InvoiceService implements IInvoiceService {
  constructor(private readonly repo: IInvoiceRepository) {}

  async findInvoices(transaction?: Transaction): Promise<Result<Collection<Invoice>, Error>> {
    const invoicesOrError = await this.repo.findAll(transaction);
    if (invoicesOrError.isFailure) {
      return Result.fail(invoicesOrError.error);
    }

    // Solo devolver usuarios activos
    //const allInvoices = invoicesOrError.data.filter((invoice) => invoice.isActive);
    //return Result.ok(new Collection(allInvoices));

    return invoicesOrError;
  }

  async findInvoiceById(invoiceId: UniqueID, transaction?: Transaction): Promise<Result<Invoice>> {
    return await this.repo.getById(invoiceId, transaction);
  }

  async updateInvoiceById(
    invoiceId: UniqueID,
    data: Partial<IInvoiceProps>,
    transaction?: Transaction
  ): Promise<Result<Invoice, Error>> {
    // Verificar si la factura existe
    const invoiceOrError = await this.repo.getById(invoiceId, transaction);
    if (invoiceOrError.isFailure) {
      return Result.fail(new Error("Invoice not found"));
    }

    const updatedInvoiceOrError = Invoice.update(invoiceOrError.data, data);
    if (updatedInvoiceOrError.isFailure) {
      return Result.fail(
        new Error(`Error updating invoice: ${updatedInvoiceOrError.error.message}`)
      );
    }

    const updateInvoice = updatedInvoiceOrError.data;

    await this.repo.update(updateInvoice, transaction);
    return Result.ok(updateInvoice);
  }

  async createInvoice(
    invoiceId: UniqueID,
    data: IInvoiceProps,
    transaction?: Transaction
  ): Promise<Result<Invoice, Error>> {
    // Verificar si la factura existe
    const invoiceOrError = await this.repo.getById(invoiceId, transaction);
    if (invoiceOrError.isSuccess) {
      return Result.fail(new Error("Invoice exists"));
    }

    const newInvoiceOrError = Invoice.create(data, invoiceId);
    if (newInvoiceOrError.isFailure) {
      return Result.fail(new Error(`Error creating invoice: ${newInvoiceOrError.error.message}`));
    }

    const newInvoice = newInvoiceOrError.data;

    await this.repo.create(newInvoice, transaction);
    return Result.ok(newInvoice);
  }

  async deleteInvoiceById(
    invoiceId: UniqueID,
    transaction?: Transaction
  ): Promise<Result<boolean, Error>> {
    return this.repo.deleteById(invoiceId, transaction);
  }
}
