import {
  ISequelizeAdapter,
  SequelizeRepository,
} from "@/contexts/common/infrastructure/sequelize";
import { ICollection, IQueryCriteria, UniqueID } from "@shared/contexts";
import { Transaction } from "sequelize";
import { ICatalogContext } from ".";
import { ICatalogRepository } from "../domain";
import { Article } from "../domain/entities";
import { IArticleMapper, createArticleMapper } from "./mappers/article.mapper";

export type QueryParams = {
  pagination: Record<string, any>;
  filters: Record<string, any>;
};

export class CatalogRepository
  extends SequelizeRepository<Article>
  implements ICatalogRepository
{
  protected mapper: IArticleMapper;

  public constructor(props: {
    mapper: IArticleMapper;
    adapter: ISequelizeAdapter;
    transaction: Transaction;
  }) {
    const { adapter, mapper, transaction } = props;
    super({ adapter, transaction });
    this.mapper = mapper;
  }

  public async getById(id: UniqueID): Promise<Article | null> {
    const rawArticle: any = await this._getById("Article_Model", id);

    if (!rawArticle === true) {
      return null;
    }

    return this.mapper.mapToDomain(rawArticle);
  }

  public async findAll(
    queryCriteria?: IQueryCriteria,
  ): Promise<ICollection<any>> {
    const { rows, count } = await this._findAll(
      "Article_Model",
      queryCriteria,
      /*{
        include: [],  // esto es para quitar las asociaciones al hacer la consulta
      }*/
    );

    return this.mapper.mapArrayAndCountToDomain(rows, count);
  }
}

export const registerCatalogRepository = (context: ICatalogContext) => {
  const adapter = context.adapter;
  const repoManager = context.repositoryManager;

  repoManager.registerRepository(
    "Article",
    (params = { transaction: null }) => {
      const { transaction } = params;

      return new CatalogRepository({
        transaction,
        adapter,
        mapper: createArticleMapper(context),
      });
    },
  );
};
