"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.EquipmentService = void 0;
const decimal_js_1 = __importDefault(require("decimal.js"));
const dayjs_1 = __importDefault(require("dayjs"));
const equipment_types_enum_1 = require("../enums/equipment-types.enum");
const BBCDate_model_1 = require("../models/BBCDate.model");
const equipment_db_1 = require("../db/equipment.db");
class EquipmentService {
    lockService;
    constructor(lockService) {
        this.lockService = lockService;
    }
    async getEquipmentDates(borrowerId) {
        const equipments = await (0, equipment_db_1.getEquipmentDates)(borrowerId);
        return equipments.map((equipment) => (0, dayjs_1.default)(equipment.date).format('YYYY-MM-DD'));
    }
    async getEquipmentForDate(borrowerId, date) {
        const equipment = await (0, equipment_db_1.getEquipment)(borrowerId, date);
        if (!equipment) {
            const lastItems = [];
            const summary = this.calculateSummary(lastItems);
            return await (0, equipment_db_1.copyEquipmentWithoutSaving)(borrowerId, date, lastItems, summary);
        }
        return equipment;
    }
    async getLatestEquipmentForDate(borrowerId, date) {
        const equipment = await (0, equipment_db_1.getLatestEquipments)(borrowerId, date);
        if (!equipment.length) {
            const lastItems = [];
            const summary = this.calculateSummary(lastItems);
            return await (0, equipment_db_1.copyEquipmentWithoutSaving)(borrowerId, date, lastItems, summary);
        }
        return equipment[0];
    }
    async getEquipmentSummaryForProduct(borrowerId, date, productId) {
        const equipment = await (0, equipment_db_1.getEquipment)(borrowerId, date);
        const lastItems = equipment
            ? equipment.items.filter((item) => item?.productId?.toString() === productId)
            : [];
        return this.calculateSummary(lastItems);
    }
    async getEquipmentForBBC(bbcDateId) {
        if (!bbcDateId) {
            return null;
        }
        const bbcDateDoc = await BBCDate_model_1.BBCDateModel.findById(bbcDateId).lean();
        const { bbcDate, borrowerId } = bbcDateDoc;
        const equipmentDocs = await (0, equipment_db_1.getLatestEquipments)(borrowerId.toString(), bbcDate);
        if (equipmentDocs.length) {
            return equipmentDocs.pop();
        }
        const emptySummary = this.calculateSummary([]);
        return { borrowerId, date: bbcDate, items: [], summary: emptySummary };
    }
    async saveAndReturnEquipment(borrowerId, date, items) {
        const isBBCLockedResult = await this.lockService.isDateLocked(date, borrowerId);
        if (isBBCLockedResult) {
            return null;
        }
        const summary = this.calculateSummary(items);
        return await (0, equipment_db_1.saveEquipmentDoc)(borrowerId, date, items, summary);
    }
    async deleteEquipment(borrowerId, date) {
        const isBBCLockedResult = await this.lockService.isDateLocked(date, borrowerId);
        if (isBBCLockedResult) {
            return;
        }
        await (0, equipment_db_1.deleteEquipment)(borrowerId, date);
    }
    async getLastCopyEquipmentItems(borrowerId, date) {
        const equipment = await (0, equipment_db_1.getLatestEquipments)(borrowerId, date);
        if (equipment.length) {
            return equipment.pop().items;
        }
        return [];
    }
    calculateSummary(equipmentItems) {
        const netTotalTypes = [equipment_types_enum_1.EEquipmentTypes.EQUIPMENT, equipment_types_enum_1.EEquipmentTypes.REAL_ESTATE, equipment_types_enum_1.EEquipmentTypes.BOOT_COLLATERAL];
        const summary = [];
        const result = Object.keys(equipment_types_enum_1.EEquipmentTypes).map((equipmentType) => {
            const typeSummary = { rowDef: equipmentType, amount: 0, advanceRate: 0, availability: 0 };
            equipmentItems.forEach((item) => {
                if (item.type === equipmentType) {
                    typeSummary.amount = new decimal_js_1.default(typeSummary.amount).add(item.amount ?? 0).toNumber();
                    typeSummary.availability = new decimal_js_1.default(item.advanceRate ?? 0).mul(item.amount ?? 0).add(typeSummary.availability ?? 0).toNumber();
                    typeSummary.advanceRate = typeSummary.amount === 0 ? 0 : new decimal_js_1.default(typeSummary.availability ?? 0).div(typeSummary.amount ?? 0).toDP(4).toNumber();
                }
                return typeSummary;
            }, typeSummary);
            return typeSummary;
        });
        netTotalTypes.forEach((type) => {
            summary.push(...result.filter((r) => r.rowDef === type));
        });
        const calculateSummaryField = (acc, item) => {
            acc.amount = new decimal_js_1.default(acc.amount).add(item.amount).toNumber();
            acc.availability = new decimal_js_1.default(acc.availability).add(item.availability).toNumber();
            acc.advanceRate = acc.amount === 0 ? 0 : new decimal_js_1.default(acc.availability).div(acc.amount).toDP(4).toNumber();
            return acc;
        };
        const netTotal = result.reduce((acc, e) => {
            if (netTotalTypes.includes(e.rowDef)) {
                acc = calculateSummaryField(acc, e);
            }
            return acc;
        }, { rowDef: 'netTotal', amount: 0, advanceRate: 0, availability: 0 });
        summary.push(netTotal);
        summary.push(...result.filter((r) => r.rowDef === equipment_types_enum_1.EEquipmentTypes.INTELLECTUAL_PROPERTY));
        const grossTotal = result.reduce((acc, e) => {
            return calculateSummaryField(acc, e);
        }, { rowDef: 'grossTotal', amount: 0, advanceRate: 0, availability: 0 });
        summary.push(grossTotal);
        return summary.reduce((acc, s) => ({ ...acc, [s.rowDef]: s }), {});
    }
}
exports.EquipmentService = EquipmentService;
