"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getPartialPaid = exports.getPartialPaidFull = void 0;
const excel_helper_1 = require("../../helpers/excel.helper");
const bbcSheets_db_1 = require("../../db/bbcSheets.db");
const receivables_db_1 = require("../../db/receivables.db");
const collaterals_enum_1 = require("../../enums/collaterals.enum");
const getPartialPaidFull = async (params) => {
    const { suspiciousInvoices, restatedInvoices, partiallyPaidInvoices } = await (0, exports.getPartialPaid)(params);
    const header = getPartialPaidHeader();
    const suspiciousInvoicesFull = (0, excel_helper_1.addHeaderToData)(header, suspiciousInvoices);
    const restatedInvoicesFull = (0, excel_helper_1.addHeaderToData)(header, restatedInvoices);
    const partiallyPaidInvoicesFull = (0, excel_helper_1.addHeaderToData)(header, partiallyPaidInvoices);
    return {
        'suspicious': suspiciousInvoicesFull,
        'restated': restatedInvoicesFull,
        'partially paid': partiallyPaidInvoicesFull,
    };
};
exports.getPartialPaidFull = getPartialPaidFull;
const getPartialPaid = async (params) => {
    const { borrowerId, startDate, endDate } = params;
    const allInventoryBbcDates = await (0, bbcSheets_db_1.getUniqueDatesForPeriod)(borrowerId.toString(), collaterals_enum_1.ECollaterals.RECEIVABLE, new Date(startDate), new Date(endDate));
    const sheetIds = allInventoryBbcDates.reduce((acc, bbc) => [...acc, ...bbc.ids], []);
    const allInvoices = await (0, receivables_db_1.getPartialPaidTable)(sheetIds);
    const groupedInvoices = allInvoices.reduce((acc, i) => {
        acc[i.invoiceNumber] = acc[i.invoiceNumber] || [];
        acc[i.invoiceNumber].push(i);
        return acc;
    }, {});
    const getInvoiceDifference = (invoices) => {
        const invoice1 = invoices[0];
        const invoice2 = invoices[invoices.length - 1];
        return {
            invoiceNumber: invoice1.invoiceNumber,
            invoiceDate: invoice1.invoiceDate,
            customer: invoice1.customerTitle,
            originalAmount: invoice1.invoiceAmount,
            restatedAmount: invoice2.invoiceAmount,
            changeCounter: invoices.length - 1,
            lastChangeDate: invoice2.bbc.bbcDate,
            difference: +Math.abs(invoice1.invoiceAmount - invoice2.invoiceAmount).toFixed(3),
        };
    };
    const getInvoiceChain = (invoices) => {
        let firstInvoice = null;
        let lastInvoice = null;
        const invoiceChain = [];
        let lastMatchIndex = 0;
        let shouldSkip = false;
        invoices.forEach((invoice, index) => {
            if (shouldSkip) {
                return;
            }
            if (firstInvoice === null) {
                firstInvoice = { ...invoice };
                invoiceChain.push(firstInvoice);
                return;
            }
            lastInvoice = { ...invoice };
            if (lastInvoice.invoiceAmount === firstInvoice.invoiceAmount ||
                lastInvoice.invoiceAmount === invoices[index - 1].invoiceAmount) {
                lastMatchIndex = index;
                return;
            }
            if (lastInvoice.invoiceAmount > firstInvoice.invoiceAmount &&
                lastInvoice.invoiceAmount > invoices[index - 1].invoiceAmount ||
                lastInvoice.invoiceAmount < firstInvoice.invoiceAmount &&
                    lastInvoice.invoiceAmount < invoices[index - 1].invoiceAmount) {
                invoiceChain.push(lastInvoice);
                lastMatchIndex = index;
                return;
            }
            if (lastInvoice.invoiceAmount > firstInvoice.invoiceAmount &&
                lastInvoice.invoiceAmount < invoices[index - 1].invoiceAmount ||
                lastInvoice.invoiceAmount < firstInvoice.invoiceAmount &&
                    lastInvoice.invoiceAmount > invoices[index - 1].invoiceAmount) {
                shouldSkip = true;
                return;
            }
        });
        return { invoiceChain, lastMatchIndex };
    };
    const megaChain = [];
    const suspiciousInvoices = [];
    const restatedInvoices = [];
    const partiallyPaidInvoices = [];
    Object.keys(groupedInvoices).forEach((invoiceNumber) => {
        const invoices = [...groupedInvoices[invoiceNumber]];
        const invoiceChains = [];
        let totalIndex = 0;
        while (totalIndex !== invoices.length - 1) {
            const { invoiceChain, lastMatchIndex } = getInvoiceChain([...invoices].slice(totalIndex));
            invoiceChains.push(invoiceChain);
            totalIndex = totalIndex + lastMatchIndex;
        }
        megaChain.push(invoiceChains);
    });
    megaChain.forEach((chains) => {
        if (chains.length > 1) {
            chains.forEach((chain) => {
                const diff = getInvoiceDifference(chain);
                suspiciousInvoices.push(diff);
            });
        }
        else {
            chains.forEach((chain) => {
                const diff = getInvoiceDifference(chain);
                if (diff.originalAmount - diff.restatedAmount > 0) {
                    partiallyPaidInvoices.push(diff);
                }
                else if (diff.originalAmount - diff.restatedAmount < 0) {
                    restatedInvoices.push(diff);
                }
            });
        }
    });
    return { suspiciousInvoices, restatedInvoices, partiallyPaidInvoices };
};
exports.getPartialPaid = getPartialPaid;
const getPartialPaidHeader = () => {
    return {
        invoiceNumber: 'Invoice number',
        customer: 'Customer',
        originalAmount: 'Original amount',
        restatedAmount: 'Last amount',
        difference: 'Difference',
        lastChangeDate: 'Last change date',
        changeCounter: 'Changed',
    };
};
