"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getInventoryMovement = exports.getSKUQtyValueUnitCost = exports.getAllUniqSKUInRangeNew = exports.getSKUUnitCostForAllDates = void 0;
const mongoose_1 = __importDefault(require("mongoose"));
const lodash_1 = __importDefault(require("lodash"));
const InventoryItem_model_1 = require("../models/InventoryItem.model");
const collaterals_db_1 = require("./collaterals.db");
const bbcSheets_db_1 = require("./bbcSheets.db");
const collaterals_enum_1 = require("../enums/collaterals.enum");
const _models_1 = require("../models/_models");
const bbcDates_db_1 = require("./bbcDates.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 getAllUniqSKUInRangeNew = async (bbcSheetIds) => {
    return InventoryItem_model_1.InventoryItemModel.aggregate([
        {
            $match: {
                'bbcSheetId': {
                    $in: bbcSheetIds.map((bbcSheetId) => new mongoose_1.default.Types.ObjectId(bbcSheetId)),
                },
            },
        },
        {
            $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: {
                'bbc.bbcDate': 1,
            },
        },
        {
            $group: {
                '_id': '$bbc.borrowerId',
                'skus': {
                    $addToSet: '$sku',
                },
            },
        },
    ]);
};
exports.getAllUniqSKUInRangeNew = getAllUniqSKUInRangeNew;
const getSKUQtyValueUnitCost = async (bbcDateId) => {
    const bbcSheets = await (0, bbcSheets_db_1.getBBCSheetsByType)([bbcDateId], collaterals_enum_1.ECollaterals.INVENTORY);
    const bbcSheetIds = bbcSheets.map((sheet) => sheet._id);
    return InventoryItem_model_1.InventoryItemModel.aggregate([
        {
            $match: {
                bbcSheetId: { $in: bbcSheetIds },
            },
        },
        ...collaterals_db_1.COLLATERALS_LOOKUP,
        {
            $group: {
                '_id': '$sku',
                'unitCost': { $first: '$unitCost' },
                'qty': { $first: '$qty' },
                'value': { $first: '$value' },
            },
        },
        { $sort: { _id: -1 } },
    ]);
};
exports.getSKUQtyValueUnitCost = getSKUQtyValueUnitCost;
const getMovementDifference = async (skus, BBCs) => {
    if (skus) {
        const groupedBbc = skus.map((sku) => {
            let minUnitCost = 0;
            const totalSum = BBCs.map((bbc) => {
                const values = bbc.items
                    .filter((item) => item.sku === sku)
                    .map((item) => item.unitCost);
                if (values.length) {
                    minUnitCost = Math.min(...values);
                }
                const sum = bbc.items.reduce((acc, item) => {
                    if (item.sku === sku) {
                        return acc + item.qty;
                    }
                    return acc;
                }, 0);
                return { bbc: bbc.bbcDate, sum };
            });
            return { sku, totalSum, minUnitCost };
        });
        const groupedBbcWithDifferences = groupedBbc.map((group) => {
            const differences = [];
            group.totalSum.forEach((sumGroup, index) => {
                if (index > 0) {
                    differences.push({
                        bbc: sumGroup.bbc,
                        diff: group.totalSum[index - 1].sum - sumGroup.sum,
                        previousValue: group.totalSum[index - 1].sum,
                        currentValue: sumGroup.sum,
                    });
                }
            });
            return { ...group, differences };
        });
        const reportAdditions = [];
        const reportRemoved = [];
        groupedBbcWithDifferences.forEach((group) => {
            const totalDifference = group.differences.reduce((acc, g) => {
                if (g.diff > 0) {
                    const diff = acc.increasesOverPeriod + g.diff;
                    return {
                        ...acc,
                        increasesOverPeriod: diff,
                        previousValue: g.previousValue,
                        currentValue: g.currentValue,
                    };
                }
                else {
                    const diff = acc.decreasesOverPeriod + Math.abs(g.diff);
                    return {
                        ...acc,
                        decreasesOverPeriod: diff,
                        previousValue: g.previousValue,
                        currentValue: g.currentValue,
                    };
                }
            }, { increasesOverPeriod: 0, decreasesOverPeriod: 0, previousValue: 0, currentValue: 0 });
            const { increasesOverPeriod, decreasesOverPeriod, previousValue, currentValue } = totalDifference;
            if (increasesOverPeriod === 0 && decreasesOverPeriod === 0) {
                return;
            }
            if (increasesOverPeriod > 0) {
                reportRemoved.push({
                    sku: group.sku,
                    units: increasesOverPeriod,
                    value: increasesOverPeriod * group.minUnitCost,
                    previousValue: previousValue,
                    currentValue: currentValue,
                });
            }
            if (decreasesOverPeriod > 0) {
                reportAdditions.push({
                    sku: group.sku,
                    units: decreasesOverPeriod,
                    value: decreasesOverPeriod * group.minUnitCost,
                    previousValue: previousValue,
                    currentValue: currentValue,
                });
            }
        });
        return {
            reportAdditions: lodash_1.default.orderBy(reportAdditions, ['sku'], ['asc']),
            reportRemoved: lodash_1.default.orderBy(reportRemoved, ['sku'], ['asc']),
        };
    }
    return { reportAdditions: [], reportRemoved: [] };
};
const getInventoryMovement = async (borrowerId, startDate, endDate) => {
    const bbcDates = await (0, bbcDates_db_1.getBBCDatesForPeriod)(borrowerId, new Date(startDate), new Date(endDate));
    const bbcIds = bbcDates.map((bbc) => String(bbc._id));
    const bbcSheets = await (0, bbcSheets_db_1.getBBCSheetsByType)(bbcIds, collaterals_enum_1.ECollaterals.INVENTORY);
    const skuGroups = await (0, exports.getAllUniqSKUInRangeNew)(bbcSheets.map((bbcSheet) => String(bbcSheet._id)));
    if (skuGroups.length > 0) {
        const { skus } = skuGroups.pop();
        const BBCs = await (0, collaterals_db_1.getCollateralDocsByBBC)(bbcIds, collaterals_enum_1.ECollaterals.INVENTORY);
        return await getMovementDifference(skus, BBCs);
    }
    return { reportAdditions: [], reportRemoved: [] };
};
exports.getInventoryMovement = getInventoryMovement;
