import { IUseCase, IUseCaseError, UseCaseError } from "@/contexts/common/application/useCases";
import { IRepositoryManager } from "@/contexts/common/domain";
import { Collection, ICollection, IQueryCriteria, Result } from "@shared/contexts";

import { IInfrastructureError } from "@/contexts/common/infrastructure";
import { ISequelizeAdapter } from "@/contexts/common/infrastructure/sequelize";
import { logger } from "@/infrastructure/logger";
import { Article, ICatalogRepository } from "../domain";

export interface IListArticlesParams {
  queryCriteria: IQueryCriteria;
}

export type ListArticlesResult =
  | Result<never, IUseCaseError> // Misc errors (value objects)
  | Result<ICollection<Article>, never>; // Success!

export class ListArticlesUseCase
  implements IUseCase<IListArticlesParams, Promise<ListArticlesResult>>
{
  private _adapter: ISequelizeAdapter;
  private _repositoryManager: IRepositoryManager;

  constructor(props: { adapter: ISequelizeAdapter; repositoryManager: IRepositoryManager }) {
    this._adapter = props.adapter;
    this._repositoryManager = props.repositoryManager;
  }

  private getRepositoryByName<T>(name: string) {
    return this._repositoryManager.getRepository<T>(name);
  }

  async execute(params: Partial<IListArticlesParams>): Promise<ListArticlesResult> {
    const { queryCriteria } = params;

    return this.findArticles(queryCriteria);
  }

  private async findArticles(queryCriteria) {
    const transaction = this._adapter.startTransaction();
    const productRepoBuilder = this.getRepositoryByName<ICatalogRepository>("Article");

    let products: ICollection<Article> = new Collection();

    try {
      await transaction.complete(async (t) => {
        products = await productRepoBuilder({ transaction: t }).findAll(queryCriteria);
      });
      return Result.ok(products);
    } catch (error: unknown) {
      const _error = error as IInfrastructureError;
      logger().error(_error);
      return Result.fail(
        UseCaseError.create(UseCaseError.REPOSITORY_ERROR, "Error al listar el catálogo", _error)
      );
    }
  }
}
