import { GraphQLError } from 'graphql';
import { FinancialAccountsTaxCategoriesProvider } from '../providers/financial-accounts-tax-categories.provider.js';
import { FinancialAccountsProvider } from '../providers/financial-accounts.provider.js';
import { FinancialBankAccountsProvider } from '../providers/financial-bank-accounts.provider.js';
import { commonFinancialAccountFields, commonFinancialEntityFields, commonTransactionFields, } from './common.js';
export const financialAccountsResolvers = {
    Query: {
        allFinancialAccounts: async (_, __, { injector }) => {
            return injector.get(FinancialAccountsProvider).getAllFinancialAccounts();
        },
        financialAccountsByOwner: async (_, { ownerId }, { injector }) => {
            return injector
                .get(FinancialAccountsProvider)
                .getFinancialAccountsByOwnerIdLoader.load(ownerId);
        },
        financialAccount: async (_, { id }, { injector }) => {
            return injector
                .get(FinancialAccountsProvider)
                .getFinancialAccountByAccountIDLoader.load(id)
                .then(account => {
                if (!account) {
                    throw new GraphQLError('Financial account not found');
                }
                return account;
            });
        },
    },
    Mutation: {
        deleteFinancialAccount: async (_, { id }, { injector }) => {
            return injector
                .get(FinancialAccountsProvider)
                .deleteFinancialAccount({ financialAccountId: id })
                .then(() => true);
        },
        createFinancialAccount: async (_, { input }, { injector }) => {
            try {
                const bankAccount = {
                    accountNumber: input.number,
                    name: input.name,
                    privateBusiness: input.privateOrBusiness,
                    ownerId: input.ownerId,
                    type: input.type,
                };
                const [account] = await injector
                    .get(FinancialAccountsProvider)
                    .insertFinancialAccounts({ bankAccounts: [bankAccount] });
                if (input.bankAccountDetails &&
                    Object.values(input.bankAccountDetails).some(v => v != null)) {
                    await injector.get(FinancialBankAccountsProvider).insertBankAccounts({
                        bankAccounts: [
                            {
                                id: account.id,
                                ownerId: input.ownerId,
                                bankNumber: input.bankAccountDetails.bankNumber,
                                branchNumber: input.bankAccountDetails.branchNumber,
                                iban: input.bankAccountDetails.iban,
                                swiftCode: input.bankAccountDetails.swiftCode,
                                extendedBankNumber: input.bankAccountDetails.extendedBankNumber,
                                partyPreferredIndication: input.bankAccountDetails.partyPreferredIndication,
                                partyAccountInvolvementCode: input.bankAccountDetails.partyAccountInvolvementCode,
                                accountDealDate: input.bankAccountDetails.accountDealDate,
                                accountUpdateDate: input.bankAccountDetails.accountUpdateDate,
                                metegDoarNet: input.bankAccountDetails.metegDoarNet,
                                kodHarshaatPeilut: input.bankAccountDetails.kodHarshaatPeilut,
                                accountClosingReasonCode: input.bankAccountDetails.accountClosingReasonCode,
                                accountAgreementOpeningDate: input.bankAccountDetails.accountAgreementOpeningDate,
                                serviceAuthorizationDesc: input.bankAccountDetails.serviceAuthorizationDesc,
                                branchTypeCode: input.bankAccountDetails.branchTypeCode,
                                mymailEntitlementSwitch: input.bankAccountDetails.mymailEntitlementSwitch,
                                productLabel: input.bankAccountDetails.productLabel,
                            },
                        ],
                    });
                }
                if (input.currencies && input.currencies.length > 0) {
                    await injector
                        .get(FinancialAccountsTaxCategoriesProvider)
                        .insertFinancialAccountTaxCategories({
                        financialAccountsTaxCategories: input.currencies.map(c => ({
                            ownerId: input.ownerId,
                            financialAccountId: account.id,
                            currency: c.currency,
                            taxCategoryId: c.taxCategoryId,
                        })),
                    });
                }
                return account;
            }
            catch (error) {
                const message = 'Failed to create financial account';
                console.error(message, error);
                throw new GraphQLError(message);
            }
        },
        updateFinancialAccount: async (_, { id, fields }, { injector }) => {
            try {
                const updatedAccount = {
                    financialAccountId: id,
                    accountNumber: fields.number,
                    ownerId: fields.ownerId,
                    privateBusiness: fields.privateOrBusiness,
                    type: fields.type,
                };
                const account = await injector
                    .get(FinancialAccountsProvider)
                    .updateFinancialAccount(updatedAccount);
                if (fields.bankAccountDetails &&
                    Object.values(fields.bankAccountDetails).some(v => v != null)) {
                    await injector.get(FinancialBankAccountsProvider).updateBankAccount({
                        bankAccountId: id,
                        accountAgreementOpeningDate: fields.bankAccountDetails.accountAgreementOpeningDate,
                        accountClosingReasonCode: fields.bankAccountDetails.accountClosingReasonCode,
                        accountDealDate: fields.bankAccountDetails.accountDealDate,
                        accountUpdateDate: fields.bankAccountDetails.accountUpdateDate,
                        bankNumber: fields.bankAccountDetails.bankNumber,
                        branchNumber: fields.bankAccountDetails.branchNumber,
                        branchTypeCode: fields.bankAccountDetails.branchTypeCode,
                        extendedBankNumber: fields.bankAccountDetails.extendedBankNumber,
                        iban: fields.bankAccountDetails.iban,
                        swiftCode: fields.bankAccountDetails.swiftCode,
                        kodHarshaatPeilut: fields.bankAccountDetails.kodHarshaatPeilut,
                        metegDoarNet: fields.bankAccountDetails.metegDoarNet,
                        mymailEntitlementSwitch: fields.bankAccountDetails.mymailEntitlementSwitch,
                        partyAccountInvolvementCode: fields.bankAccountDetails.partyAccountInvolvementCode,
                        partyPreferredIndication: fields.bankAccountDetails.partyPreferredIndication,
                        productLabel: fields.bankAccountDetails.productLabel,
                        serviceAuthorizationDesc: fields.bankAccountDetails.serviceAuthorizationDesc,
                    });
                }
                if (fields.currencies && fields.currencies.length > 0) {
                    const currentTaxCategories = await injector
                        .get(FinancialAccountsTaxCategoriesProvider)
                        .getFinancialAccountTaxCategoriesByFinancialAccountIdLoader.load(account.id);
                    if (currentTaxCategories.length > 0) {
                        const updateTaxCategories = [];
                        // check for tax categories to delete - those that exist currently but are not included in the input
                        const taxCategoriesToDelete = currentTaxCategories.filter(ctc => !fields.currencies.some(inputTaxCategory => inputTaxCategory.currency === ctc.currency));
                        if (taxCategoriesToDelete.length > 0) {
                            updateTaxCategories.push(injector
                                .get(FinancialAccountsTaxCategoriesProvider)
                                .deleteFinancialAccountTaxCategories({
                                financialAccountId: account.id,
                                currencies: taxCategoriesToDelete.map(tc => tc.currency),
                            }));
                        }
                        const taxCategoriesToInsert = [];
                        fields.currencies.map(inputTaxCategory => {
                            const currentTaxCategory = currentTaxCategories.find(ctc => ctc.currency === inputTaxCategory.currency);
                            if (currentTaxCategory) {
                                if (currentTaxCategory.tax_category_id !== inputTaxCategory.taxCategoryId) {
                                    // tax category changed for this currency, update it
                                }
                                updateTaxCategories.push(injector
                                    .get(FinancialAccountsTaxCategoriesProvider)
                                    .updateFinancialAccountTaxCategory({
                                    financialAccountId: account.id,
                                    currency: inputTaxCategory.currency,
                                    taxCategoryId: inputTaxCategory.taxCategoryId,
                                }));
                            }
                            else {
                                // new tax category for this account, insert it
                                taxCategoriesToInsert.push({
                                    ownerId: account.owner_id,
                                    financialAccountId: account.id,
                                    currency: inputTaxCategory.currency,
                                    taxCategoryId: inputTaxCategory.taxCategoryId,
                                });
                            }
                        });
                        if (taxCategoriesToInsert.length > 0) {
                            updateTaxCategories.push(injector
                                .get(FinancialAccountsTaxCategoriesProvider)
                                .insertFinancialAccountTaxCategories({
                                financialAccountsTaxCategories: taxCategoriesToInsert,
                            }));
                        }
                        await Promise.all(updateTaxCategories);
                    }
                    else {
                        // none existing,insert all
                        await injector
                            .get(FinancialAccountsTaxCategoriesProvider)
                            .insertFinancialAccountTaxCategories({
                            financialAccountsTaxCategories: fields.currencies.map(c => ({
                                ownerId: account.owner_id,
                                financialAccountId: account.id,
                                currency: c.currency,
                                taxCategoryId: c.taxCategoryId,
                            })),
                        });
                    }
                }
                return account;
            }
            catch (error) {
                const message = 'Failed to update financial account';
                console.error(message, error);
                throw new GraphQLError(message);
            }
        },
    },
    CardFinancialAccount: {
        __isTypeOf: DbAccount => DbAccount.type === 'CREDIT_CARD',
        ...commonFinancialAccountFields,
        fourDigits: DbAccount => DbAccount.account_number,
        name: DbAccount => DbAccount.account_name ?? DbAccount.account_number,
    },
    CryptoWalletFinancialAccount: {
        __isTypeOf: DbAccount => DbAccount.type === 'CRYPTO_WALLET',
        ...commonFinancialAccountFields,
        name: DbAccount => DbAccount.account_name ??
            (DbAccount.account_number.length >= 20
                ? DbAccount.account_number.slice(-8)
                : DbAccount.account_number),
    },
    ForeignSecuritiesFinancialAccount: {
        __isTypeOf: DbAccount => DbAccount.type === 'FOREIGN_SECURITIES',
        ...commonFinancialAccountFields,
        name: DbAccount => DbAccount.account_name ?? DbAccount.account_number,
    },
    BankDepositFinancialAccount: {
        __isTypeOf: DbAccount => DbAccount.type === 'BANK_DEPOSIT_ACCOUNT',
        ...commonFinancialAccountFields,
        name: DbAccount => DbAccount.account_name ?? DbAccount.account_number,
    },
    ConversionTransaction: {
        ...commonTransactionFields,
    },
    CommonTransaction: {
        ...commonTransactionFields,
    },
    LtdFinancialEntity: {
        ...commonFinancialEntityFields,
    },
    PersonalFinancialEntity: {
        ...commonFinancialEntityFields,
    },
};
//# sourceMappingURL=financial-accounts.resolver.js.map