import { GraphQLError } from 'graphql';
import { Currency } from '../../../shared/enums.js';
import { dateToTimelessDateString, formatCurrency } from '../../../shared/helpers/index.js';
import { AdminContextProvider } from '../../admin-context/providers/admin-context.provider.js';
import { getChargeDocumentsMeta, getChargeLedgerMeta, getChargeTransactionsMeta, } from '../../charges/helpers/common.helper.js';
import { TransactionsProvider } from '../../transactions/providers/transactions.provider.js';
import { defineConversionBaseAndQuote, getFiatExchangeRate } from '../helpers/exchange.helper.js';
import { ExchangeProvider } from '../providers/exchange.provider.js';
import { commonTransactionFields } from './common.js';
export const exchangeResolvers = {
    Query: {
        exchangeRates: async (_, { date }) => {
            if (!date) {
                throw new GraphQLError('Date is required');
            }
            return date;
        },
    },
    ExchangeRates: {
        usd: async (timelessDate, _, { injector }) => getFiatExchangeRate(injector, timelessDate, 'usd'),
        gbp: async (timelessDate, _, { injector }) => getFiatExchangeRate(injector, timelessDate, 'gbp'),
        eur: async (timelessDate, _, { injector }) => getFiatExchangeRate(injector, timelessDate, 'eur'),
        cad: async (timelessDate, _, { injector }) => getFiatExchangeRate(injector, timelessDate, 'cad'),
        jpy: async (timelessDate, _, { injector }) => getFiatExchangeRate(injector, timelessDate, 'jpy'),
        aud: async (timelessDate, _, { injector }) => getFiatExchangeRate(injector, timelessDate, 'aud'),
        sek: async (timelessDate, _, { injector }) => getFiatExchangeRate(injector, timelessDate, 'sek'),
        ils: () => {
            return 1;
        },
        grt: async (timelessDate, _, { injector }) => {
            const { defaultLocalCurrency } = await injector
                .get(AdminContextProvider)
                .getVerifiedAdminContext();
            const exchangeRates = await injector
                .get(ExchangeProvider)
                .getExchangeRates(Currency.Grt, defaultLocalCurrency, new Date(timelessDate));
            if (!exchangeRates) {
                return null;
            }
            return typeof exchangeRates === 'string' ? parseFloat(exchangeRates) : exchangeRates;
        },
        eth: async (timelessDate, _, { injector }) => {
            const { defaultLocalCurrency } = await injector
                .get(AdminContextProvider)
                .getVerifiedAdminContext();
            const exchangeRates = await injector
                .get(ExchangeProvider)
                .getExchangeRates(Currency.Eth, defaultLocalCurrency, new Date(timelessDate));
            if (!exchangeRates) {
                return null;
            }
            return typeof exchangeRates === 'string' ? parseFloat(exchangeRates) : exchangeRates;
        },
        usdc: async (timelessDate, _, { injector }) => {
            const { defaultLocalCurrency } = await injector
                .get(AdminContextProvider)
                .getVerifiedAdminContext();
            const exchangeRates = await injector
                .get(ExchangeProvider)
                .getExchangeRates(Currency.Usdc, defaultLocalCurrency, new Date(timelessDate));
            if (!exchangeRates) {
                return null;
            }
            return typeof exchangeRates === 'string' ? parseFloat(exchangeRates) : exchangeRates;
        },
        date: timelessDate => timelessDate,
    },
    FinancialCharge: {
        exchangeRates: async (DbCharge, _, { injector }) => {
            const [{ transactionsMinDebitDate }, { ledgerMinInvoiceDate }, { documentsMinDate }] = await Promise.all([
                getChargeTransactionsMeta(DbCharge.id, injector),
                getChargeLedgerMeta(DbCharge.id, injector),
                getChargeDocumentsMeta(DbCharge.id, injector),
            ]);
            const ratesDate = transactionsMinDebitDate || documentsMinDate || ledgerMinInvoiceDate;
            if (!ratesDate) {
                return null;
            }
            return dateToTimelessDateString(ratesDate);
        },
    },
    ConversionCharge: {
        officialRate: async (dbCharge, _, { injector }) => {
            const transactions = await injector
                .get(TransactionsProvider)
                .transactionsByChargeIDLoader.load(dbCharge.id);
            if (!transactions) {
                throw new GraphQLError(`Couldn't find any transactions for charge ID="${dbCharge.id}"`);
            }
            const { baseTransaction, quoteTransaction } = defineConversionBaseAndQuote(transactions);
            const baseCurrency = formatCurrency(baseTransaction.currency);
            const quoteCurrency = formatCurrency(quoteTransaction.currency);
            const date = baseTransaction.debit_timestamp ||
                quoteTransaction.debit_timestamp ||
                baseTransaction.debit_date_override ||
                baseTransaction.debit_date;
            const rate = await injector
                .get(ExchangeProvider)
                .getExchangeRates(baseCurrency, quoteCurrency, date);
            return {
                from: baseCurrency,
                to: quoteCurrency,
                rate,
            };
        },
        eventRate: async (dbCharge, _, { injector }) => {
            const transactions = await injector
                .get(TransactionsProvider)
                .transactionsByChargeIDLoader.load(dbCharge.id);
            const { baseTransaction, quoteTransaction } = defineConversionBaseAndQuote(transactions);
            const baseCurrency = formatCurrency(baseTransaction.currency);
            const quoteCurrency = formatCurrency(quoteTransaction.currency);
            let rate = undefined;
            for (const transaction of [baseTransaction, quoteTransaction]) {
                if (transaction.currency_rate && transaction.currency_rate !== '0') {
                    const transactionRate = Number(transaction.currency_rate);
                    if (rate && rate !== transactionRate) {
                        throw new GraphQLError(`Multiple rates found for charge ID="${dbCharge.id}"`);
                    }
                    rate = transactionRate;
                }
            }
            if (!rate) {
                throw new GraphQLError(`Couldn't find any rate for charge ID="${dbCharge.id}"`);
            }
            return {
                from: baseCurrency,
                to: quoteCurrency,
                rate,
            };
        },
    },
    CommonTransaction: {
        ...commonTransactionFields,
    },
    ConversionTransaction: {
        ...commonTransactionFields,
    },
};
//# sourceMappingURL=exchange.resolver.js.map