"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CashAllocationService = void 0;
const main_helper_1 = require("../helpers/main.helper");
const CashAllocationReference_model_1 = require("../models/CashAllocationReference.model");
const CashAllocationProduct_model_1 = require("../models/CashAllocationProduct.model");
class CashAllocationService {
    async createCashAllocation(transactions) {
        const newReferencesSet = new Set(transactions.map((transaction) => transaction.reference.toLowerCase()));
        const newReferences = Array.from(newReferencesSet);
        const foundCashAllocation = await this.getCashAllocationsByReferences(newReferences);
        const excludedReferences = foundCashAllocation.map((allocation) => allocation.reference.toLowerCase());
        const createdReferences = newReferences.filter((r) => !excludedReferences.includes(r));
        const createdTransactions = createdReferences.reduce((acc, cur) => {
            const newTransactions = transactions.find((tr) => tr.reference.toLowerCase() === cur);
            return [...acc, newTransactions];
        }, []);
        const order = await this.getNextOrder();
        await Promise.all(createdTransactions.map(async (transactions) => {
            if (excludedReferences.includes(transactions.reference.toLowerCase())) {
                return;
            }
            if (!newReferencesSet.has(transactions.reference.toLowerCase())) {
                return;
            }
            const cashAllocation = {
                uiId: (0, main_helper_1.getUUID)(),
                order,
                reference: transactions.reference.trim(),
                cashAllocationProductId: null,
            };
            const newCashAllocationReference = new CashAllocationReference_model_1.CashAllocationReference(cashAllocation);
            await newCashAllocationReference.save();
            newReferencesSet.delete(transactions.reference.toLowerCase());
        }));
    }
    async getNextOrder() {
        const lastOrder = await CashAllocationReference_model_1.CashAllocationReference.findOne().sort({ order: -1 }).select('order').lean();
        return lastOrder ? lastOrder.order + 1 : 0;
    }
    async getCashAllocationsByReferences(references) {
        return CashAllocationReference_model_1.CashAllocationReference
            .find({ reference: { $in: references.map(ref => new RegExp(`^${ref}$`, 'i')) } })
            .lean();
    }
    async getAllCashAllocations() {
        const cashAllocationReferences = await CashAllocationReference_model_1.CashAllocationReference
            .find()
            .sort({ order: 1 });
        const cashAllocationsProducts = await CashAllocationProduct_model_1.CashAllocationProduct
            .find()
            .sort({ order: 1 });
        return {
            references: cashAllocationReferences.map((i) => (0, main_helper_1.removeFields)(i, main_helper_1.fieldsToUnset)),
            products: cashAllocationsProducts.map((i) => (0, main_helper_1.removeFields)(i, main_helper_1.fieldsToUnset)),
        };
    }
    async updateAllCashAllocation(products, references) {
        const existingCashAllocations = await this.getAllCashAllocations();
        const existingCashAllocationProductIds = existingCashAllocations.products.map((i) => i._id.toString());
        const cashAllocationProductsToDelete = existingCashAllocationProductIds.filter((id) => !products.some((i) => i._id === id));
        await CashAllocationProduct_model_1.CashAllocationProduct.deleteMany({ _id: { $in: cashAllocationProductsToDelete } });
        const newProductsMap = new Map();
        await Promise.all(products.map(async (product, order) => {
            const { _id, ...update } = product;
            if (_id.includes('new_')) {
                const newCashAllocationProduct = new CashAllocationProduct_model_1.CashAllocationProduct({ ...update, order });
                const createdCashAllocationProduct = await newCashAllocationProduct.save();
                newProductsMap.set(_id, createdCashAllocationProduct._id.toString());
            }
            else {
                await CashAllocationProduct_model_1.CashAllocationProduct.findByIdAndUpdate(_id, { ...update, order });
            }
        }));
        const existingCashAllocationReferenceIds = existingCashAllocations.references.map((i) => i._id.toString());
        const cashAllocationReferencesToDelete = existingCashAllocationReferenceIds.filter((id) => !references.some((i) => i._id === id));
        await CashAllocationReference_model_1.CashAllocationReference.deleteMany({ _id: { $in: cashAllocationReferencesToDelete } });
        await Promise.all(references.map(async (reference, order) => {
            if (reference.cashAllocationProductId.includes('new_')) {
                reference.cashAllocationProductId = newProductsMap.get(reference.cashAllocationProductId);
            }
            const { _id, ...update } = reference;
            if (_id.includes('new_')) {
                const newCashAllocationReference = new CashAllocationReference_model_1.CashAllocationReference({ ...update, order });
                await newCashAllocationReference.save();
            }
            else {
                await CashAllocationReference_model_1.CashAllocationReference.findByIdAndUpdate(_id, { ...update, order });
            }
        }));
    }
}
exports.CashAllocationService = CashAllocationService;
