import { GraphQLError } from 'graphql';
import { dateToTimelessDateString, formatFinancialAmount } from '../../../shared/helpers/index.js';
import { AdminContextProvider } from '../../admin-context/providers/admin-context.provider.js';
import { ExchangeProvider } from '../../exchange-rates/providers/exchange.provider.js';
import { getTransactionDebitDate } from '../../transactions/helpers/debit-date.helper.js';
import { TransactionsProvider } from '../../transactions/providers/transactions.provider.js';
export const chartsResolvers = {
    Query: {
        incomeExpenseChart: async (_, { filters }, { injector }) => {
            try {
                const { ownerId, defaultCryptoConversionFiatCurrency } = await injector
                    .get(AdminContextProvider)
                    .getVerifiedAdminContext();
                const transactions = await injector.get(TransactionsProvider).getTransactionsByFilters({
                    fromDebitDate: filters.fromDate,
                    toDebitDate: filters.toDate,
                    ownerIDs: [ownerId],
                });
                const currency = filters.currency ?? defaultCryptoConversionFiatCurrency;
                const monthDataMap = new Map();
                await Promise.all(transactions.map(async (transaction) => {
                    const date = getTransactionDebitDate(transaction);
                    // convert amount to chart currency
                    const exchangeRate = await injector
                        .get(ExchangeProvider)
                        .getExchangeRates(transaction.currency, currency, date);
                    // add amount to relevant month
                    const monthTag = dateToTimelessDateString(new Date(date.getFullYear(), date.getMonth(), 1));
                    if (!monthDataMap.has(monthTag)) {
                        monthDataMap.set(monthTag, { income: 0, expense: 0, balance: 0 });
                    }
                    const monthData = monthDataMap.get(monthTag);
                    const amount = Number(transaction.amount);
                    if (amount > 0) {
                        monthData.income += Math.abs(amount) * exchangeRate;
                    }
                    else {
                        monthData.expense += Math.abs(amount) * exchangeRate;
                    }
                }));
                const INITIAL_BALANCE = 0;
                let balance = INITIAL_BALANCE;
                const orderedMonthInfo = Array.from(monthDataMap.entries()).sort(([dateA], [dateB]) => dateA.localeCompare(dateB));
                const monthlyData = [];
                for (const [date, data] of orderedMonthInfo) {
                    balance += data.income - data.expense;
                    const monthBalance = balance;
                    monthlyData.push({
                        date,
                        ...data,
                        balance: monthBalance,
                        currency,
                    });
                }
                return {
                    fromDate: filters.fromDate,
                    toDate: filters.toDate,
                    currency,
                    monthlyData,
                };
            }
            catch (e) {
                console.error('Error fetching income/expense chart info', e);
                throw new GraphQLError(e?.message ?? 'Error fetching chart info');
            }
        },
    },
    IncomeExpenseChartMonthData: {
        date: proto => proto.date,
        income: proto => formatFinancialAmount(proto.income, proto.currency),
        expense: proto => formatFinancialAmount(proto.expense, proto.currency),
        balance: proto => formatFinancialAmount(proto.balance, proto.currency),
    },
};
//# sourceMappingURL=charts.resolver.js.map