import { endOfYear, startOfYear } from 'date-fns';
import { GraphQLError } from 'graphql';
import { Currency } from '../../../shared/enums.js';
import { dateToTimelessDateString, formatFinancialAmount } from '../../../shared/helpers/index.js';
import { AdminContextProvider } from '../../admin-context/providers/admin-context.provider.js';
import { ScopeProvider } from '../../auth/providers/scope.provider.js';
import { CountriesProvider } from '../../countries/providers/countries.provider.js';
import { BusinessesProvider } from '../../financial-entities/providers/businesses.provider.js';
import { TaxCategoriesProvider } from '../../financial-entities/providers/tax-categories.provider.js';
import { AnnualRevenueReportProvider } from '../providers/annual-revenue-report.provider.js';
export const annualRevenueResolvers = {
    Query: {
        annualRevenueReport: async (_, { filters: { year, adminBusinessId } }, { injector }) => {
            // Per-business report: validate an explicitly requested business against
            // the read scope and use its admin context; default to the primary.
            let targetAdminContext;
            if (adminBusinessId) {
                // Validates the id is within the read scope (throws otherwise), so the
                // requested id can be used directly.
                await injector.get(ScopeProvider).getReadScope([adminBusinessId]);
                targetAdminContext = await injector
                    .get(AdminContextProvider)
                    .adminContextByOwnerIdLoader.load(adminBusinessId);
                if (!targetAdminContext) {
                    throw new GraphQLError('Admin context not found for the requested business', {
                        extensions: { code: 'NOT_FOUND' },
                    });
                }
            }
            else {
                targetAdminContext = await injector.get(AdminContextProvider).getVerifiedAdminContext();
            }
            const ownerId = targetAdminContext.ownerId;
            const incomeTaxCategories = await injector
                .get(TaxCategoriesProvider)
                .taxCategoriesBySortCodeLoader.load(810);
            const date = new Date(year, 6, 1);
            const records = await injector.get(AnnualRevenueReportProvider).getNormalizedRevenueRecords({
                incomeTaxCategoriesIDs: incomeTaxCategories.map(tc => tc.id),
                incomeToCollectId: targetAdminContext.crossYear.incomeToCollectTaxCategoryId,
                ownerId,
                fromDate: dateToTimelessDateString(startOfYear(date)),
                toDate: dateToTimelessDateString(endOfYear(date)),
            });
            // Normalize records (client, amount local currency, amount default foreign currency)
            const businessesProvider = injector.get(BusinessesProvider);
            const normalizedRecords = [];
            const businesses = await Promise.all(records.map(r => r.business_id ? businessesProvider.getBusinessByIdLoader.load(r.business_id) : null));
            records.map((record, index) => {
                if (!record.business_id)
                    return;
                const business = businesses[index];
                if (!business)
                    return;
                const amountIls = record.amount_local ? parseFloat(record.amount_local) : 0;
                const amountUsd = record.amount_usd ? parseFloat(record.amount_usd) : 0;
                normalizedRecords.push({
                    clientId: record.business_id,
                    countryCode: business.country,
                    amountIls,
                    amountUsd,
                    record: {
                        id: record.id ?? '',
                        chargeId: record.charge_id,
                        businessId: record.business_id,
                        date: dateToTimelessDateString(record.date),
                        description: record.description ?? null,
                        reference: record.reference ?? null,
                        amountIls,
                        amountUsd,
                        amountOriginal: record.amount_foreign ? parseFloat(record.amount_foreign) : 0,
                        currency: record.currency,
                    },
                });
            });
            // Group and sum by client
            const clientSums = new Map();
            for (const normalized of normalizedRecords) {
                const existing = clientSums.get(normalized.clientId);
                if (existing) {
                    existing.amountIls += normalized.amountIls;
                    existing.amountUsd += normalized.amountUsd;
                    existing.records.push(normalized.record);
                }
                else {
                    clientSums.set(normalized.clientId, {
                        countryCode: normalized.countryCode,
                        amountIls: normalized.amountIls,
                        amountUsd: normalized.amountUsd,
                        records: [normalized.record],
                    });
                }
            }
            // Group by country
            const countrySums = new Map();
            for (const [clientId, data] of clientSums.entries()) {
                const existing = countrySums.get(data.countryCode);
                if (existing) {
                    existing.amountIls += data.amountIls;
                    existing.amountUsd += data.amountUsd;
                    existing.clients.push({
                        id: clientId,
                        amountIls: data.amountIls,
                        amountUsd: data.amountUsd,
                        records: data.records,
                    });
                }
                else {
                    countrySums.set(data.countryCode, {
                        amountIls: data.amountIls,
                        amountUsd: data.amountUsd,
                        clients: [
                            {
                                id: clientId,
                                amountIls: data.amountIls,
                                amountUsd: data.amountUsd,
                                records: data.records,
                            },
                        ],
                    });
                }
            }
            // Build the response
            const countriesProvider = injector.get(CountriesProvider);
            const countries = await Promise.all(Array.from(countrySums.entries()).map(async ([countryCode, data]) => {
                const country = await countriesProvider.getCountryByCodeLoader.load(countryCode);
                const clients = await Promise.all(data.clients.map(async (client) => {
                    const business = await businessesProvider.getBusinessByIdLoader.load(client.id);
                    return {
                        id: `annual-revenue-report-${year}-${countryCode}-${client.id}`,
                        name: business?.name ?? '',
                        revenueLocal: formatFinancialAmount(client.amountIls, Currency.Ils),
                        revenueDefaultForeign: formatFinancialAmount(client.amountUsd, Currency.Usd),
                        records: client.records.map(record => ({
                            id: `annual-revenue-report-${year}-${countryCode}-${client.id}-record-${record.id}`,
                            chargeId: record.chargeId,
                            date: record.date,
                            description: record.description,
                            reference: record.reference,
                            revenueLocal: formatFinancialAmount(record.amountIls, Currency.Ils),
                            revenueDefaultForeign: formatFinancialAmount(record.amountUsd, Currency.Usd),
                            revenueOriginal: formatFinancialAmount(record.amountOriginal, record.currency),
                        })),
                    };
                }));
                return {
                    id: `annual-revenue-report-${year}-${countryCode}`,
                    code: countryCode,
                    name: country?.name ?? countryCode,
                    revenueLocal: formatFinancialAmount(data.amountIls, Currency.Ils),
                    revenueDefaultForeign: formatFinancialAmount(data.amountUsd, Currency.Usd),
                    clients,
                };
            }));
            return {
                id: year.toString(),
                year,
                countries,
            };
        },
    },
};
//# sourceMappingURL=annual-revenue.resover.js.map