"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.addCustomerGroups = exports.excludeNoDataColumns = exports.findCollaterals = exports.getCollateralListBySheetId = exports.findCollateralSheetsById = exports.findCollateralSheets = exports.getCollateralListByBBCAndType = exports.getCollateralDocsByBBC = exports.getPreviousCollateralDocument = exports.getCollateralListBySheet = exports.getBBCSheetsForBorrowerAndType = exports.findCollateralsWithSheets = exports.ITEMS_PAGINATION = exports.createQuery = exports.COLLATERALS_LOOKUP = exports.collateralFields = exports.collateralMap = void 0;
const mongoose_1 = __importDefault(require("mongoose"));
const lodash_1 = __importDefault(require("lodash"));
const _models_1 = require("../models/_models");
const collaterals_enum_1 = require("../enums/collaterals.enum");
const AccountPayableItem_model_1 = require("../models/AccountPayableItem.model");
const BBCDate_model_1 = require("../models/BBCDate.model");
const BBCSheet_model_1 = require("../models/BBCSheet.model");
const InventoryItem_model_1 = require("../models/InventoryItem.model");
const ReceivableItem_model_1 = require("../models/ReceivableItem.model");
const enums_helper_1 = require("../helpers/enums.helper");
const bbcSheets_db_1 = require("./bbcSheets.db");
const bbcDates_db_1 = require("./bbcDates.db");
const groups_db_1 = require("./groups.db");
const SalesItem_model_1 = require("../models/SalesItem.model");
exports.collateralMap = {
    [collaterals_enum_1.ECollaterals.INVENTORY]: InventoryItem_model_1.InventoryItemModel,
    [collaterals_enum_1.ECollaterals.RECEIVABLE]: ReceivableItem_model_1.ReceivableItemModel,
    [collaterals_enum_1.ECollaterals.ACCOUNT_PAYABLE]: AccountPayableItem_model_1.AccountPayableItemModel,
    [collaterals_enum_1.ECollaterals.SALES]: SalesItem_model_1.SalesItem,
};
exports.collateralFields = {
    [collaterals_enum_1.ECollaterals.INVENTORY]: InventoryItem_model_1.INVENTORY_FIELDS,
    [collaterals_enum_1.ECollaterals.RECEIVABLE]: ReceivableItem_model_1.RECEIVABLE_FIELDS,
    [collaterals_enum_1.ECollaterals.ACCOUNT_PAYABLE]: AccountPayableItem_model_1.ACCOUNT_PAYABLE_FIELDS,
    [collaterals_enum_1.ECollaterals.SALES]: SalesItem_model_1.SALES_FIELDS,
};
exports.COLLATERALS_LOOKUP = [
    {
        $lookup: {
            from: _models_1.MODEL_NAMES.BBCSheets,
            localField: 'bbcSheetId',
            foreignField: '_id',
            as: 'bbcSheet',
        },
    },
    {
        $unwind: {
            path: '$bbcSheet',
        },
    },
    {
        $lookup: {
            from: _models_1.MODEL_NAMES.BBCDates,
            localField: 'bbcSheet.bbcDateId',
            foreignField: '_id',
            as: 'bbc',
        },
    },
    {
        $unwind: {
            path: '$bbc',
        },
    },
];
const createQuery = (groupFields, collateralType) => {
    const enumKey = (0, enums_helper_1.getEnumKeyByEnumValue)(collaterals_enum_1.ECollaterals, collateralType);
    const itemFields = exports.collateralFields[enumKey];
    if (!itemFields) {
        console.error('Incorrect collateralType - ', collateralType);
        return null;
    }
    const groupQueries = Object
        .entries(groupFields)
        .map(([fieldKey, fieldValue]) => ({ [fieldKey]: { $first: `$${fieldValue}` } }))
        .reduce((acc, group) => ({ ...acc, ...group }), {});
    const itemQueries = itemFields
        .map((fieldKey) => ({ [fieldKey]: `$${fieldKey}` }))
        .reduce((acc, group) => ({ ...acc, ...group }), {});
    return { groupQueries, itemQueries, enumKey };
};
exports.createQuery = createQuery;
const ITEMS_PAGINATION = (paginatorOptions) => {
    if (!paginatorOptions) {
        return [];
    }
    if (paginatorOptions.pageSize === 0 && paginatorOptions.pageIndex === 0) {
        return [];
    }
    return !!paginatorOptions.pageSize
        ? [{ $skip: paginatorOptions.pageIndex * paginatorOptions.pageSize }, { $limit: paginatorOptions.pageSize }]
        : [];
};
exports.ITEMS_PAGINATION = ITEMS_PAGINATION;
const findCollateralsWithSheets = async (borrowerId, collateralTypes) => {
    const bbcDates = await (0, bbcDates_db_1.getBBCDatesByBorrower)(borrowerId);
    const bbcFilter = { 'bbcDateId': { $in: bbcDates.map((bbcDate) => bbcDate._id) } };
    const collateralFilter = collateralTypes
        ? {
            $and: [
                bbcFilter,
                { 'dataType': { $in: collateralTypes } },
            ],
        }
        : bbcFilter;
    return BBCSheet_model_1.BBCSheetModel.aggregate([
        {
            $match: collateralFilter,
        },
        {
            $lookup: {
                from: _models_1.MODEL_NAMES.BBCDates,
                localField: 'bbcDateId',
                foreignField: '_id',
                as: 'bbcDate',
            },
        },
        {
            $unwind: {
                path: '$bbcDate',
            },
        },
        {
            $group: {
                '_id': {
                    'collateralType': '$dataType',
                    'bbcDate': '$bbcDate.bbcDate',
                    '_id': '$bbcDate._id',
                },
                'sheets': {
                    $addToSet: {
                        'name': '$sheetName',
                        '_id': '$_id',
                    },
                },
            },
        },
        {
            $addFields: {
                'collateralType': '$_id.collateralType',
                'bbcDate': '$_id.bbcDate',
                'id': '$_id._id',
            },
        },
        {
            $project: {
                '_id': '$id',
                'sheets': '$sheets',
                'collateralType': '$collateralType',
                'bbcDate': '$bbcDate',
            },
        },
        {
            $sort: {
                'bbcDate': -1,
            },
        },
    ]);
};
exports.findCollateralsWithSheets = findCollateralsWithSheets;
const getBBCSheetsForBorrowerAndType = async (borrowerId, collateralType) => {
    const bbcDates = await (0, bbcDates_db_1.getBBCDatesByBorrower)(borrowerId);
    return (0, bbcSheets_db_1.getBBCSheetsByType)(bbcDates.map((bbcDate) => String(bbcDate._id)), collateralType);
};
exports.getBBCSheetsForBorrowerAndType = getBBCSheetsForBorrowerAndType;
const getCollateralListBySheet = async (sheetIds, collateralType) => {
    const enumKey = (0, enums_helper_1.getEnumKeyByEnumValue)(collaterals_enum_1.ECollaterals, collateralType);
    const sheetIdsMapped = sheetIds.map((sheetId) => new mongoose_1.default.Types.ObjectId(sheetId));
    return exports.collateralMap[enumKey].aggregate([
        {
            $match: {
                'bbcSheetId': { $in: sheetIdsMapped },
            },
        },
        {
            $lookup: {
                from: _models_1.MODEL_NAMES.BBCSheets,
                localField: 'bbcSheetId',
                foreignField: '_id',
                as: 'bbcSheet',
            },
        },
        {
            $unwind: {
                path: '$bbcSheet',
            },
        },
        {
            $lookup: {
                from: _models_1.MODEL_NAMES.BBCDates,
                localField: 'bbcSheet.bbcDateId',
                foreignField: '_id',
                as: 'bbc',
            },
        },
        {
            $unwind: {
                path: '$bbc',
            },
        },
        {
            $sort: {
                'order': 1,
                'bbc.bbcDate': 1,
            },
        },
    ]);
};
exports.getCollateralListBySheet = getCollateralListBySheet;
const getPreviousCollateralDocument = async (borrowerId, date, collateralType, limit = 1) => {
    return BBCSheet_model_1.BBCSheetModel.aggregate([
        {
            $match: {
                'dataType': collateralType,
            },
        },
        {
            $lookup: {
                from: _models_1.MODEL_NAMES.BBCDates,
                localField: 'bbcDateId',
                foreignField: '_id',
                as: 'bbc',
            },
        },
        {
            $unwind: {
                path: '$bbc',
            },
        },
        {
            $match: {
                'bbc.borrowerId': new mongoose_1.default.Types.ObjectId(borrowerId),
                'bbc.bbcDate': { $lt: date },
            },
        },
        {
            $group: {
                '_id': '$bbcDateId',
                'bbcDate': {
                    $first: '$bbc.bbcDate',
                },
            },
        },
        {
            $sort: {
                bbcDate: -1,
            },
        },
        {
            $limit: limit,
        },
    ]);
};
exports.getPreviousCollateralDocument = getPreviousCollateralDocument;
const getCollateralDocsByBBC = async (bbcIds, collateralType) => {
    if (!exports.collateralFields[collateralType]) {
        console.error('Incorrect collateralType! - ', collateralType);
        return [];
    }
    const bbcSheets = await (0, bbcSheets_db_1.getBBCSheetsByType)(bbcIds, collateralType);
    const groupFields = {
        bbcDate: 'bbc.bbcDate',
        borrowerId: 'bbc.borrowerId',
    };
    const { groupQueries, itemQueries, enumKey } = (0, exports.createQuery)(groupFields, collateralType);
    const groupingQuery = { _id: '$bbc._id', ...groupQueries, items: { $push: itemQueries } };
    const aggregationResult = await exports.collateralMap[enumKey].aggregate([
        {
            $match: {
                'bbcSheetId': { $in: bbcSheets.map((bbcSheet) => bbcSheet._id) },
            },
        },
        ...exports.COLLATERALS_LOOKUP,
        {
            $sort: {
                order: 1,
            },
        },
        {
            $group: groupingQuery,
        },
        {
            $sort: {
                bbcDate: 1,
            },
        },
    ]);
    if (!aggregationResult.length) {
        const BBCs = await BBCDate_model_1.BBCDateModel.find({ _id: { $in: bbcIds } }).lean();
        return BBCs.map((BBC) => ({ ...BBC, items: [] }));
    }
    return aggregationResult;
};
exports.getCollateralDocsByBBC = getCollateralDocsByBBC;
const getCollateralListByBBCAndType = async (bbcDateId, collateralType) => {
    const sheets = await (0, bbcSheets_db_1.getBBCSheetsByType)([bbcDateId], collateralType);
    return (0, exports.getCollateralListBySheet)(sheets.map((sheet) => String(sheet._id)), collateralType);
};
exports.getCollateralListByBBCAndType = getCollateralListByBBCAndType;
const findCollateralSheets = (bbcDateId, collateralType) => {
    return BBCSheet_model_1.BBCSheetModel.find({ bbcDateId, dataType: collateralType });
};
exports.findCollateralSheets = findCollateralSheets;
const findCollateralSheetsById = async (collateralsId) => {
    return BBCSheet_model_1.BBCSheetModel.findById(collateralsId);
};
exports.findCollateralSheetsById = findCollateralSheetsById;
const getCollateralsBySheet = async (sheet, paginatorOptions) => {
    const groupFields = {
        bbcDate: 'bbc.bbcDate',
        borrowerId: 'bbc.borrowerId',
        fileName: 'bbcSheet.fileName',
        sheetName: 'bbcSheet.sheetName',
    };
    const { groupQueries, itemQueries, enumKey } = (0, exports.createQuery)(groupFields, sheet.dataType);
    const groupingQuery = { _id: '$bbcSheetId', ...groupQueries, items: { $push: itemQueries } };
    const collateralSheets = await exports.collateralMap[enumKey].aggregate([
        {
            $match: {
                'bbcSheetId': sheet._id,
            },
        },
        ...exports.COLLATERALS_LOOKUP,
        {
            $sort: {
                order: 1,
            },
        },
        ...(0, exports.ITEMS_PAGINATION)(paginatorOptions),
        {
            $group: groupingQuery,
        },
    ]);
    if (collateralSheets.length === 0) {
        const bbcDates = await BBCDate_model_1.BBCDateModel.aggregate([
            {
                $match: {
                    '_id': sheet.bbcDateId,
                },
            },
        ]);
        if (bbcDates.length === 0) {
            return [];
        }
        return [{
                _id: sheet._id,
                bbcDate: bbcDates[0].bbcDate,
                borrowerId: bbcDates[0].borrowerId,
                fileName: sheet.fileName,
                sheetName: sheet.sheetName,
                items: [],
            }];
    }
    return collateralSheets;
};
const getCollateralListBySheetId = async (sheet, paginatorOptions) => {
    const enumKey = (0, enums_helper_1.getEnumKeyByEnumValue)(collaterals_enum_1.ECollaterals, sheet.dataType);
    return exports.collateralMap[enumKey].aggregate([
        {
            $match: {
                'bbcSheetId': sheet._id,
            },
        },
        ...exports.COLLATERALS_LOOKUP,
        {
            $sort: {
                order: 1,
            },
        },
        ...(0, exports.ITEMS_PAGINATION)(paginatorOptions),
    ]);
};
exports.getCollateralListBySheetId = getCollateralListBySheetId;
const findCollaterals = async (collateralsId, group, paginatorOptions) => {
    const sheet = await (0, exports.findCollateralSheetsById)(collateralsId);
    if (group) {
        return await getCollateralsBySheet(sheet, paginatorOptions);
    }
    return await (0, exports.getCollateralListBySheetId)(sheet, paginatorOptions);
};
exports.findCollaterals = findCollaterals;
const excludeNoDataColumns = (data, columns) => {
    return data.map((dataRow) => lodash_1.default.pick(dataRow, columns));
};
exports.excludeNoDataColumns = excludeNoDataColumns;
const addCustomerGroups = async (data, borrowerId) => {
    const groupName = 'customers';
    const groups = await (0, groups_db_1.getBorrowerGroups)(borrowerId, groupName);
    return data.map((dataRow) => {
        const foundGroup = groups[groupName].find((group) => group.items.includes(dataRow.customerTitle));
        return {
            ...dataRow,
            customerGroup: foundGroup ? foundGroup.groupName : dataRow.customerTitle,
        };
    });
};
exports.addCustomerGroups = addCustomerGroups;
