import { Criteria } from "@repo/rdx-criteria/server";
import { UniqueID } from "@repo/rdx-ddd";
import { Collection, Result } from "@repo/rdx-utils";
import { CustomerInvoiceListDTO } from "../../infrastructure";
import { CustomerInvoice } from "../aggregates";

/**
 * Interfaz del repositorio para el agregado `CustomerInvoice`.
 * El escopado multitenant está representado por `companyId`.
 */
export interface ICustomerInvoiceRepository {
  /**
   *
   * Crea una nueva factura.
   *
   * @param invoice - El agregado a guardar.
   * @param transaction - Transacción activa para la operación.
   * @returns Result<void, Error>
   */
  create(invoice: CustomerInvoice, transaction?: unknown): Promise<Result<void, Error>>;

  /**
   * Actualiza una factura existente.
   *
   * @param invoice - El agregado a actualizar.
   * @param transaction - Transacción activa para la operación.
   * @returns Result<void, Error>
   */
  update(invoice: CustomerInvoice, transaction?: unknown): Promise<Result<void, Error>>;

  /**
   * Comprueba si existe una factura con un `id` dentro de una `company`.
   */
  existsByIdInCompany(
    companyId: UniqueID,
    id: UniqueID,
    transaction?: unknown
  ): Promise<Result<boolean, Error>>;

  /**
   * Recupera una factura por su ID y companyId.
   * Devuelve un `NotFoundError` si no se encuentra.
   */
  getByIdInCompany(
    companyId: UniqueID,
    id: UniqueID,
    transaction?: unknown
  ): Promise<Result<CustomerInvoice, Error>>;

  /**
   *
   * Consulta facturas dentro de una empresa usando un
   * objeto Criteria (filtros, orden, paginación).
   * El resultado está encapsulado en un objeto `Collection<T>`.
   *
   * @param companyId - ID de la empresa.
   * @param criteria - Criterios de búsqueda.
   * @param transaction - Transacción activa para la operación.
   * @returns Result<Collection<CustomerInvoiceListDTO>, Error>
   *
   * @see Criteria
   */
  findByCriteriaInCompany(
    companyId: UniqueID,
    criteria: Criteria,
    transaction: unknown
  ): Promise<Result<Collection<CustomerInvoiceListDTO>, Error>>;

  /**
   *
   * Elimina o marca como eliminada una factura dentro de una empresa.
   *
   * @param companyId - ID de la empresa.
   * @param id - UUID de la factura a eliminar.
   * @param transaction - Transacción activa para la operación.
   * @returns Result<void, Error>
   */
  deleteByIdInCompany(
    companyId: UniqueID,
    id: UniqueID,
    transaction: unknown
  ): Promise<Result<boolean, Error>>;
}
