"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CollateralsService = void 0;
const mongoose_1 = __importDefault(require("mongoose"));
const lodash_1 = __importDefault(require("lodash"));
const collaterals_enum_1 = require("../enums/collaterals.enum");
const BBCDate_model_1 = require("../models/BBCDate.model");
const BBCSheet_model_1 = require("../models/BBCSheet.model");
const bbcDates_db_1 = require("../db/bbcDates.db");
const bbcSheets_db_1 = require("../db/bbcSheets.db");
const collaterals_db_1 = require("../db/collaterals.db");
const numbers_helper_1 = require("../helpers/numbers.helper");
const enums_helper_1 = require("../helpers/enums.helper");
class CollateralsService {
    _groupsService;
    _uploadsService;
    constructor(_groupsService, _uploadsService) {
        this._groupsService = _groupsService;
        this._uploadsService = _uploadsService;
    }
    async findCollateralsByType(bbcDateId, collateralType) {
        const sheets = await this.findCollateralSheets(bbcDateId, collateralType);
        return (await Promise.all(sheets.map(async (sheet) => {
            return await this.getCollateralsBySheet(sheet);
        })))
            .reduce((acc, group) => [...acc, ...group], []);
    }
    async findCollaterals(collateralsId, group, paginatorOptions) {
        const sheet = await this.findCollateralSheetsById(collateralsId);
        if (group) {
            return await this.getCollateralsBySheet(sheet, paginatorOptions);
        }
        return await (0, collaterals_db_1.getCollateralListBySheetId)(sheet, paginatorOptions);
    }
    async countCollateralItems(bbcSheetId) {
        const sheet = await this.findCollateralSheetsById(bbcSheetId);
        return await this.getCollateralItemTotal(sheet);
    }
    async findCollateralSheets(bbcDateId, collateralType) {
        return BBCSheet_model_1.BBCSheetModel.find({ bbcDateId, dataType: collateralType });
    }
    async findCollateralSheetsById(collateralsId) {
        return BBCSheet_model_1.BBCSheetModel.findById(collateralsId);
    }
    async findCollateralSheetByIdWithBBCDate(collateralsId) {
        const bbcSheet = await BBCSheet_model_1.BBCSheetModel.aggregate([
            {
                $match: {
                    '_id': new mongoose_1.default.Types.ObjectId(collateralsId),
                },
            }, {
                $lookup: {
                    'from': 'bbcdates',
                    'localField': 'bbcDateId',
                    'foreignField': '_id',
                    'as': 'bbcDate',
                },
            }, {
                $unwind: {
                    'path': '$bbcDate',
                },
            },
        ]);
        return bbcSheet.length ? bbcSheet[0] : null;
    }
    async findAllCollaterals(borrowerId, collateralTypes) {
        return (0, bbcDates_db_1.getBBCDatesByType)(borrowerId, collateralTypes);
    }
    async saveCollateralItems(uploadedItems, collateralType, shift = 0) {
        const bbcDates = await (0, bbcDates_db_1.getBBCDates)(uploadedItems.borrowerId, uploadedItems.bbcDate);
        const bbcSheets = await (0, bbcSheets_db_1.getBBCSheetsByType)(bbcDates.map((bbcDate) => String(bbcDate._id)), collateralType);
        const lastBBCDate = bbcDates.pop();
        const lastBBCSheet = bbcSheets.find((bbcSheet) => (bbcSheet.fileName === uploadedItems.fileName) && (bbcSheet.sheetName === uploadedItems.sheetName));
        let savedBBCDate;
        if (!lastBBCDate) {
            const newBBCDate = new BBCDate_model_1.BBCDateModel({
                borrowerId: uploadedItems.borrowerId,
                bbcDate: uploadedItems.bbcDate,
            });
            savedBBCDate = await newBBCDate.save();
        }
        else {
            savedBBCDate = lastBBCDate;
        }
        let savedBBCSheet;
        if (!lastBBCSheet) {
            const newBBCSheet = new BBCSheet_model_1.BBCSheetModel({
                bbcDateId: savedBBCDate._id,
                dataType: collateralType,
                fileName: uploadedItems.fileName,
                sheetName: uploadedItems.sheetName,
            });
            savedBBCSheet = await newBBCSheet.save();
        }
        else {
            savedBBCSheet = bbcSheets.pop();
        }
        const orderedItems = uploadedItems.items.map((item, index) => ({
            ...item,
            order: index + shift,
        }));
        await Promise.all(orderedItems.map(async (item) => {
            const newCollateralItem = new collaterals_db_1.collateralMap[collateralType]({
                bbcSheetId: savedBBCSheet._id,
                order: item.order,
                ...item,
            });
            await newCollateralItem.save();
        }));
        return savedBBCDate._id;
    }
    async getCollateralsBySheet(sheet, paginatorOptions) {
        const groupFields = {
            bbcDate: 'bbc.bbcDate',
            borrowerId: 'bbc.borrowerId',
            fileName: 'bbcSheet.fileName',
            sheetName: 'bbcSheet.sheetName',
        };
        const { groupQueries, itemQueries, enumKey } = (0, collaterals_db_1.createQuery)(groupFields, sheet.dataType);
        const groupingQuery = { _id: '$bbcSheetId', ...groupQueries, items: { $push: itemQueries } };
        const collateralSheets = await collaterals_db_1.collateralMap[enumKey].aggregate([
            {
                $match: {
                    'bbcSheetId': sheet._id,
                },
            },
            ...collaterals_db_1.COLLATERALS_LOOKUP,
            {
                $sort: {
                    order: 1,
                },
            },
            ...(0, collaterals_db_1.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;
    }
    async getCollateralItemTotal(sheet) {
        const enumKey = (0, enums_helper_1.getEnumKeyByEnumValue)(collaterals_enum_1.ECollaterals, sheet.dataType);
        return collaterals_db_1.collateralMap[enumKey].countDocuments({
            'bbcSheetId': sheet._id,
        });
    }
    getCollateralsBenford(collaterals) {
        if (collaterals.length === 0) {
            return [];
        }
        const eachInventoryBenfordResult = [];
        collaterals[0]?.digitArrays.forEach((lastDigitsArray) => {
            const digitsArrayWithoutZeros = lastDigitsArray.filter((digit) => digit !== '0');
            const results = [];
            const firstDigitFrequencies = (0, numbers_helper_1.getDigitsFrequencies)(lastDigitsArray);
            for (let n = 1; n <= 9; n++) {
                const dataFrequency = firstDigitFrequencies[n];
                const dataFrequencyPercent = (dataFrequency / digitsArrayWithoutZeros.length) * 100;
                const dataFrequencyTotal = isNaN(dataFrequencyPercent) ? 0 : Math.round(dataFrequencyPercent * 100) / 100;
                results.push(dataFrequencyTotal);
            }
            eachInventoryBenfordResult.push(results);
        });
        return {
            _id: collaterals[0]._id,
            bbcDates: collaterals[0].bbcDates,
            confirmed: eachInventoryBenfordResult,
        };
    }
    async countCollateralDocsByBBC(bbcIds, collateralType) {
        const bbcSheets = await (0, bbcSheets_db_1.getBBCSheetsByType)(bbcIds, collateralType);
        const collateralModel = collaterals_db_1.collateralMap[collateralType];
        if (!collateralModel) {
            console.error(`Could not find a model for ${collateralType}`);
            return 0;
        }
        return collateralModel.countDocuments({
            'bbcSheetId': { $in: bbcSheets.map((bbcSheet) => bbcSheet._id) },
        });
    }
    excludeNoDataColumns(data, columns) {
        return data.map((dataRow) => lodash_1.default.pick(dataRow, columns));
    }
    async addCustomerGroups(data, borrowerId) {
        const groupName = 'customers';
        const groups = await this._groupsService.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,
            };
        });
    }
    async getLatestBBC(borrowerId, bbcDate = new Date()) {
        const bbcDateDocs = await BBCDate_model_1.BBCDateModel.aggregate([
            {
                $match: {
                    'borrowerId': new mongoose_1.default.Types.ObjectId(borrowerId),
                    'bbcDate': { $lte: bbcDate },
                },
            }, {
                $sort: {
                    'bbcDate': -1,
                },
            }, {
                $limit: 1,
            },
        ]);
        if (bbcDateDocs.length === 0) {
            return null;
        }
        return bbcDateDocs[0];
    }
    async gebNextBBC(borrowerId, bbcDate = new Date()) {
        return BBCDate_model_1.BBCDateModel.aggregate([
            {
                $match: {
                    'borrowerId': new mongoose_1.default.Types.ObjectId(borrowerId),
                    'bbcDate': { $gte: bbcDate },
                },
            }, {
                $sort: {
                    'bbcDate': -1,
                },
            },
        ]);
    }
    async getLatestBBCDate(borrowerId) {
        const latestBBC = await this.getLatestBBC(borrowerId);
        if (!latestBBC) {
            return { lastBBCDate: null, lastBBCId: null };
        }
        return { lastBBCDate: latestBBC.bbcDate, lastBBCId: latestBBC._id.toString() };
    }
    async createBBCDate(bbcDate) {
        if (bbcDate.inventory || bbcDate.receivables) {
            const existingBbcDates = await (0, bbcDates_db_1.getBBCDates)(bbcDate.borrowerId, bbcDate.date);
            let existingBbcDate = existingBbcDates.length > 0 ? existingBbcDates[0] : null;
            if (!existingBbcDate) {
                existingBbcDate = await (0, bbcDates_db_1.createBBCDate)(bbcDate.borrowerId, bbcDate.date);
            }
            if (bbcDate.inventory) {
                await (0, bbcSheets_db_1.createBBCSheet)(existingBbcDate._id.toString(), 'INVENTORY');
            }
            if (bbcDate.receivables) {
                await (0, bbcSheets_db_1.createBBCSheet)(existingBbcDate._id.toString(), 'RECEIVABLE');
            }
        }
    }
    async deleteCollateralById(collateralId) {
        const results = await BBCSheet_model_1.BBCSheetModel.findByIdAndDelete(collateralId);
        setTimeout(async () => await this._uploadsService.removeEmptyBBC(true), 500);
        return results;
    }
}
exports.CollateralsService = CollateralsService;
