import { differenceInDays } from 'date-fns';
import { GraphQLError } from 'graphql';
import { accommodationExpenseDataCollector, BusinessTripError, calculateTotalReportSummaryCategory, carRentalExpensesDataCollector, convertSummaryCategoryDataToRow, flightExpenseDataCollector, onlyUnique, otherExpensesDataCollector, travelAndSubsistenceExpensesDataCollector, } from '../helpers/business-trip-report.helper.js';
import { BusinessTripAttendeesProvider } from '../providers/business-trips-attendees.provider.js';
import { BusinessTripExpensesProvider } from '../providers/business-trips-expenses.provider.js';
import { BusinessTripTaxVariablesProvider } from '../providers/business-trips-tax-variables.provider.js';
export async function businessTripSummary(injector, dbBusinessTrip) {
    try {
        const attendees = await injector
            .get(BusinessTripAttendeesProvider)
            .getBusinessTripsAttendeesByBusinessTripIdLoader.load(dbBusinessTrip.id);
        if (!attendees?.length) {
            return {
                rows: [],
                errors: ['Attendees are not set'],
            };
        }
        let fromDate;
        let toDate;
        attendees.map(attendee => {
            const { arrival, departure } = attendee;
            if (arrival && (!fromDate || arrival < fromDate)) {
                fromDate = arrival;
            }
            if (departure && (!toDate || departure > toDate)) {
                toDate = departure;
            }
        });
        if (!fromDate || !toDate) {
            return {
                rows: [],
                errors: ['Business trip dates are not set'],
            };
        }
        const expensesPromise = await injector
            .get(BusinessTripExpensesProvider)
            .getBusinessTripExtendedExpensesByBusinessTripId(dbBusinessTrip.id);
        const taxVariablesPromise = injector
            .get(BusinessTripTaxVariablesProvider)
            .getTaxVariablesByDateLoader.load(toDate);
        const [{ flightExpenses, accommodationsExpenses, travelAndSubsistenceExpenses, otherExpenses, carRentalExpenses, }, taxVariables,] = await Promise.all([expensesPromise, taxVariablesPromise]);
        if (!taxVariables) {
            return {
                rows: [],
                errors: ['Tax variables are not set'],
            };
        }
        const summaryData = {};
        const attendeesMap = new Map();
        attendees.map(attendee => {
            const { arrival, departure } = attendee;
            let daysCount = 0;
            let nightsCount = 0;
            if (arrival && departure) {
                daysCount = differenceInDays(departure, arrival) + 1;
                nightsCount = daysCount - 1;
            }
            attendeesMap.set(attendee.id, {
                name: attendee.name,
                arrival,
                departure,
                daysCount,
                nightsCount,
            });
        });
        const errors = [];
        const [unAccommodatedDays] = await Promise.all([
            accommodationExpenseDataCollector(injector, accommodationsExpenses, summaryData, dbBusinessTrip.destination, taxVariables, attendeesMap).catch(e => {
                if (e instanceof BusinessTripError) {
                    errors.push(e.message);
                }
                else {
                    console.error(`Error handling accommodation expenses`, e);
                    throw new GraphQLError(e?.message ?? `Error handling accommodation expenses`);
                }
            }),
            ...flightExpenses.map(flightExpense => flightExpenseDataCollector(injector, flightExpense, summaryData).catch(e => {
                if (e instanceof BusinessTripError) {
                    errors.push(e.message);
                }
                else {
                    console.error(`Error handling flight expenses`, e);
                    throw new GraphQLError(e?.message ?? `Error handling flight expenses`);
                }
            })),
            otherExpensesDataCollector(injector, otherExpenses, summaryData).catch(e => {
                if (e instanceof BusinessTripError) {
                    errors.push(e.message);
                }
                else {
                    console.error(`Error handling other expenses`, e);
                    throw new GraphQLError(e?.message ?? `Error handling other expenses`);
                }
            }),
            carRentalExpensesDataCollector(injector, carRentalExpenses, summaryData, taxVariables, dbBusinessTrip.destination).catch(e => {
                if (e instanceof BusinessTripError) {
                    errors.push(e.message);
                }
                else {
                    console.error(`Error handling car rental expenses`, e);
                    throw new GraphQLError(e?.message ?? `Error handling car rental expenses`);
                }
            }),
        ]);
        await travelAndSubsistenceExpensesDataCollector(injector, travelAndSubsistenceExpenses, summaryData, taxVariables, {
            destinationCode: dbBusinessTrip.destination,
            attendees: attendeesMap,
            unAccommodatedDays: unAccommodatedDays ?? 0,
        }).catch(e => {
            if (e instanceof BusinessTripError) {
                errors.push(e.message);
            }
            else {
                console.error(`Error handling travel and subsistence expenses`, e);
                throw new GraphQLError(e?.message ?? `Error handling travel and subsistence expenses`);
            }
        });
        const totalSumCategory = calculateTotalReportSummaryCategory(summaryData);
        summaryData['TOTAL'] = totalSumCategory;
        return {
            rows: Object.entries(summaryData).map(([category, data]) => convertSummaryCategoryDataToRow(category, data)),
            errors: errors.length ? errors.filter(onlyUnique) : undefined,
        };
    }
    catch (e) {
        console.error(`Error fetching business trip expenses`, e);
        throw new GraphQLError(e?.message ?? `Error fetching business trip expenses`);
    }
}
//# sourceMappingURL=business-trip-summary.resolver.js.map