"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PdfService = exports.defaultPDFPageSettings = exports.defaultPDFPageSize = exports.defaultPDFPageMarginSize = void 0;
const decimal_js_1 = __importDefault(require("decimal.js"));
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const pdfmake_1 = __importDefault(require("pdfmake/build/pdfmake"));
const vfs_fonts_1 = __importDefault(require("pdfmake/build/vfs_fonts"));
const dayjs_1 = __importDefault(require("dayjs"));
const LoanProducts_model_1 = require("../models/LoanProducts.model");
const Borrower_model_1 = require("../models/Borrower.model");
const loan_charge_type_enum_1 = require("../enums/loan-charge-type.enum");
const numbers_helper_1 = require("../helpers/numbers.helper");
const loan_types_enum_1 = require("../enums/loan-types.enum");
const receivables_db_1 = require("../db/receivables.db");
const financial_indexes_service_1 = require("./financial-indexes.service");
const mappedChargeTypes = {
    [loan_charge_type_enum_1.ELoanChargeType.INTEREST_FEE]: 'Interest',
    [loan_charge_type_enum_1.ELoanChargeType.ADMIN_FEE]: 'Loan Administration Fee',
    [loan_charge_type_enum_1.ELoanChargeType.UNUSED_LINE_FEE]: 'Unused Line Fee',
    [loan_charge_type_enum_1.ELoanChargeType.WIRE_FEE]: 'Wire fee',
    [loan_charge_type_enum_1.ELoanChargeType.ANNUAL_LINE_FEE]: 'Annual Line Fee',
    [loan_charge_type_enum_1.ELoanChargeType.OTHER]: 'Other',
    [loan_charge_type_enum_1.ELoanChargeType.RECOVERABLE]: 'Recoverable',
};
exports.defaultPDFPageMarginSize = 30;
exports.defaultPDFPageSize = {
    width: 841.890, // Page width in points for A4 size (8.27 inches)
    height: 595.276, // Page height in points for A4 size (11.69 inches)
};
exports.defaultPDFPageSettings = {
    margin: exports.defaultPDFPageMarginSize,
    docWidth: exports.defaultPDFPageSize.width - exports.defaultPDFPageMarginSize * 2,
    docHeight: exports.defaultPDFPageSize.width - exports.defaultPDFPageMarginSize * 2,
};
const defaultDateFormat = 'MM/DD/YYYY';
class PdfService {
    financialIndexesService;
    loanChargesService;
    loanStatementBalanceService;
    loanStatementService;
    loanTransactionsService;
    organizationsService;
    termLoanService;
    config;
    margin = exports.defaultPDFPageMarginSize;
    docWidth;
    docHeight;
    constructor(config, financialIndexesService, loanChargesService, loanStatementBalanceService, loanStatementService, loanTransactionsService, organizationsService, termLoanService) {
        this.financialIndexesService = financialIndexesService;
        this.loanChargesService = loanChargesService;
        this.loanStatementBalanceService = loanStatementBalanceService;
        this.loanStatementService = loanStatementService;
        this.loanTransactionsService = loanTransactionsService;
        this.organizationsService = organizationsService;
        this.termLoanService = termLoanService;
        this.config = config;
    }
    addHeaderNew(organizationSubfolder) {
        const imageData = (imageUrl) => {
            const imagePath = path_1.default.join(this.config.rootDir, imageUrl);
            const imageBuffer = fs_1.default.readFileSync(imagePath);
            const imageBase64 = Buffer.from(imageBuffer).toString('base64');
            return `data:image/png;base64,${imageBase64}`;
        };
        const logoElement = {
            image: imageData(`./public/images/${organizationSubfolder}/logo.png`),
            width: 150,
        };
        const gradientElement = {
            image: imageData(`./public/images/${organizationSubfolder}/gradient.png`),
            width: this.docWidth * 0.8,
            height: 60,
        };
        return {
            alignment: 'justify',
            columns: [
                logoElement,
                gradientElement,
            ],
        };
    }
    async getProductStatementData(productId, start, end) {
        const product = await LoanProducts_model_1.LoanProduct.findById(productId).lean();
        const borrower = await Borrower_model_1.BorrowerModel.findById(product.borrowerId).lean();
        const charges = await this.loanChargesService.getLoanChargeForProduct(productId);
        const periodStart = (0, dayjs_1.default)(start);
        const getInterestFee = (adminFeePercent) => {
            const fullFee = new decimal_js_1.default(primeIndex).mul(100).add(adminFeePercent ?? 0).toDP(4).toNumber();
            if (product.type === loan_types_enum_1.ELoanTypes.TERM) {
                const minPercent = (product.minPercent ?? 0) === 0 ? 0 : new decimal_js_1.default(product.minPercent).mul(100).toNumber() ?? 0;
                const maxPercent = (product.maxPercent ?? 0) === 0 ? 100 : new decimal_js_1.default(product.maxPercent).mul(100).toNumber();
                return Math.min(Math.max(fullFee, minPercent), maxPercent);
            }
            return fullFee;
        };
        const getAdminFeeMin = () => {
            const adminFee = charges.find((charge) => charge.chargeType === loan_charge_type_enum_1.ELoanChargeType.ADMIN_FEE);
            if (!adminFee) {
                return '';
            }
            if (!!adminFee.minimumAmount && adminFee.minimumAmount > 0) {
                return `(min = ${adminFee.minimumAmount}$)`;
            }
            return '';
        };
        const { groupedData, otherStatements, transactions, } = await this.loanStatementService.getProductStatementPdfData(productId, start, end);
        const chargeInfo = (chargeType) => {
            const foundCharge = charges.find((charge) => charge.chargeType === chargeType);
            if (!foundCharge) {
                return { percent: null, minimumAmount: null };
            }
            return { percent: foundCharge.percent * 100, minimumAmount: foundCharge.minimumAmount };
        };
        const primeIndex = await this.financialIndexesService.getFinancialIndexValue(financial_indexes_service_1.EFinancialIndex.PRIME_RATE) ?? 0;
        const chargeMap = {
            [loan_charge_type_enum_1.ELoanChargeType.INTEREST_FEE]: {
                title: mappedChargeTypes[loan_charge_type_enum_1.ELoanChargeType.INTEREST_FEE],
                explanation: `${getInterestFee(chargeInfo(loan_charge_type_enum_1.ELoanChargeType.INTEREST_FEE).percent)}% - daily charge`,
            },
            [loan_charge_type_enum_1.ELoanChargeType.ADMIN_FEE]: {
                title: mappedChargeTypes[loan_charge_type_enum_1.ELoanChargeType.ADMIN_FEE],
                explanation: `${chargeInfo(loan_charge_type_enum_1.ELoanChargeType.ADMIN_FEE).percent}% - per month, average monthly balance ${getAdminFeeMin()}`,
            },
            [loan_charge_type_enum_1.ELoanChargeType.UNUSED_LINE_FEE]: {
                title: mappedChargeTypes[loan_charge_type_enum_1.ELoanChargeType.UNUSED_LINE_FEE],
                explanation: `${chargeInfo(loan_charge_type_enum_1.ELoanChargeType.UNUSED_LINE_FEE).percent}% - daily charge on unused amount`,
            },
            [loan_charge_type_enum_1.ELoanChargeType.WIRE_FEE]: {
                title: mappedChargeTypes[loan_charge_type_enum_1.ELoanChargeType.WIRE_FEE],
                explanation: `${chargeInfo(loan_charge_type_enum_1.ELoanChargeType.WIRE_FEE).minimumAmount}$ per disbursement`,
            },
            [loan_charge_type_enum_1.ELoanChargeType.ANNUAL_LINE_FEE]: {
                title: mappedChargeTypes[loan_charge_type_enum_1.ELoanChargeType.ANNUAL_LINE_FEE],
                explanation: `${chargeInfo(loan_charge_type_enum_1.ELoanChargeType.ANNUAL_LINE_FEE).percent}% of commitment`,
            },
            [loan_charge_type_enum_1.ELoanChargeType.OTHER]: {
                title: mappedChargeTypes[loan_charge_type_enum_1.ELoanChargeType.OTHER],
                explanation: '',
            },
            [loan_charge_type_enum_1.ELoanChargeType.RECOVERABLE]: {
                title: mappedChargeTypes[loan_charge_type_enum_1.ELoanChargeType.RECOVERABLE],
                explanation: '',
            },
        };
        const preparedStatement = Object.entries(groupedData).map(([chargeType, amount]) => {
            if (amount === 0) {
                return null;
            }
            return [
                chargeMap[chargeType].title,
                { text: (0, numbers_helper_1.formatNumbers)(amount), alignment: 'right' },
                { text: chargeMap[chargeType].explanation, noWrap: true },
            ];
        });
        const groupedOtherStatements = otherStatements.reduce((acc, otherStatement) => {
            const groupName = `${otherStatement.chargeName}${receivables_db_1.CUSTOMER_NUMBER_SEPARATOR}${otherStatement.memo}`;
            const foundValue = acc[groupName];
            if (foundValue) {
                acc[groupName].amount = new decimal_js_1.default(foundValue.amount).add(otherStatement.amount).toNumber();
                return acc;
            }
            return {
                ...acc,
                [groupName]: {
                    amount: otherStatement.amount,
                    chargeName: otherStatement.chargeName,
                    memo: otherStatement.memo,
                },
            };
        }, {});
        Object
            .values(groupedOtherStatements)
            .sort((values1, values2) => values1.memo.localeCompare(values2.memo))
            .sort((values1, values2) => values1.chargeName.localeCompare(values2.chargeName))
            .forEach((values) => {
            preparedStatement.push([
                { text: values.chargeName, noWrap: false },
                { text: (0, numbers_helper_1.formatNumbers)(values.amount), alignment: 'right' },
                { text: values.memo, noWrap: false },
            ]);
        });
        const previousStatementTransaction = await this.loanStatementBalanceService.getLastStatementTransactionForDate(productId, new Date(periodStart.format('YYYY-MM-DD')));
        const startStatementBalance = previousStatementTransaction ? previousStatementTransaction.balance : 0;
        let monthlyTermPrincipal = null;
        if (product.type === loan_types_enum_1.ELoanTypes.TERM) {
            const { monthlyPrincipal } = await this.getTermLoan(product._id.toString(), new Date(start));
            monthlyTermPrincipal = monthlyPrincipal;
        }
        const totalOther = Object.values(groupedOtherStatements).reduce((acc, st) => new decimal_js_1.default(acc).add(st.amount).toNumber(), 0);
        const other = { other: totalOther };
        const totalAmountDue = Object.values({ ...groupedData, ...other }).reduce((acc, value) => new decimal_js_1.default(acc).add(value || 0).toNumber(), 0);
        const fullStatementTable = [
            [{ text: '' }, { text: 'AMOUNT', bold: true, alignment: 'right' }, { text: 'BASIS FOR CHARGE', bold: true }],
            ...preparedStatement.filter((statement) => !!statement),
            monthlyTermPrincipal ? [{ text: 'Principal' }, {
                    text: (0, numbers_helper_1.formatNumbers)(monthlyTermPrincipal),
                    alignment: 'right',
                }, { text: '' }] : [],
            [
                { text: 'Past due amount from previous statement', bold: true, border: [false], noWrap: true },
                {
                    text: (0, numbers_helper_1.formatNumbers)(startStatementBalance),
                    bold: true,
                    border: [false],
                    alignment: 'right',
                },
                { text: '', border: [false] },
            ],
            [{
                    text: 'TOTAL AMOUNT DUE',
                    bold: true,
                    color: 'red',
                    border: [false],
                    noWrap: true,
                }, {
                    text: (0, numbers_helper_1.formatNumbers)(new decimal_js_1.default(totalAmountDue).add(startStatementBalance).add(monthlyTermPrincipal ? monthlyTermPrincipal : 0).toNumber()),
                    bold: true,
                    color: 'red',
                    border: [false],
                    alignment: 'right',
                }, { text: '', border: [false] }],
        ].filter((row) => row.length > 0);
        const productInfoTable = [
            [{ text: '' }, { text: '' }],
            [{ text: 'Product start date' }, {
                    text: (0, dayjs_1.default)(product.startDate).format(defaultDateFormat),
                    alignment: 'right',
                }],
            [{ text: 'Product maturity date' }, {
                    text: (0, dayjs_1.default)(product.maturityDate).format(defaultDateFormat),
                    alignment: 'right',
                }],
            [{ text: 'Commitment amount' }, { text: (0, numbers_helper_1.formatNumbers)(product.commitment), alignment: 'right' }],
        ];
        const endDate = product.deactivationDate
            ? (0, dayjs_1.default)(product.deactivationDate).isBefore((0, dayjs_1.default)(end.slice(0, 10))) ? (0, dayjs_1.default)(product.deactivationDate) : (0, dayjs_1.default)(end.slice(0, 10))
            : (0, dayjs_1.default)(end.slice(0, 10));
        const preparedStatementHeader = [
            { text: `STATEMENT FOR PRODUCT: ${product.name}`, bold: true },
            { text: `Client: ${borrower.code}`, bold: true },
            {
                text: `PERIOD FROM ${dayjs_1.default.utc(start).format(defaultDateFormat)} TO ${endDate.format(defaultDateFormat)}`,
                bold: true,
            },
            {
                table: { widths: [120, 140], body: productInfoTable },
                layout: 'lightHorizontalLines',
            },
        ];
        const previousTransaction = transactions.length > 0
            ? await this.loanTransactionsService.getLastTransactionForDate(transactions[0].productId.toString(), (0, dayjs_1.default)(transactions[0].date).subtract(1, 'second').toDate())
            : await this.loanTransactionsService.getLastTransactionForDate(productId, (0, dayjs_1.default)(periodStart).subtract(1, 'second').toDate());
        const lastTransaction = transactions.length > 0
            ? transactions[transactions.length - 1]
            : previousTransaction;
        const preparedTransactionsHeader = [
            { text: `LOAN TRANSACTIONS: ${product.name}` },
        ];
        const preparedTransactions = transactions.map((transaction) => {
            return [
                { text: (0, dayjs_1.default)(transaction.date).format(defaultDateFormat) },
                { text: transaction.transactionType },
                { text: (0, numbers_helper_1.formatNumbers)(transaction.amount), alignment: 'right' },
                { text: transaction.reference },
                { text: (0, numbers_helper_1.formatNumbers)(transaction.balance), alignment: 'right' },
            ];
        });
        const fullTransactionsTable = [
            [
                { text: 'Date' },
                { text: 'Type' },
                { text: 'Amount', alignment: 'right' },
                { text: 'Reference' },
                { text: 'Balance', alignment: 'right' },
            ],
            [
                { text: '' },
                { text: '' },
                { text: '' },
                { text: 'OPENING BALANCE' },
                { text: `${previousTransaction ? (0, numbers_helper_1.formatNumbers)(previousTransaction.balance) : 0}`, alignment: 'right' },
            ],
            ...preparedTransactions,
            [
                { text: '' },
                { text: '' },
                { text: '' },
                { text: 'CLOSING BALANCE' },
                { text: `${lastTransaction ? (0, numbers_helper_1.formatNumbers)(lastTransaction.balance) : 0}`, alignment: 'right' },
            ],
        ];
        return {
            startStatementBalance,
            preparedStatementHeader,
            preparedStatement: {
                table: {
                    widths: ['auto', 100, '*'],
                    body: fullStatementTable,
                },
                layout: 'lightHorizontalLines',
            },
            preparedTransactionsHeader,
            preparedTransactions: {
                table: {
                    widths: [80, 100, 80, '*', 80],
                    body: fullTransactionsTable,
                },
                layout: 'lightHorizontalLines',
            },
            groupedData,
            otherStatements,
        };
    }
    async getTermLoan(productId, start) {
        const termLoan = await this.termLoanService.getTermLoan(productId, true);
        let isMatch = false;
        const tableHeader = [
            { text: 'Relevant statement', bold: true },
            { text: 'Due date', bold: true },
            { text: 'Interest rate', bold: true, alignment: 'right' },
            { text: 'Closing Balance', bold: true, alignment: 'right' },
            { text: 'Principal', bold: true, alignment: 'right' },
            { text: 'Interest', bold: true, alignment: 'right' },
            { text: 'EMI', bold: true, alignment: 'right' },
            { text: 'Admin Fee', bold: true, alignment: 'right' },
            { text: 'Total Payment', bold: true, alignment: 'right' },
        ];
        let tableData = [];
        let monthlyPrincipal = null;
        let dueDate = null;
        const cellParams = { border: [false], noWrap: true, fontSize: 12 };
        const numberCellParams = { ...cellParams, alignment: 'right' };
        if (termLoan) {
            tableData = termLoan.calculated.reduce((acc, calculatedRow) => {
                isMatch = isMatch || (0, dayjs_1.default)(calculatedRow.relevantStatement).endOf('month').isAfter((0, dayjs_1.default)(start));
                if (!isMatch) {
                    return acc;
                }
                const EMI = new decimal_js_1.default(calculatedRow.monthlyPrincipal).add(calculatedRow.monthlyInterest).toNumber();
                const totalPayment = new decimal_js_1.default(EMI).add(calculatedRow.adminFee).toNumber();
                if (monthlyPrincipal === null) {
                    monthlyPrincipal = calculatedRow.monthlyPrincipal;
                    dueDate = calculatedRow.paymentDueDate;
                }
                return [
                    ...acc,
                    [
                        { text: (0, dayjs_1.default)(calculatedRow.relevantStatement).format(defaultDateFormat), ...cellParams },
                        { text: (0, dayjs_1.default)(calculatedRow.paymentDueDate).format(defaultDateFormat), ...cellParams },
                        { text: (0, numbers_helper_1.formatNumbers)(new decimal_js_1.default(calculatedRow.interestRate).mul(100).toDP(2).toNumber() + '%'), ...numberCellParams },
                        { text: (0, numbers_helper_1.formatNumbers)(calculatedRow.closingBalance), ...numberCellParams },
                        { text: (0, numbers_helper_1.formatNumbers)(calculatedRow.monthlyPrincipal), ...numberCellParams },
                        { text: (0, numbers_helper_1.formatNumbers)(calculatedRow.monthlyInterest), ...numberCellParams },
                        { text: (0, numbers_helper_1.formatNumbers)(EMI), ...numberCellParams },
                        { text: (0, numbers_helper_1.formatNumbers)(calculatedRow.adminFee), ...numberCellParams },
                        { text: (0, numbers_helper_1.formatNumbers)(totalPayment), ...numberCellParams },
                    ],
                ];
            }, []);
        }
        return {
            monthlyPrincipal,
            dueDate,
            termLoanTableData: [tableHeader, ...tableData],
        };
    }
    async createStatementDoc(params, getOnlyTotal = false) {
        const { borrowerId, start, end } = params;
        const products = await this.loanChargesService.getLoanProducts(borrowerId);
        const productForPeriod = products.filter(product => {
            if (!product.deactivationDate) {
                return true;
            }
            const deactivation = (0, dayjs_1.default)(product.deactivationDate);
            return deactivation.isAfter((0, dayjs_1.default)(start)) && deactivation.isBefore((0, dayjs_1.default)(end));
        });
        const borrower = await Borrower_model_1.BorrowerModel.findById(borrowerId).lean();
        const organization = await this.organizationsService.getOrganizationForBorrower(borrowerId);
        pdfmake_1.default.vfs = vfs_fonts_1.default.pdfMake.vfs;
        const pageSize = {
            width: 841.890, // Page width in points for A4 size (8.27 inches)
            height: 595.276, // Page height in points for A4 size (11.69 inches)
        };
        this.docWidth = exports.defaultPDFPageSize.width - this.margin * 2;
        this.docHeight = exports.defaultPDFPageSize.height - this.margin * 2;
        const emptyString = { text: ' ', margin: 5 };
        const pageBreaker = { text: '', pageBreak: 'after' };
        const totalGroupedData = {
            [loan_charge_type_enum_1.ELoanChargeType.INTEREST_FEE]: 0,
            [loan_charge_type_enum_1.ELoanChargeType.ADMIN_FEE]: 0,
            [loan_charge_type_enum_1.ELoanChargeType.UNUSED_LINE_FEE]: 0,
            [loan_charge_type_enum_1.ELoanChargeType.WIRE_FEE]: 0,
            [loan_charge_type_enum_1.ELoanChargeType.ANNUAL_LINE_FEE]: 0,
            [loan_charge_type_enum_1.ELoanChargeType.OTHER]: 0,
            [loan_charge_type_enum_1.ELoanChargeType.RECOVERABLE]: 0,
        };
        let totalOverDueStatementBalance = 0;
        const productTotals = productForPeriod.reduce((acc, p) => ({
            ...acc,
            [p._id.toString()]: 0,
        }), {});
        let totalStatementValue = 0;
        const principalData = [];
        let paymentDueDate = null;
        const docContent = await Promise.all(productForPeriod.map(async (product, index) => {
            const { startStatementBalance, preparedStatementHeader, preparedStatement, preparedTransactionsHeader, preparedTransactions, groupedData, otherStatements, } = await this.getProductStatementData(product._id.toString(), start, end);
            totalOverDueStatementBalance = new decimal_js_1.default(totalOverDueStatementBalance).add(startStatementBalance).toNumber();
            let totalPerProduct = 0;
            Object.entries(groupedData).forEach(([chargeType, amount]) => {
                totalGroupedData[chargeType] = new decimal_js_1.default(totalGroupedData[chargeType]).add(amount).toNumber();
                totalPerProduct = new decimal_js_1.default(totalPerProduct).add(amount).toNumber();
            });
            otherStatements.forEach((otherStatement) => {
                totalGroupedData[otherStatement.chargeType] = new decimal_js_1.default(totalGroupedData[otherStatement.chargeType]).add(otherStatement.amount).toNumber();
                totalPerProduct = new decimal_js_1.default(totalPerProduct).add(otherStatement.amount).toNumber();
            });
            productTotals[product._id.toString()] = new decimal_js_1.default(startStatementBalance).add(totalPerProduct).toNumber();
            const warningText = product.type === loan_types_enum_1.ELoanTypes.REVOLVER
                ? `AMOUNT WILL BE ADDED TO THE LOAN ON 1ST. ${organization.name.toUpperCase()} RESERVES THE RIGHT TO STOP FUNDING IF THERE IS INSUFFICIENT AVAILABILITY TO ADD IT TO THE LOAN.`
                : `PAYABLE BY 7TH. ${organization.name.toUpperCase()} RESERVES THE RIGHT TO STOP FUNDING IF THE STATEMENT IS NOT PAID.`;
            const baseContent = [
                this.addHeaderNew(organization.subfolder),
                emptyString,
                ...preparedStatementHeader,
                emptyString,
                preparedStatement,
                emptyString,
                {
                    text: warningText,
                    color: 'red',
                },
                {
                    text: `PAYABLE BY DIRECT TRANSFER, OR BORROWING BASE SUBMISSION CONFIRMING AVAILABILITY. ${organization.name.toUpperCase()} RESERVES THE RIGHT TO ACH FROM YOUR ACCOUNT`,
                    bold: true,
                },
                emptyString,
                ...preparedTransactionsHeader,
                preparedTransactions,
            ];
            const productPageEnd = productForPeriod.length === index + 1
                ? emptyString
                : pageBreaker;
            if (product.type === loan_types_enum_1.ELoanTypes.TERM) {
                const { termLoanTableData, monthlyPrincipal, dueDate, } = await this.getTermLoan(product._id.toString(), new Date(start));
                if (monthlyPrincipal !== null) {
                    totalStatementValue = new decimal_js_1.default(totalStatementValue).add(monthlyPrincipal).toNumber();
                    principalData.push([
                        { text: `Principal (${product.name})` },
                        { text: (0, numbers_helper_1.formatNumbers)(monthlyPrincipal), alignment: 'right' },
                        { text: '' },
                    ]);
                    paymentDueDate = dueDate;
                    productTotals[product._id.toString()] = new decimal_js_1.default(productTotals[product._id.toString()]).add(monthlyPrincipal).toNumber();
                }
                return [
                    ...baseContent,
                    pageBreaker,
                    this.addHeaderNew(organization.subfolder),
                    emptyString,
                    { text: `Term loan schedule: `, fontSize: 15, bold: true },
                    emptyString,
                    {
                        table: { widths: ['*', '*', '*', '*', '*', '*', '*', '*', '*'], body: termLoanTableData },
                        layout: 'lightHorizontalLines',
                    },
                    productPageEnd,
                ];
            }
            return [
                ...baseContent,
                productPageEnd,
            ];
        }));
        const preparedTotal = Object.entries(totalGroupedData).map(([chargeType, amount]) => {
            totalStatementValue = new decimal_js_1.default(totalStatementValue).add(amount).toNumber();
            return [
                { text: mappedChargeTypes[loan_charge_type_enum_1.ELoanChargeType[chargeType]] },
                { text: (0, numbers_helper_1.formatNumbers)(amount), alignment: 'right' },
                { text: '' },
            ];
        });
        const totalOverDueStatement = totalOverDueStatementBalance > 0
            ? [
                { text: 'Past due amount from previous statement' },
                { text: (0, numbers_helper_1.formatNumbers)(totalOverDueStatementBalance), alignment: 'right' },
                { text: '' }
            ]
            : [];
        const totalOwed = new decimal_js_1.default(totalStatementValue).add(totalOverDueStatementBalance).toNumber();
        if (getOnlyTotal) {
            return { total: totalOwed, dueDate: paymentDueDate, productTotals };
        }
        const bankAccounts = {
            'Black Feather': [
                [{ text: 'Bank name' }, { text: 'BMO N.A' }],
                [{ text: 'ABA' }, { text: '071000288' }],
                [{ text: 'Account' }, { text: '1841261' }],
            ],
            'GemCap': [
                [{ text: 'Bank name' }, { text: 'CIBC Bank USA' }],
                [{ text: 'ABA' }, { text: '0710-0648-6' }],
                [{ text: 'SWIFT' }, { text: 'PVTBUS44' }],
                [{ text: 'Account' }, { text: '2583852' }],
            ],
        };
        const paymentInstruction = [
            [{ text: 'Please remit payment to', fillColor: '#44464b', color: 'white' }, { text: '', fillColor: '#44464b' }],
            ...bankAccounts[organization.name],
            [{ text: 'Account name' }, { text: `${this.config.title} Funding AssetCo LLC Collection Account` }],
            [{ text: 'Reference' }, { text: `${borrower.code} - STATEMENT PAYMENT` }],
            [{ text: 'The reference is required to ensure timely settlement of your account.', color: 'red' }, {}],
        ];
        const totalStatementTable = [
            [{ text: '' }, { text: 'AMOUNT', bold: true, alignment: 'right' }, { text: '' }],
            ...preparedTotal,
            ...principalData,
            totalOverDueStatement,
            [
                { text: 'TOTAL', color: 'red' },
                {
                    text: (0, numbers_helper_1.formatNumbers)(totalOwed),
                    bold: true,
                    color: 'red',
                    alignment: 'right',
                },
                { text: paymentDueDate ? `due on ${(0, dayjs_1.default)(paymentDueDate).format(defaultDateFormat)}` : '', color: 'red' },
            ],
        ];
        docContent.unshift([
            this.addHeaderNew(organization.subfolder),
            emptyString,
            { text: 'Total Statement Amount', fontSize: 18, bold: true },
            { text: `Client: ${borrower.name}`, fontSize: 15, bold: true },
            {
                table: { widths: [300, 100, '*'], body: totalStatementTable.filter((row) => row.length !== 0) },
                layout: 'lightHorizontalLines',
            },
            emptyString,
            {
                table: { widths: ['*', '*'], body: paymentInstruction, styles: 'section' },
                layout: 'lightHorizontalLines',
            },
            pageBreaker,
        ]);
        const docDefinition = {
            content: docContent,
            footer: (currentPage, pageCount) => {
                return {
                    text: 'Page ' + currentPage.toString() + ' of ' + pageCount,
                    alignment: 'center',
                };
            },
            pageOrientation: 'landscape',
            pageSize,
            pageMargins: this.margin,
        };
        return pdfmake_1.default.createPdf(docDefinition);
    }
}
exports.PdfService = PdfService;
