"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getAllCategories = exports.aggregateBbcExposuresGrouped = exports.aggregateBbcExposures = exports.aggregateAllValuesForBbc = exports.aggregateSKUDateAgingPlot = exports.getAllTimeOldestSKUDateNew = exports.groupSKUsByDate = exports.getLastDigitFromAllValues = exports.getMostRecentInventoryBBCDate = exports.getInventoriesAndTheirQtyByBorrowerId = exports.getInventoryItemsSKUAndValue = exports.getSKUUnitCostForAllDates = void 0;
const mongoose_1 = __importDefault(require("mongoose"));
const dayjs_1 = __importDefault(require("dayjs"));
const Inventory_model_1 = require("../models/Inventory.model");
const bbcDates_db_1 = require("./bbcDates.db");
const bbcSheets_db_1 = require("./bbcSheets.db");
const collaterals_enum_1 = require("../enums/collaterals.enum");
const InventoryItem_model_1 = require("../models/InventoryItem.model");
const collaterals_db_1 = require("./collaterals.db");
const getSKUUnitCostForAllDates = async (sheetsIds) => {
    return InventoryItem_model_1.InventoryItemModel.aggregate([
        {
            $match: {
                'bbcSheetId': {
                    $in: sheetsIds
                }
            }
        },
        ...collaterals_db_1.COLLATERALS_LOOKUP,
        {
            $sort: {
                'bbc.bbcDate': -1
            }
        },
        {
            $group: {
                '_id': '$sku',
                'currentCost': {
                    $first: '$unitCost'
                },
                'minCost': {
                    $min: {
                        'minCost': '$unitCost',
                        'bbcDate': '$bbc.bbcDate'
                    }
                },
                'qty': {
                    $first: '$qty'
                }
            }
        }
    ]);
};
exports.getSKUUnitCostForAllDates = getSKUUnitCostForAllDates;
const getInventoryItemsSKUAndValue = async (sheetIds) => await InventoryItem_model_1.InventoryItemModel.aggregate([
    {
        $match: { bbcSheetId: { $in: sheetIds.map((sheetId) => new mongoose_1.default.Types.ObjectId(sheetId)) } },
    },
    {
        $group: {
            _id: '$sku',
            totalAmount: {
                $sum: '$value',
            },
        },
    },
    {
        $sort: { totalAmount: -1 },
    },
]);
exports.getInventoryItemsSKUAndValue = getInventoryItemsSKUAndValue;
const getInventoriesAndTheirQtyByBorrowerId = async (borrowerId, allBbcDates) => await Inventory_model_1.InventoryModel.aggregate([
    {
        $match: {
            borrowerId,
            bbcDate: {
                $in: allBbcDates.map((i) => i.bbcDate)
            }
        }
    },
    { $unwind: '$items' },
    {
        $group: {
            _id: '$bbcDate',
            qty: { $sum: '$items.qty' },
        },
    },
    {
        $sort: {
            _id: 1,
        },
    },
]);
exports.getInventoriesAndTheirQtyByBorrowerId = getInventoriesAndTheirQtyByBorrowerId;
const getMostRecentInventoryBBCDate = async (borrowerId) => {
    const inventory = await Inventory_model_1.InventoryModel.find({ borrower: borrowerId })
        .sort([['bbcDate', -1]])
        .limit(1);
    return inventory[0].bbcDate;
};
exports.getMostRecentInventoryBBCDate = getMostRecentInventoryBBCDate;
const getLastDigitFromAllValues = async (allBbcDates) => {
    const allIds = allBbcDates.reduce((acc, bbcDate) => [...acc, ...bbcDate.ids], []);
    return InventoryItem_model_1.InventoryItemModel.aggregate([
        {
            $match: {
                'bbcSheetId': {
                    $in: allIds
                }
            }
        },
        ...collaterals_db_1.COLLATERALS_LOOKUP,
        {
            $group: {
                '_id': '$bbc.bbcDate',
                'borrowerId': {
                    $first: '$bbc.borrowerId',
                },
                'items': {
                    $addToSet: {
                        'value': '$value',
                    },
                },
            },
        },
        {
            $project: {
                '_id': '$borrowerId',
                'bbcDate': '$_id',
                'digitArray': {
                    $map: {
                        input: '$items',
                        as: 'item',
                        in: {
                            $substr: [
                                {
                                    $toString: '$$item.value',
                                },
                                0,
                                1,
                            ],
                        },
                    },
                },
            },
        },
        {
            $sort: {
                'bbcDate': 1
            }
        },
        {
            $group: {
                '_id': 1,
                'bbcDates': {
                    $push: '$bbcDate'
                },
                'digitArrays': {
                    $push: '$digitArray'
                },
            }
        }
    ]);
};
exports.getLastDigitFromAllValues = getLastDigitFromAllValues;
const groupSKUsByDate = async (borrowerId) => {
    const bbcDate = await (0, exports.getMostRecentInventoryBBCDate)(borrowerId);
    const date = new Date(bbcDate);
    const oneMonthAgo = (0, dayjs_1.default)(date).subtract(1, 'month').toDate();
    const threeMonthsAgo = (0, dayjs_1.default)(date).subtract(3, 'month').toDate();
    const sixMonthsAgo = (0, dayjs_1.default)(date).subtract(6, 'month').toDate();
    const items = await Inventory_model_1.InventoryModel.aggregate([
        {
            $match: {
                bbcDate: { $in: [date, oneMonthAgo, threeMonthsAgo, sixMonthsAgo] },
            },
        },
        {
            $unwind: '$items',
        },
        {
            $group: {
                _id: '$items.sku',
                valuesAtTime: { $push: { bbcDate: '$bbcDate', count: '$items.qty' } },
            },
        },
    ]);
    return {
        items,
        oneMonthAgo,
        threeMonthsAgo,
        sixMonthsAgo,
        recent: date,
    };
};
exports.groupSKUsByDate = groupSKUsByDate;
const getAllTimeOldestSKUDateNew = async (borrowerId, bbcDate) => {
    const bbcDates = await (0, bbcDates_db_1.getOlderBBCDates)(borrowerId, bbcDate);
    const sheets = await (0, bbcSheets_db_1.getBBCSheetsByType)(bbcDates.map((bbcDate) => bbcDate._id.toString()), collaterals_enum_1.ECollaterals.INVENTORY);
    return InventoryItem_model_1.InventoryItemModel.aggregate([
        {
            $match: {
                bbcSheetId: {
                    '$in': sheets.map((sheet) => sheet._id)
                }
            }
        },
        {
            $group: {
                _id: '$sku',
                oldestDate: {
                    $min: '$skuDate',
                },
            },
        },
    ]);
};
exports.getAllTimeOldestSKUDateNew = getAllTimeOldestSKUDateNew;
const todayDayjs = (0, dayjs_1.default)();
const today = todayDayjs.toDate();
const thirtyDaysAgo = todayDayjs.subtract(30, 'day').toDate();
const sixtyDaysAgo = todayDayjs.subtract(60, 'day').toDate();
const ninetyDaysAgo = todayDayjs.subtract(90, 'day').toDate();
const aggregateSKUDateAgingPlot = async (bbcSheetIds) => {
    const generateSumAggregation = (start, end) => ({
        $sum: {
            $add: {
                $cond: [
                    {
                        $and: [
                            { $lte: ['$skuDate', start] },
                            { $gte: ['$skuDate', end] },
                        ],
                    },
                    '$value',
                    '$$REMOVE',
                ],
            },
        },
    });
    const a = await InventoryItem_model_1.InventoryItemModel.aggregate([
        { $match: { 'bbcSheetId': { $in: bbcSheetIds } } },
        ...collaterals_db_1.COLLATERALS_LOOKUP,
        {
            $group: {
                _id: '$bbc.bbcDate',
                '0-30': generateSumAggregation(today, thirtyDaysAgo),
                '30-60': generateSumAggregation(thirtyDaysAgo, sixtyDaysAgo),
                '60-90': generateSumAggregation(sixtyDaysAgo, ninetyDaysAgo),
                '90+': {
                    $sum: {
                        $add: {
                            $cond: [
                                {
                                    $lte: ['$skuDate', ninetyDaysAgo],
                                },
                                '$value',
                                '$$REMOVE',
                            ],
                        },
                    },
                },
            },
        },
    ]);
    return a[0];
};
exports.aggregateSKUDateAgingPlot = aggregateSKUDateAgingPlot;
const aggregateAllValuesForBbc = async (bbcSheetIds) => {
    return InventoryItem_model_1.InventoryItemModel.aggregate([
        {
            $match: {
                bbcSheetId: { $in: bbcSheetIds },
            },
        },
        {
            $group: {
                _id: '$sku',
                value: { $first: '$value' },
                skuDescription: { $first: '$skuDescription1' },
                category: { $first: '$category' }
            },
        },
        {
            $project: {
                _id: 0,
                sku: '$_id',
                value: 1,
                skuDescription: 1,
                category: 1,
            },
        },
        { $sort: { value: -1 } },
        { $limit: 500 },
    ]);
};
exports.aggregateAllValuesForBbc = aggregateAllValuesForBbc;
const aggregateBbcExposures = async (bbcSheetIds) => {
    const getTotalBbcValue = await InventoryItem_model_1.InventoryItemModel.aggregate([
        {
            $match: {
                'bbcSheetId': { $in: bbcSheetIds }
            }
        },
        { $group: { _id: 0, total: { $sum: '$value' } } },
    ]);
    const inventoryTotal = getTotalBbcValue[0].total;
    const topItemsForBbc = await InventoryItem_model_1.InventoryItemModel.aggregate([
        {
            $match: {
                'bbcSheetId': { $in: bbcSheetIds }
            }
        },
        {
            $group: {
                _id: '$category',
                totalItemValue: { $sum: '$value' },
            },
        },
        { $sort: { totalItemValue: -1 } },
        { $limit: 10 },
        { $project: { _id: 0, name: '$_id', totalItemValue: 1 } },
    ]);
    return { inventoryTotal, topItemsForBbc };
};
exports.aggregateBbcExposures = aggregateBbcExposures;
const aggregateBbcExposuresGrouped = async (bbcSheetIds) => {
    const commonAggregation = [
        {
            $match: {
                'bbcSheetId': { $in: bbcSheetIds }
            }
        },
        ...collaterals_db_1.COLLATERALS_LOOKUP,
        {
            $lookup: {
                from: 'categorygroups',
                let: {
                    'res_cod_it': 'category',
                    'borrowerId': '$borrowerId'
                },
                pipeline: [
                    {
                        $match: {
                            $expr: {
                                $eq: [
                                    '$bbc.borrowerId', '$$borrowerId'
                                ]
                            }
                        }
                    },
                    {
                        $unwind: '$items'
                    }
                ],
                as: 'item'
            }
        },
        {
            $project: {
                'bbc': 1,
                '_id': 1,
                'skuDate': 1,
                'category': 1,
                'value': 1,
                'group': {
                    '$filter': {
                        'input': '$item',
                        'as': 'groupEx',
                        'cond': {
                            '$eq': [
                                '$$groupEx.items', '$category'
                            ]
                        }
                    }
                }
            }
        },
        {
            $addFields: {
                'groupName': {
                    $first: '$group.groupName'
                }
            }
        },
        {
            $project: {
                'borrowerId': 1,
                'bbc': 1,
                'skuDate': 1,
                'category': {
                    $ifNull: [
                        '$groupName', '$category'
                    ]
                },
                'value': 1,
            }
        },
    ];
    const getTotalBbcValue = await InventoryItem_model_1.InventoryItemModel.aggregate([
        ...commonAggregation,
        {
            $group: {
                '_id': 0,
                'total': {
                    $sum: '$value'
                }
            }
        }
    ]);
    const inventoryTotal = getTotalBbcValue[0].total;
    const topItemsForBbc = await InventoryItem_model_1.InventoryItemModel.aggregate([
        ...commonAggregation,
        {
            $group: {
                '_id': '$category',
                'totalItemValue': {
                    $sum: '$value'
                }
            }
        },
        { $sort: { 'totalItemValue': -1 } },
        { $limit: 5 },
        { $project: { '_id': 0, 'name': '$_id', 'totalItemValue': 1 } },
    ]);
    return { inventoryTotal, topItemsForBbc };
};
exports.aggregateBbcExposuresGrouped = aggregateBbcExposuresGrouped;
const getAllCategories = async (borrowerId) => {
    const bbcSheets = await (0, collaterals_db_1.getBBCSheetsForBorrowerAndType)(borrowerId, collaterals_enum_1.ECollaterals.INVENTORY);
    return InventoryItem_model_1.InventoryItemModel.aggregate([
        {
            $match: {
                'bbcSheetId': {
                    $in: bbcSheets.map((bbcSheet) => new mongoose_1.default.Types.ObjectId(String(bbcSheet._id)))
                }
            }
        },
        {
            $group: {
                '_id': null,
                'categories': {
                    $addToSet: '$category'
                }
            }
        },
        {
            $project: {
                '_id': 0
            }
        },
    ]);
};
exports.getAllCategories = getAllCategories;
