"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AbstractController = void 0;
const mongoose_1 = __importDefault(require("mongoose"));
const express_validator_1 = require("express-validator");
const error_handle_1 = require("../utils/handlers/error.handle");
const paginationParams_1 = require("../config/paginationParams");
const mongoosePaginate = require("mongoose-paginate-v2");
const mongoosePaginateAggregate = require("mongoose-aggregate-paginate-v2");
const mongoseDelete = require("mongoose-delete");
const api_query_params_1 = __importDefault(require("api-query-params"));
const abstract_method_1 = require("../methods/abstract.method");
class AbstractController {
    constructor(model, params = {
        mongoose: mongoose_1.default,
        mongoosePaginate,
        mongoosePaginateAggregate,
        mongoseDelete,
        check: express_validator_1.check,
        matchedData: express_validator_1.matchedData,
        handleHttpError: error_handle_1.handleHttpError,
        handleErrorResponse: error_handle_1.handleErrorResponse,
        optionsPaginate: paginationParams_1.optionsPaginate,
        aqp: (query) => {
            const { filter, sort } = (0, api_query_params_1.default)(query);
            Object.keys(filter).forEach((f) => {
                if (mongoose_1.default.Types.ObjectId.isValid(filter[f]) &&
                    filter[f].length === 24) {
                    filter[f] = new mongoose_1.default.Types.ObjectId(filter[f]);
                }
            });
            delete filter.page;
            return { filter, sort };
        },
    }) {
        this.methods = new abstract_method_1.AbstractMethods(model);
        this.model = model;
        this.params = params;
    }
    async getItem(req, res) {
        try {
            const matchedData = this.params.matchedData(req);
            const _id = matchedData._id;
            const data = await this.model.aggregate([
                {
                    $match: { _id: new mongoose_1.default.Types.ObjectId(_id) },
                },
                ...this.methods.mainFilter(req),
            ]);
            res.send(data.length > 0 ? data[0] : {});
        }
        catch (e) {
            this.params.handleHttpError(res, e);
        }
    }
    async getItems(req, res, next) {
        try {
            const { filter, sort } = this.params.aqp(req.query);
            const [, options] = this.params.optionsPaginate(req);
            let aggregate = this.model.aggregate([
                {
                    $match: filter,
                },
                {
                    $match: { deleted: false },
                },
                ...this.methods.mainFilter(req),
            ]);
            const data = await this.model.aggregatePaginate({ ...aggregate }, {
                ...options,
                sort,
            });
            res.send(data);
        }
        catch (e) {
            this.params.handleHttpError(res, e);
        }
    }
    async createItem(req, res) {
        try {
            const matchedData = this.params.matchedData(req);
            const data = await this.methods.saveDocument(matchedData, req);
            res.send(data);
        }
        catch (e) {
            this.params.handleHttpError(res, e);
        }
    }
    async updateItem(req, res) {
        try {
            const matchedData = this.params.matchedData(req);
            const { _id, ...body } = matchedData;
            const data = await this.model.findOneAndUpdate({ _id }, body, {
                new: true,
            });
            res.send(data);
        }
        catch (e) {
            this.params.handleHttpError(res, e);
        }
    }
    async deleteItem(req, res) {
        try {
            const matchedData = this.params.matchedData(req);
            const _id = matchedData._id;
            const findData = await this.model.delete({ _id });
            const data = {
                findData,
                deleted: true,
            };
            res.send(data);
        }
        catch (e) {
            this.params.handleHttpError(res, e);
        }
    }
}
exports.AbstractController = AbstractController;
