import { GraphQLError } from 'graphql';
import { AdminContextProvider } from '../../admin-context/providers/admin-context.provider.js';
import { deleteCharges } from '../../charges/helpers/delete-charges.helper.js';
import { ChargesProvider } from '../../charges/providers/charges.provider.js';
import { DocumentsProvider } from '../../documents/providers/documents.provider.js';
import { TransactionsProvider } from '../../transactions/providers/transactions.provider.js';
import { createDeelInvoiceMatchFromUnmatchedInvoice, fetchAndFilterInvoices, fetchReceipts, getChargeMatchesForPayments, getContractsFromPaymentBreakdowns, getDeelChargeDescription, insertDeelInvoiceRecord, matchInvoicesWithPayments, validateContracts, } from '../helpers/deel.helper.js';
import { DeelContractsProvider } from '../providers/deel-contracts.provider.js';
export const deelResolvers = {
    Mutation: {
        addDeelContract: async (_, { contractId, contractorId, contractorName, contractStartDate, businessId }, { injector }) => {
            try {
                await injector.get(DeelContractsProvider).insertDeelContract({
                    contractId,
                    contractorId,
                    contractorName,
                    contractStartDate,
                    businessId,
                });
                return true;
            }
            catch (error) {
                const message = `Error adding Deel contract [${contractId}]`;
                console.error(message, error);
                throw new GraphQLError(message);
            }
        },
        fetchDeelDocuments: async (_, __, { injector }) => {
            try {
                const invoices = await fetchAndFilterInvoices(injector);
                if (invoices.length === 0) {
                    return [];
                }
                const receipts = await fetchReceipts(injector);
                const { matches, unmatched } = await matchInvoicesWithPayments(injector, invoices, receipts);
                if (matches.length + unmatched.length <= 0) {
                    return [];
                }
                // fetch contacts and validate
                const contractsInfo = getContractsFromPaymentBreakdowns(matches);
                await validateContracts(contractsInfo, injector);
                const { receiptChargeMap, invoiceChargeMap, newReceipts } = await getChargeMatchesForPayments(injector, receipts);
                const updatedChargeIdsSet = new Set();
                const { ownerId } = await injector.get(AdminContextProvider).getVerifiedAdminContext();
                // insert/update unmatched Deel invoice records
                for (const invoice of unmatched) {
                    if (invoiceChargeMap.has(invoice.id)) {
                        console.log('Found missing match for invoice via invoiceChargeMap:', invoice.id);
                    }
                    const charge = await injector.get(ChargesProvider).generateCharge({
                        ownerId,
                        userDescription: `Deel invoice ${invoice.label}`,
                    });
                    updatedChargeIdsSet.add(charge.id);
                    const match = createDeelInvoiceMatchFromUnmatchedInvoice(invoice);
                    await insertDeelInvoiceRecord(injector, match, charge.id);
                }
                // insert/update matched Deel invoice records
                for (const match of matches) {
                    let chargeId = invoiceChargeMap.get(match.id) ?? receiptChargeMap.get(match.breakdown_receipt_id);
                    // if no charge found, create one from receipt
                    if (!chargeId) {
                        const receipt = newReceipts.find(r => r.id === match.breakdown_receipt_id);
                        if (receipt) {
                            const description = await getDeelChargeDescription(injector, receipt.workers);
                            const charge = await injector.get(ChargesProvider).generateCharge({
                                ownerId,
                                userDescription: description,
                            });
                            chargeId = charge.id;
                            // TODO: upload receipt file (currently not available from Deel API)
                        }
                    }
                    if (!chargeId) {
                        throw new Error('Charge not found for invoice');
                    }
                    updatedChargeIdsSet.add(chargeId);
                    await insertDeelInvoiceRecord(injector, match, chargeId);
                }
                // fetch charges, clean empty ones
                const charges = [];
                await Promise.all(Array.from(updatedChargeIdsSet).map(async (chargeId) => {
                    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) {
                        return;
                    }
                    if (documents.length === 0 && transactions.length === 0) {
                        await deleteCharges([charge.id], injector);
                    }
                    else {
                        charges.push(charge);
                    }
                }));
                return charges;
            }
            catch (error) {
                const message = 'Error fetching Deel documents';
                console.error(message, error);
                throw new GraphQLError(message);
            }
        },
    },
};
//# sourceMappingURL=deel.resolvers.js.map