"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.InventoryAvailabilityService = void 0;
const decimal_js_1 = __importDefault(require("decimal.js"));
const lodash_1 = __importDefault(require("lodash"));
const mongoose_1 = __importDefault(require("mongoose"));
const inventory_availability_db_1 = require("../db/inventory-availability.db");
const bbcDates_db_1 = require("../db/bbcDates.db");
const BBCDate_model_1 = require("../models/BBCDate.model");
const inventory_availability_results_enum_1 = require("../enums/inventory-availability-results.enum");
const InventoryAvailability_model_1 = require("../models/InventoryAvailability.model");
const inventory_availability_1 = require("../db/inventory-availability");
const availability_service_1 = require("./availability.service");
class InventoryAvailabilityService {
    manualEntryService;
    constructor(manualEntryService) {
        this.manualEntryService = manualEntryService;
    }
    async getLatestBBCFilters(excludedBBCDateId) {
        const bbcDateDoc = await BBCDate_model_1.BBCDateModel.findById(excludedBBCDateId).lean();
        if (!bbcDateDoc) {
            return [];
        }
        const latestBBCDate = await BBCDate_model_1.BBCDateModel.aggregate([
            {
                $match: {
                    '_id': { $ne: new mongoose_1.default.Types.ObjectId(excludedBBCDateId) },
                    'borrowerId': new mongoose_1.default.Types.ObjectId(bbcDateDoc.borrowerId),
                },
            }, {
                $sort: {
                    'bbcDate': -1,
                },
            },
        ]);
        if (latestBBCDate.length === 0) {
            return [];
        }
        for (const bbcDate of latestBBCDate) {
            const availability = await this.getInventoryAvailabilityFilters(bbcDate._id.toString());
            if (!!availability) {
                return availability.filters;
            }
        }
        return [];
    }
    async getInventoryAvailability(bbcDateId, paginators) {
        const availability = await this.getInventoryAvailabilityFilters(bbcDateId);
        const { borrowerId } = await (0, bbcDates_db_1.getBBCDateDoc)(bbcDateId);
        if (!availability) {
            const lastFilters = await this.getLatestBBCFilters(bbcDateId);
            const newAvailability = {
                bbcDateId: new mongoose_1.default.Types.ObjectId(bbcDateId),
                borrowerId: new mongoose_1.default.Types.ObjectId(borrowerId),
                filters: lastFilters,
                options: { maxAdvanceRatePriority: true },
                useManualInputs: false,
                results: {
                    [inventory_availability_results_enum_1.EInventoryAvailabilityResults.UNIQ_ITEMS]: {
                        items: [],
                        totalItems: 0,
                        paginatorOptions: paginators[inventory_availability_results_enum_1.EInventoryAvailabilityResults.UNIQ_ITEMS],
                    },
                    [inventory_availability_results_enum_1.EInventoryAvailabilityResults.NON_UNIQ_ITEMS]: {
                        items: [],
                        totalItems: 0,
                        paginatorOptions: paginators[inventory_availability_results_enum_1.EInventoryAvailabilityResults.NON_UNIQ_ITEMS],
                    },
                    [inventory_availability_results_enum_1.EInventoryAvailabilityResults.NOT_MATCHED_ITEMS]: {
                        items: [],
                        totalItems: 0,
                        paginatorOptions: paginators[inventory_availability_results_enum_1.EInventoryAvailabilityResults.NOT_MATCHED_ITEMS],
                    },
                },
                summary: [],
            };
            return newAvailability;
        }
        const items = await (0, inventory_availability_1.getInventoryAvailabilityItems)(String(availability._id), paginators);
        availability.results = { ...availability.results, ...items };
        return availability;
    }
    async getInventoryAvailabilityFilters(bbcDateId) {
        return await (0, inventory_availability_db_1.getInventoryAvailabilityByBBCDateId)(bbcDateId);
    }
    async updateInventoryAvailabilityFilters(inventoryAvailability) {
        return await (0, inventory_availability_1.createInventoryAvailability)(inventoryAvailability);
    }
    async getAllInventorySettings(bbcDateId = null, borrowerId) {
        const availabilities = await InventoryAvailability_model_1.InventoryAvailabilityModel.aggregate([
            {
                $match: {
                    $and: [
                        { 'borrowerId': new mongoose_1.default.Types.ObjectId(borrowerId) },
                        { 'bbcDateId': { '$ne': new mongoose_1.default.Types.ObjectId(bbcDateId) } },
                    ],
                },
            },
        ]);
        return availabilities.reduce((acc, availability) => {
            const settings = lodash_1.default.pick(availability, ['filters', 'options']);
            return { ...acc, [availability.bbcDateId.toString()]: settings };
        }, {});
    }
    async checkCreateAvailability(bbcDateId) {
        const inventoryAvailability = await (0, inventory_availability_db_1.getInventoryAvailabilityByBBCDateId)(bbcDateId);
        if (inventoryAvailability) {
            return;
        }
        const newAvailability = await this.getInventoryAvailability(bbcDateId, availability_service_1.START_PAGINATORS);
        if (newAvailability) {
            await (0, inventory_availability_1.createInventoryAvailability)(newAvailability);
        }
    }
    async toggleManualInventoryAvailability(bbcDateId, useManualInputs) {
        await this.checkCreateAvailability(bbcDateId);
        await (0, inventory_availability_db_1.setManualInputsToggle)(bbcDateId, useManualInputs);
        const inventoryAvailability = await (0, inventory_availability_db_1.getInventoryAvailabilityByBBCDateId)(bbcDateId);
        if (!inventoryAvailability) {
            return;
        }
        if (useManualInputs) {
            const manualRates = await this.manualEntryService.getInventoryManualEntry(bbcDateId);
            const summaryTotal = {
                advanceRate: 0,
                availability: 0,
                inventoryName: 'TOTAL',
                isGroup: false,
                order: 1000,
                totalQty: 0,
                totalValue: 0,
            };
            const newSummary = manualRates.items.map((item, order) => {
                return {
                    order,
                    isGroup: false,
                    inventoryName: item.inventoryName,
                    totalQty: item.totalQty,
                    totalValue: item.totalValue,
                    advanceRate: new decimal_js_1.default(item.advanceRate).div(100).toDP(2).toNumber(),
                    availability: item.availability,
                };
            });
            const updateSummaryTotal = (summaryTotal, item) => {
                summaryTotal.availability += item.availability;
                summaryTotal.totalQty += item.totalQty;
                summaryTotal.totalValue += item.totalValue;
                if (summaryTotal.totalValue) {
                    summaryTotal.advanceRate = summaryTotal.availability / summaryTotal.totalValue;
                }
                else {
                    summaryTotal.advanceRate = 0;
                }
            };
            newSummary.forEach((item) => updateSummaryTotal(summaryTotal, item));
            summaryTotal.availability = new decimal_js_1.default(summaryTotal.availability).toDP(2).toNumber();
            summaryTotal.totalQty = new decimal_js_1.default(summaryTotal.totalQty).toDP(2).toNumber();
            summaryTotal.totalValue = new decimal_js_1.default(summaryTotal.totalValue).toDP(2).toNumber();
            summaryTotal.advanceRate = new decimal_js_1.default(summaryTotal.advanceRate).toDP(2).toNumber();
            await (0, inventory_availability_db_1.saveInventoryAvailabilitySummary)(String(inventoryAvailability._id), [...newSummary, summaryTotal]);
        }
        else {
            await (0, inventory_availability_db_1.saveInventoryAvailabilitySummary)(String(inventoryAvailability._id), []);
        }
    }
}
exports.InventoryAvailabilityService = InventoryAvailabilityService;
