"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getInventoryTurn = exports.getInventoryTurnFull = void 0;
const decimal_js_1 = __importDefault(require("decimal.js"));
const dayjs_1 = __importDefault(require("dayjs"));
const bbcDates_db_1 = require("../../db/bbcDates.db");
const bbcSheets_db_1 = require("../../db/bbcSheets.db");
const collaterals_enum_1 = require("../../enums/collaterals.enum");
const collaterals_db_1 = require("../../db/collaterals.db");
const excel_helper_1 = require("../../helpers/excel.helper");
const inventories_db_1 = require("../../db/inventories.db");
const getInventoryTurnFull = async (params) => {
    const { tableByUnit, tableByValue } = await (0, exports.getInventoryTurn)(params);
    const headerByUnit = getInventoryTurnHeader('byUnit');
    const headerByValue = getInventoryTurnHeader('byValue');
    const tableByUnitFull = (0, excel_helper_1.addHeaderToData)(headerByUnit, tableByUnit);
    const tableByValueFull = (0, excel_helper_1.addHeaderToData)(headerByValue, tableByValue);
    return { 'by unit': tableByUnitFull, 'by value': tableByValueFull };
};
exports.getInventoryTurnFull = getInventoryTurnFull;
const getInventoryTurn = async (params) => {
    const { borrowerId, startDate, endDate } = params;
    const bbcDates = await (0, bbcDates_db_1.getBBCDatesForPeriod)(String(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 skuGroup = (await (0, inventories_db_1.getAllUniqSKUInRangeNew)(bbcSheets.map((bbcSheet) => String(bbcSheet._id)))).pop();
    const BBCs = await (0, collaterals_db_1.getCollateralDocsByBBC)(bbcIds, collaterals_enum_1.ECollaterals.INVENTORY);
    return getDifference(skuGroup ? skuGroup.skus.sort() : [], BBCs);
};
exports.getInventoryTurn = getInventoryTurn;
const getDifference = (uniqSKUs, BBCs) => {
    if (uniqSKUs) {
        const groupedBbc = uniqSKUs.map((sku) => {
            let minUnitCost = 0;
            const totalSum = BBCs.map((bbc) => {
                const skuItems = bbc.items.filter((item) => item.sku === sku);
                const unitCosts = skuItems.map((item) => item.qty === 0 ? 0 : new decimal_js_1.default(item.value).div(item.qty).toNumber());
                if (unitCosts.length) {
                    minUnitCost = Math.min(...unitCosts);
                }
                const sum = skuItems.reduce((acc, item) => new decimal_js_1.default(acc).add(item.qty).toNumber(), 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) {
                    const firstDate = (0, dayjs_1.default)(group.totalSum[index - 1].bbc);
                    const lastDate = (0, dayjs_1.default)(sumGroup.bbc);
                    const diffDays = lastDate.diff(firstDate, 'day');
                    const diff = new decimal_js_1.default(group.totalSum[index - 1].sum).sub(sumGroup.sum).toNumber();
                    const diffPerDay = diffDays > 0 ? new decimal_js_1.default(diff).div(diffDays).toNumber() : 0;
                    differences.push({
                        bbc: sumGroup.bbc,
                        diff,
                        diffDays,
                        decreasePerDay: diffPerDay > 0 ? diffPerDay : 0,
                        increasePerDay: diffPerDay < 0 ? diffPerDay : 0,
                    });
                }
            });
            return { ...group, differences };
        });
        const tableByUnit = [];
        groupedBbcWithDifferences.forEach((group) => {
            const totalDifference = group.differences.reduce((acc, group) => {
                if (group.diff < 0) {
                    const diff = new decimal_js_1.default(acc.increasesOverPeriod).add(group.diff).toNumber();
                    return { ...acc, increasesOverPeriod: diff };
                }
                else {
                    const diff = new decimal_js_1.default(acc.decreasesOverPeriod).add(Math.abs(group.diff)).toNumber();
                    return { ...acc, decreasesOverPeriod: diff };
                }
            }, { increasesOverPeriod: 0, decreasesOverPeriod: 0 });
            const { increasesOverPeriod, decreasesOverPeriod } = totalDifference;
            const current = group.totalSum[group.totalSum.length - 1].sum;
            const firstDate = (0, dayjs_1.default)(group.totalSum[0].bbc);
            const lastDate = (0, dayjs_1.default)(group.totalSum[group.totalSum.length - 1].bbc);
            const dayInRange = lastDate.diff(firstDate, 'day');
            const averageIncreasesPerDay = new decimal_js_1.default(increasesOverPeriod).div(dayInRange).toNumber();
            const averageDecreasesPerDay = new decimal_js_1.default(decreasesOverPeriod).div(dayInRange).toNumber();
            // const increaseDiffs = group.differences.filter((diff) => diff.increasePerDay < 0);
            // const decreaseDiffs = group.differences.filter((diff) => diff.decreasePerDay > 0);
            // const averageIncreasePerDay_test = increaseDiffs.length > 0
            //   ? new Decimal(increaseDiffs.reduce((acc, diff) => new Decimal(diff.increasePerDay).add(acc).toNumber(), 0)).div(decreaseDiffs.length).toNumber()
            //   : 0;
            // const averageDecreasesPerDay_test = decreaseDiffs.length > 0
            //   ? new Decimal(decreaseDiffs.reduce((acc, diff) => new Decimal(diff.decreasePerDay).add(acc).toNumber(), 0)).div(decreaseDiffs.length).toNumber()
            //   : 0;
            const daysToClear = averageDecreasesPerDay === 0
                ? 0
                : new decimal_js_1.default(current).div(averageDecreasesPerDay).toDP().toNumber();
            const ranking = averageDecreasesPerDay === 0
                ? Math.round(averageIncreasesPerDay)
                : new decimal_js_1.default(averageIncreasesPerDay).div(averageDecreasesPerDay).toDP().toNumber();
            tableByUnit.push({
                sku: group.sku,
                current,
                minUnitCost: group.minUnitCost,
                increasesOverPeriod,
                decreasesOverPeriod,
                averageIncreasesPerDay,
                averageDecreasesPerDay,
                daysToClear,
                ranking,
            });
        });
        tableByUnit.sort((a, b) => a.ranking > b.ranking ? -1 : 0);
        const tableByValue = [];
        tableByUnit.forEach((unit) => {
            const minUnitCost = unit.minUnitCost;
            const current = new decimal_js_1.default(unit.current).mul(minUnitCost).toNumber();
            const increasesOverPeriod = new decimal_js_1.default(unit.increasesOverPeriod).mul(minUnitCost).toNumber();
            const decreasesOverPeriod = new decimal_js_1.default(unit.decreasesOverPeriod).mul(minUnitCost).toNumber();
            const averageIncreasesPerDay = new decimal_js_1.default(unit.averageIncreasesPerDay).mul(minUnitCost).toNumber();
            const averageDecreasesPerDay = new decimal_js_1.default(unit.averageDecreasesPerDay).mul(minUnitCost).toNumber();
            const daysToClear = Math.round(new decimal_js_1.default(unit.daysToClear).mul(minUnitCost).toNumber());
            const ranking = Math.round(new decimal_js_1.default(unit.ranking).mul(minUnitCost).toNumber());
            tableByValue.push({
                sku: unit.sku,
                minUnitCost,
                current,
                increasesOverPeriod,
                decreasesOverPeriod,
                averageIncreasesPerDay,
                averageDecreasesPerDay,
                daysToClear,
                ranking,
            });
        });
        return { tableByUnit, tableByValue };
    }
    return { tableByUnit: [], tableByValue: [] };
};
const getInventoryTurnHeader = (type) => {
    const headerMap = {
        'byUnit': {
            sku: 'SKU',
            current: 'Current number of units',
            increasesOverPeriod: 'Increases in units over period',
            decreasesOverPeriod: 'Decreases in units over period',
            averageIncreasesPerDay: 'Average increases in units per day',
            averageDecreasesPerDay: 'Average decreases in units per day',
            daysToClear: 'Days to clear',
            ranking: 'Ranking',
        },
        'byValue': {
            sku: 'SKU',
            current: 'Current value',
            minUnitCost: 'Min unit cost',
            increasesOverPeriod: 'Increases over in value period',
            decreasesOverPeriod: 'Decreases over in value period',
            averageIncreasesPerDay: 'Average value increases per day',
            averageDecreasesPerDay: 'Average value decreases per day',
            daysToClear: 'Days to clear',
            ranking: 'Ranking',
        },
    };
    return headerMap[type];
};
