import { ISequelizeAdapter, SequelizeRepository } from "@/contexts/common/infrastructure/sequelize";
import { Email, ICollection, IQueryCriteria, UniqueID } from "@shared/contexts";
import { Transaction } from "sequelize";
import { AuthUser } from "../domain/entities";
import { IAuthRepository } from "../domain/repository/AuthRepository.interface";
import { IAuthContext } from "./Auth.context";
import { IUserMapper, createUserMapper } from "./mappers/authuser.mapper";

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

export class AuthRepository extends SequelizeRepository<AuthUser> implements IAuthRepository {
  protected mapper: IUserMapper;

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

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

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

    return this.mapper.mapToDomain(rawUser);
  }

  public async findUserByEmail(email: Email): Promise<AuthUser | null> {
    const rawUser: any = await this._getBy("AuthUser_Model", "email", email.toPrimitive());

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

    return this.mapper.mapToDomain(rawUser);
  }

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

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

export const registerAuthRepository = (context: IAuthContext) => {
  const adapter = context.adapter;
  const repoManager = context.repositoryManager;

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

    return new AuthRepository({
      transaction,
      adapter,
      mapper: createUserMapper(context),
    });
  });
};
