import { GraphQLError } from 'graphql';
import { EMPTY_UUID } from '../../../shared/constants.js';
import { ChargeSortByField, ChargeTypeEnum } from '../../../shared/enums.js';
import { errorSimplifier } from '../../../shared/errors.js';
import { AdminContextProvider } from '../../admin-context/providers/admin-context.provider.js';
import { ScopeProvider } from '../../auth/providers/scope.provider.js';
import { BusinessTripsProvider } from '../../business-trips/providers/business-trips.provider.js';
import { isInvoice, isReceipt } from '../../documents/helpers/common.helper.js';
import { DocumentsProvider } from '../../documents/providers/documents.provider.js';
import { IssuedDocumentsProvider } from '../../documents/providers/issued-documents.provider.js';
import { ledgerGenerationByCharge } from '../../ledger/helpers/ledger-by-charge-type.helper.js';
import { isChargeLocked } from '../../ledger/helpers/ledger-lock.js';
import { ledgerRecordsGenerationFullMatchComparison } from '../../ledger/helpers/ledgrer-storage.helper.js';
import { LedgerProvider } from '../../ledger/providers/ledger.provider.js';
import { MiscExpensesProvider } from '../../misc-expenses/providers/misc-expenses.provider.js';
import { ChargeTagsProvider } from '../../tags/providers/charge-tags.provider.js';
import { TransactionsProvider } from '../../transactions/providers/transactions.provider.js';
import { batchUpdateChargesBusinessTrip, batchUpdateChargesTags, batchUpdateChargesYearsSpread, } from '../helpers/batch-update-charges.js';
import { getChargeType, normalizeDbType } from '../helpers/charge-type.js';
import { getChargeBusinesses, getChargeDocumentsMeta, getChargeLedgerMeta, getChargeTransactionsMeta, } from '../helpers/common.helper.js';
import { deleteCharges } from '../helpers/delete-charges.helper.js';
import { mergeChargesExecutor } from '../helpers/merge-charges.helper.js';
import { ChargeSpreadProvider } from '../providers/charge-spread.provider.js';
import { ChargesProvider } from '../providers/charges.provider.js';
import { commonChargeFields, commonDocumentsFields } from './common.js';
async function chargeTypeChecker(chargeType, charge, injector) {
    try {
        return (await getChargeType(charge, injector)) === chargeType;
    }
    catch (error) {
        throw errorSimplifier('Failed to determine charge type', error);
    }
}
export const chargesResolvers = {
    Query: {
        charge: async (_, { chargeId }, { injector }) => {
            try {
                const charge = await injector.get(ChargesProvider).getChargeByIdLoader.load(chargeId);
                if (!charge) {
                    throw new GraphQLError(`Charge ID="${chargeId}" not found`);
                }
                return charge;
            }
            catch (error) {
                throw errorSimplifier('Failed to fetch charge by ID', error);
            }
        },
        chargesByIDs: async (_, { chargeIDs }, { injector }) => {
            if (chargeIDs.length === 0) {
                return [];
            }
            try {
                const dbCharges = await injector
                    .get(ChargesProvider)
                    .getChargeByIdLoader.loadMany(chargeIDs);
                if (!dbCharges) {
                    if (chargeIDs.length === 1) {
                        throw new GraphQLError(`Charge ID="${chargeIDs[0]}" not found`);
                    }
                    else {
                        throw new GraphQLError(`Couldn't find any charges`);
                    }
                }
                const charges = chargeIDs.map(id => {
                    const charge = dbCharges.find(charge => charge && !(charge instanceof Error) && charge.id === id);
                    if (!charge) {
                        throw new GraphQLError(`Charge ID="${id}" not found`);
                    }
                    return charge;
                });
                return charges;
            }
            catch (error) {
                throw errorSimplifier('Failed to fetch charges by IDs', error);
            }
        },
        allCharges: async (_, { filters, page, limit }, { injector }) => {
            // handle sort column
            let sortColumn = 'event_date';
            switch (filters?.sortBy?.field) {
                case ChargeSortByField.Amount:
                    sortColumn = 'event_amount';
                    break;
                case ChargeSortByField.AbsAmount:
                    sortColumn = 'abs_event_amount';
                    break;
                case ChargeSortByField.Date:
                    sortColumn = 'event_date';
                    break;
            }
            const charges = await injector
                .get(ChargesProvider)
                .getChargesByFilters({
                ownerIds: filters?.byOwners,
                fromAnyDate: filters?.fromAnyDate,
                toAnyDate: filters?.toAnyDate,
                sortColumn,
                asc: filters?.sortBy?.asc !== false,
                chargeType: filters?.chargesType,
                businessIds: filters?.byBusinesses,
                businessTripIds: filters?.byBusinessTrips,
                withMissingCounterparty: filters?.withMissingCounterparty,
                withoutInvoice: filters?.withoutInvoice,
                withoutReceipt: filters?.withoutReceipt,
                withoutDocuments: filters?.withoutDocuments,
                withOpenDocuments: filters?.withOpenDocuments,
                withoutTransactions: filters?.withoutTransactions,
                withoutLedger: filters?.withoutLedger,
                freeText: filters?.freeText?.trim().toLowerCase(),
                tags: filters?.byTags,
                accountantStatuses: filters?.accountantStatus,
            })
                .catch(error => {
                throw errorSimplifier('Error fetching charges', error);
            });
            // charge __typename is resolved dynamically, so filter by concrete type post-fetch
            let filteredCharges = charges;
            if (filters?.byChargeTypes?.length) {
                const wantedTypes = new Set(filters.byChargeTypes?.map(normalizeDbType));
                const chargeTypes = await Promise.all(charges.map(charge => getChargeType(charge, injector).catch(error => {
                    throw errorSimplifier('Failed to determine charge type', error);
                })));
                filteredCharges = charges.filter((_, index) => wantedTypes.has(chargeTypes[index]));
            }
            const pageCharges = filteredCharges.slice(page * limit, (page + 1) * limit);
            return {
                __typename: 'PaginatedCharges',
                nodes: pageCharges,
                pageInfo: {
                    totalPages: Math.ceil(filteredCharges.length / limit),
                    totalRecords: filteredCharges.length,
                },
            };
        },
        chargesWithMissingRequiredInfo: async (_, { page, limit }, { injector }) => {
            try {
                const chargeIds = new Set();
                // get by transactions
                const getByTransactionsPromise = injector
                    .get(TransactionsProvider)
                    .getTransactionsByMissingRequiredInfo()
                    .then(transactions => {
                    transactions.map(transaction => {
                        if (transaction.charge_id) {
                            chargeIds.add(transaction.charge_id);
                        }
                    });
                });
                // get by documents
                const getByDocumentsPromise = injector
                    .get(DocumentsProvider)
                    .getDocumentsByMissingRequiredInfo()
                    .then(documents => {
                    documents.map(document => {
                        if (document.charge_id) {
                            chargeIds.add(document.charge_id);
                        }
                    });
                });
                // get by charge
                const getByChargesPromise = injector
                    .get(ChargesProvider)
                    .getChargesByMissingRequiredInfo()
                    .then(charges => {
                    charges.map(charge => {
                        if (charge.id) {
                            chargeIds.add(charge.id);
                        }
                    });
                });
                await Promise.all([getByTransactionsPromise, getByDocumentsPromise, getByChargesPromise]);
                const charges = await Promise.all(Array.from(chargeIds).map(async (id) => {
                    const [charge, { transactionsMinDebitDate, transactionsMinEventDate }, { ledgerMinInvoiceDate, ledgerMinValueDate }, { documentsMinDate },] = await Promise.all([
                        injector
                            .get(ChargesProvider)
                            .getChargeByIdLoader.load(id)
                            .then(charge => {
                            if (!charge) {
                                throw new GraphQLError(`Charge ID="${id}" not found`);
                            }
                            return charge;
                        })
                            .catch(e => {
                            const message = `Error loading charge ID="${id}"`;
                            console.error(`${message}: ${e}`);
                            throw new GraphQLError(message);
                        }),
                        getChargeTransactionsMeta(id, injector),
                        getChargeLedgerMeta(id, injector),
                        getChargeDocumentsMeta(id, injector),
                    ]);
                    return {
                        ...charge,
                        transactionsMinDebitDate,
                        transactionsMinEventDate,
                        ledgerMinInvoiceDate,
                        ledgerMinValueDate,
                        documentsMinDate,
                    };
                }));
                const readScope = await injector.get(ScopeProvider).getReadScope();
                const pageCharges = charges
                    .filter(charge => !!charge.owner_id && readScope.includes(charge.owner_id))
                    .sort((chargeA, chargeB) => {
                    const dateA = (chargeA.documentsMinDate ||
                        chargeA.transactionsMinDebitDate ||
                        chargeA.transactionsMinEventDate ||
                        chargeA.ledgerMinValueDate ||
                        chargeA.ledgerMinInvoiceDate)?.getTime() ?? 0;
                    const dateB = (chargeB.documentsMinDate ||
                        chargeB.transactionsMinDebitDate ||
                        chargeB.transactionsMinEventDate ||
                        chargeB.ledgerMinValueDate ||
                        chargeB.ledgerMinInvoiceDate)?.getTime() ?? 0;
                    if (dateA > dateB) {
                        return -1;
                    }
                    if (dateA < dateB) {
                        return 1;
                    }
                    return chargeA.id.localeCompare(chargeB.id);
                })
                    .slice(page * limit - limit, page * limit);
                return {
                    __typename: 'PaginatedCharges',
                    nodes: pageCharges,
                    pageInfo: {
                        totalPages: Math.ceil(charges.length / limit),
                        totalRecords: charges.length,
                    },
                };
            }
            catch (error) {
                throw errorSimplifier('Failed to fetch charges with missing required info', error);
            }
        },
    },
    Mutation: {
        updateCharge: async (_, { chargeId, fields }, { injector }) => {
            const adjustedFields = {
                accountantStatus: fields.accountantApproval,
                type: fields.type,
                isProperty: fields.isDecreasedVAT,
                isInvoicePaymentDifferentCurrency: fields.isInvoicePaymentDifferentCurrency,
                userDescription: fields.userDescription,
                taxCategoryId: fields.defaultTaxCategoryID,
                optionalVAT: fields.optionalVAT,
                optionalDocuments: fields.optionalDocuments,
                chargeId,
            };
            try {
                const updatedCharge = await injector
                    .get(ChargesProvider)
                    .updateCharge({ ...adjustedFields })
                    .catch(e => {
                    console.error(e);
                    throw new GraphQLError(`Error updating charge ID="${chargeId}"`);
                });
                if (!updatedCharge) {
                    throw new Error(`Charge ID="${chargeId}" not found`);
                }
                const indirectUpdatesPromises = [];
                // handle tags
                if (fields?.tags) {
                    const newTagIDs = fields.tags.map(t => t.id);
                    const updateTagsPromise = async () => {
                        const tagsPromises = [];
                        const pastTags = await injector
                            .get(ChargeTagsProvider)
                            .getTagsByChargeIDLoader.load(chargeId)
                            .then(res => res.map(tag => tag.id));
                        // clear removed tags
                        const tagsToRemove = pastTags.filter(tagId => !newTagIDs.includes(tagId));
                        if (tagsToRemove.length) {
                            tagsPromises.push(injector
                                .get(ChargeTagsProvider)
                                .clearChargeTags({ chargeId, tagIDs: tagsToRemove })
                                .catch(e => {
                                console.error(e);
                                throw new GraphQLError(`Error clearing tags IDs="${tagsToRemove}" to charge ID="${chargeId}"`);
                            }));
                        }
                        // add new tags
                        const tagIDsToAdd = newTagIDs.filter(tagId => !pastTags.includes(tagId));
                        for (const tagId of tagIDsToAdd) {
                            tagsPromises.push(injector
                                .get(ChargeTagsProvider)
                                .insertChargeTag({ chargeId, tagId })
                                .catch(e => {
                                console.error(e);
                                throw new GraphQLError(`Error adding tag ID="${tagId}" to charge ID="${chargeId}"`);
                            }));
                        }
                        await Promise.all(tagsPromises);
                    };
                    indirectUpdatesPromises.push(updateTagsPromise());
                }
                // handle business trip
                if (fields?.businessTripID) {
                    indirectUpdatesPromises.push(injector
                        .get(BusinessTripsProvider)
                        .updateChargeBusinessTrip(chargeId, fields.businessTripID === EMPTY_UUID ? null : fields.businessTripID)
                        .catch(e => {
                        console.error(e);
                        throw new GraphQLError(`Error updating business trip for charge ID="${chargeId}"`);
                    }));
                }
                // handle charge spread
                if (fields?.yearsOfRelevance?.length) {
                    const updateSpreadRecords = async () => {
                        await injector
                            .get(ChargeSpreadProvider)
                            .deleteAllChargeSpreadByChargeIds({ chargeIds: [chargeId] })
                            .catch(e => {
                            console.error(e);
                            throw new GraphQLError(`Error deleting spread records for charge ID="${chargeId}"`);
                        });
                        return injector
                            .get(ChargeSpreadProvider)
                            .insertChargeSpread({
                            chargeSpread: fields.yearsOfRelevance.map(record => ({
                                ownerId: updatedCharge.owner_id,
                                chargeId,
                                yearOfRelevance: record.year,
                                amount: record.amount,
                            })),
                        })
                            .catch(e => {
                            console.error(e);
                            throw new GraphQLError(`Error inserting spread records for charge ID="${chargeId}"`);
                        });
                    };
                    indirectUpdatesPromises.push(updateSpreadRecords());
                }
                await Promise.all(indirectUpdatesPromises);
                return { charge: updatedCharge };
            }
            catch (e) {
                let message = 'Error updating charges';
                if (e instanceof GraphQLError) {
                    message = e.message;
                }
                else {
                    console.error(e);
                }
                return {
                    __typename: 'CommonError',
                    message,
                };
            }
        },
        batchUpdateCharges: async (_, { chargeIds, fields }, { injector }) => {
            if (!chargeIds || chargeIds.length === 0) {
                return {
                    __typename: 'CommonError',
                    message: 'No charges provided for update',
                };
            }
            const adjustedFields = {
                accountantStatus: fields.accountantApproval,
                type: fields.type,
                isProperty: fields.isDecreasedVAT,
                isInvoicePaymentDifferentCurrency: fields.isInvoicePaymentDifferentCurrency,
                userDescription: fields.userDescription,
                taxCategoryId: fields.defaultTaxCategoryID,
                optionalVAT: fields.optionalVAT,
                optionalDocuments: fields.optionalDocuments,
                chargeIds,
            };
            try {
                const res = await injector
                    .get(ChargesProvider)
                    .batchUpdateCharges({ ...adjustedFields })
                    .catch(e => {
                    console.error(e);
                    throw new GraphQLError(`Error updating charges (IDs "${chargeIds.join('", "')}")`);
                });
                const updatedCharges = await injector
                    .get(ChargesProvider)
                    .getChargeByIdLoader.loadMany(res.map(c => c.id))
                    .catch(e => {
                    console.error(e);
                    throw new GraphQLError(`Error loading updated charges (IDs "${chargeIds.join('", "')}")`);
                });
                // check if all charges were updated successfully
                if (!updatedCharges) {
                    throw new GraphQLError(`Updated charges not found (IDs "${chargeIds.join('", "')}")`);
                }
                if (updatedCharges.some(charge => !charge || charge instanceof Error)) {
                    throw new GraphQLError(`Some updated charges not found (IDs "${chargeIds.join('", "')}")`);
                }
                // Type assertion as error handling is done above
                const charges = updatedCharges;
                const indirectUpdatesPromises = [];
                // handle tags
                if (fields?.tags) {
                    indirectUpdatesPromises.push(batchUpdateChargesTags(injector, fields.tags.map(t => t.id), chargeIds));
                }
                // handle business trip
                if (fields?.businessTripID) {
                    indirectUpdatesPromises.push(batchUpdateChargesBusinessTrip(injector, fields.businessTripID, chargeIds));
                }
                // handle charge spread
                if (fields?.yearsOfRelevance?.length) {
                    indirectUpdatesPromises.push(batchUpdateChargesYearsSpread(injector, fields.yearsOfRelevance, chargeIds));
                }
                await Promise.all(indirectUpdatesPromises);
                return { charges };
            }
            catch (e) {
                let message = 'Error updating charges';
                if (e instanceof GraphQLError) {
                    message = e.message;
                }
                else {
                    console.error(e);
                }
                return {
                    __typename: 'CommonError',
                    message,
                };
            }
        },
        mergeCharges: async (_, { baseChargeID, chargeIdsToMerge, fields }, { injector }) => {
            try {
                const charge = await injector.get(ChargesProvider).getChargeByIdLoader.load(baseChargeID);
                if (!charge) {
                    throw new Error(`Charge not found`);
                }
                if (fields) {
                    const adjustedFields = {
                        accountantStatus: fields?.accountantApproval,
                        type: fields?.type,
                        isProperty: fields?.isDecreasedVAT,
                        isInvoicePaymentDifferentCurrency: fields?.isInvoicePaymentDifferentCurrency,
                        optionalVAT: fields?.optionalVAT,
                        optionalDocuments: fields?.optionalDocuments,
                        userDescription: fields?.userDescription,
                        chargeId: baseChargeID,
                    };
                    await injector
                        .get(ChargesProvider)
                        .updateCharge({ ...adjustedFields })
                        .catch(e => {
                        const message = `Failed to update charge ID="${baseChargeID}" before merge`;
                        console.error(`${message}: ${e}`);
                        if (e instanceof GraphQLError) {
                            throw e;
                        }
                        throw new Error(message);
                    });
                }
                await mergeChargesExecutor(chargeIdsToMerge, baseChargeID, injector);
                return { charge };
            }
            catch (e) {
                if (e instanceof GraphQLError) {
                    throw e;
                }
                console.error(e);
                return {
                    __typename: 'CommonError',
                    message: e?.message ??
                        e?.errors.map(e => e.message).toString() ??
                        'Unknown error',
                };
            }
        },
        deleteCharge: async (_, { chargeId }, { injector }) => {
            try {
                const [charge, transactions, documents] = await Promise.all([
                    injector.get(ChargesProvider).getChargeByIdLoader.load(chargeId),
                    injector.get(TransactionsProvider).transactionsByChargeIDLoader.load(chargeId),
                    injector.get(DocumentsProvider).getDocumentsByChargeIdLoader.load(chargeId),
                ]);
                if (!charge) {
                    throw new GraphQLError(`Charge ID="${chargeId}" not found`);
                }
                if (documents.length > 0 || transactions.length > 0) {
                    throw new GraphQLError(`Charge ID="${chargeId}" has linked documents/transactions`);
                }
                await deleteCharges([chargeId], injector);
                return true;
            }
            catch (e) {
                if (e instanceof GraphQLError) {
                    throw e;
                }
                console.error(e);
                throw new GraphQLError(`Error deleting charge ID="${chargeId}"`);
            }
        },
    },
    UpdateChargeResult: {
        __resolveType: (obj, _context, _info) => {
            if (('__typename' in obj && obj.__typename === 'CommonError') || 'message' in obj)
                return 'CommonError';
            return 'UpdateChargeSuccessfulResult';
        },
    },
    BatchUpdateChargesResult: {
        __resolveType: (obj, _context, _info) => {
            if (('__typename' in obj && obj.__typename === 'CommonError') || 'message' in obj)
                return 'CommonError';
            return 'BatchUpdateChargesSuccessfulResult';
        },
    },
    MergeChargeResult: {
        __resolveType: (obj, _context, _info) => {
            if (('__typename' in obj && obj.__typename === 'CommonError') || 'message' in obj)
                return 'CommonError';
            return 'MergeChargeSuccessfulResult';
        },
    },
    CommonCharge: {
        __isTypeOf: async (DbCharge, { injector }) => chargeTypeChecker(ChargeTypeEnum.Common, DbCharge, injector),
        ...commonChargeFields,
    },
    ConversionCharge: {
        __isTypeOf: async (DbCharge, { injector }) => chargeTypeChecker(ChargeTypeEnum.Conversion, DbCharge, injector),
        ...commonChargeFields,
    },
    SalaryCharge: {
        __isTypeOf: async (DbCharge, { injector }) => chargeTypeChecker(ChargeTypeEnum.Salary, DbCharge, injector),
        ...commonChargeFields,
    },
    InternalTransferCharge: {
        __isTypeOf: async (DbCharge, { injector }) => chargeTypeChecker(ChargeTypeEnum.InternalTransfer, DbCharge, injector),
        ...commonChargeFields,
    },
    DividendCharge: {
        __isTypeOf: async (DbCharge, { injector }) => chargeTypeChecker(ChargeTypeEnum.Dividend, DbCharge, injector),
        ...commonChargeFields,
    },
    BusinessTripCharge: {
        __isTypeOf: async (DbCharge, { injector }) => chargeTypeChecker(ChargeTypeEnum.BusinessTrip, DbCharge, injector),
        ...commonChargeFields,
    },
    MonthlyVatCharge: {
        __isTypeOf: async (DbCharge, { injector }) => chargeTypeChecker(ChargeTypeEnum.MonthlyVat, DbCharge, injector),
        ...commonChargeFields,
    },
    BankDepositCharge: {
        __isTypeOf: async (DbCharge, { injector }) => chargeTypeChecker(ChargeTypeEnum.BankDeposit, DbCharge, injector),
        ...commonChargeFields,
    },
    ForeignSecuritiesCharge: {
        __isTypeOf: async (DbCharge, { injector }) => chargeTypeChecker(ChargeTypeEnum.ForeignSecurities, DbCharge, injector),
        ...commonChargeFields,
    },
    CreditcardBankCharge: {
        __isTypeOf: async (DbCharge, { injector }) => chargeTypeChecker(ChargeTypeEnum.CreditcardBankCharge, DbCharge, injector),
        ...commonChargeFields,
    },
    Invoice: {
        ...commonDocumentsFields,
    },
    InvoiceReceipt: {
        ...commonDocumentsFields,
    },
    CreditInvoice: {
        ...commonDocumentsFields,
    },
    Proforma: {
        ...commonDocumentsFields,
    },
    Unprocessed: {
        ...commonDocumentsFields,
    },
    OtherDocument: {
        ...commonDocumentsFields,
    },
    Receipt: {
        ...commonDocumentsFields,
    },
    ChargeMetadata: {
        createdAt: DbCharge => DbCharge.created_at,
        updatedAt: DbCharge => DbCharge.updated_at,
        invoicesCount: async (DbCharge, _, { injector }) => {
            try {
                return injector
                    .get(DocumentsProvider)
                    .getDocumentsByChargeIdLoader.load(DbCharge.id)
                    .then(docs => docs.filter(doc => isInvoice(doc.type)).length);
            }
            catch (err) {
                throw errorSimplifier('Error loading invoices', err);
            }
        },
        receiptsCount: async (DbCharge, _, { injector }) => {
            try {
                return injector
                    .get(DocumentsProvider)
                    .getDocumentsByChargeIdLoader.load(DbCharge.id)
                    .then(docs => docs.filter(doc => isReceipt(doc.type)).length);
            }
            catch (err) {
                throw errorSimplifier('Error loading receipts', err);
            }
        },
        documentsCount: async (DbCharge, _, { injector }) => {
            try {
                return injector
                    .get(DocumentsProvider)
                    .getDocumentsByChargeIdLoader.load(DbCharge.id)
                    .then(docs => docs.length);
            }
            catch (err) {
                throw errorSimplifier('Error loading documents', err);
            }
        },
        openDocuments: async (DbCharge, _, { injector }) => {
            try {
                const res = await injector
                    .get(IssuedDocumentsProvider)
                    .getIssuedDocumentsStatusByChargeIdLoader.load(DbCharge.id);
                return res?.open_docs_flag ?? false;
            }
            catch (error) {
                throw errorSimplifier('Error loading open documents status', error);
            }
        },
        transactionsCount: async (DbCharge, _, { injector }) => {
            const transactions = await injector
                .get(TransactionsProvider)
                .transactionsByChargeIDLoader.load(DbCharge.id)
                .catch(error => {
                throw errorSimplifier('Error loading transactions', error);
            });
            return transactions.length;
        },
        ledgerCount: async (DbCharge, _, { injector }) => injector
            .get(LedgerProvider)
            .getLedgerRecordsByChargesIdLoader.load(DbCharge.id)
            .catch(error => {
            throw errorSimplifier('Error loading ledger records', error);
        })
            .then(records => records.length),
        invalidLedger: async (DbCharge, _, context, info) => {
            const { injector } = context;
            try {
                const { ledgerLock } = await injector.get(AdminContextProvider).getVerifiedAdminContext();
                if (await isChargeLocked(DbCharge, injector, ledgerLock)) {
                    return 'VALID';
                }
                const generatedLedgerPromise = ledgerGenerationByCharge(DbCharge, { insertLedgerRecordsIfNotExists: false }, context, info);
                const currentRecordPromise = injector
                    .get(LedgerProvider)
                    .getLedgerRecordsByChargesIdLoader.load(DbCharge.id);
                const [currentRecord, generated] = await Promise.all([
                    currentRecordPromise,
                    generatedLedgerPromise,
                ]);
                if (!generated ||
                    'message' in generated ||
                    generated.balance?.isBalanced === false ||
                    generated.errors?.length > 0) {
                    return 'INVALID';
                }
                const fullMatching = ledgerRecordsGenerationFullMatchComparison(currentRecord, generated.records);
                return fullMatching.isFullyMatched ? 'VALID' : 'DIFF';
            }
            catch (err) {
                console.error(err);
                return 'INVALID';
            }
        },
        miscExpensesCount: async (DbCharge, _, { injector }) => {
            try {
                return injector
                    .get(MiscExpensesProvider)
                    .getExpensesByChargeIdLoader.load(DbCharge.id)
                    .then(res => res.length);
            }
            catch (err) {
                throw errorSimplifier('Error loading misc expenses', err);
            }
        },
        optionalBusinesses: async (DbCharge, _, { injector }) => {
            try {
                const { allBusinessIds } = await getChargeBusinesses(DbCharge.id, injector);
                return allBusinessIds.length > 1 ? allBusinessIds : [];
            }
            catch (error) {
                throw errorSimplifier('Failed to fetch optional businesses', error);
            }
        },
    },
};
//# sourceMappingURL=charges.resolver.js.map