"use strict";
/**
 * money-allocation controller
 */
Object.defineProperty(exports, "__esModule", { value: true });
const strapi_1 = require("@strapi/strapi");
const helpers_1 = require("../../../utils/helpers");
const campus_1 = require("../../campus/controllers/campus");
exports.default = strapi_1.factories.createCoreController("api::money-allocation.money-allocation", ({ strapi }) => ({
    async org(ctx) {
        let theYear = (0, helpers_1.getMonthsForYearFromDate)(new Date());
        let accumilation = [];
        let networks = await strapi.entityService.findMany("api::network.network");
        for (let nidx = 0; nidx < networks.length; nidx++) {
            let network = networks[nidx];
            let ctx = {
                params: {
                    id: network.id,
                },
            };
            let summary = await this.network(ctx);
            accumilation.push({ network, ...summary });
        }
        let inOneYear = [];
        for (let ntidx = 0; ntidx < networks.length; ntidx++) {
            const network = networks[ntidx];
            let campuses = await strapi.entityService.findMany("api::campus.campus", {
                filters: {
                    network: {
                        id: network.id,
                    },
                },
            });
            let singleNetwork = [];
            // get network allocations for diffent months
            for (let yidx = 0; yidx < theYear.length; yidx++) {
                const month = theYear[yidx];
                // network allocations for in the network at monthly interval
                let results = await strapi.entityService.findMany("api::money-allocation.money-allocation", {
                    filters: {
                        date: {
                            $gte: month.startDate,
                            $lte: month.endDate,
                        },
                        campus: {
                            id: {
                                $in: campuses.map((it) => it.id),
                            },
                        },
                    },
                    populate: "*",
                });
                let allocation = results.reduce((acc, curr) => curr.amount + acc, 0);
                singleNetwork.push({
                    month: month.name,
                    allocation,
                });
            }
            inOneYear.push({ network, allocations: singleNetwork });
        }
        let recent = await strapi.entityService.findMany("api::money-allocation.money-allocation", {
            filters: {},
            sort: "date:desc",
            populate: "*",
            limit: 8,
        });
        for (let index = 0; index < recent.length; index++) {
            const allocation = recent[index];
            recent[index].campus = await strapi.entityService.findOne("api::campus.campus", allocation.campus.id, {
                populate: "network",
            });
        }
        recent = (0, campus_1.omitFieldsRecursively)(recent);
        ctx.body = {
            data: { networks: inOneYear, entries: accumilation, recent },
            meta: {},
        };
    },
    async network(ctx) {
        var _a;
        let theYear = (0, helpers_1.getMonthsForYearFromDate)(new Date());
        let netId = ctx.params.id;
        let type = ((_a = ctx === null || ctx === void 0 ? void 0 : ctx.query) === null || _a === void 0 ? void 0 : _a.type) || "";
        let network = await strapi.entityService.findOne("api::network.network", netId, {
            populate: "*",
        });
        if (!network) {
            ctx.body = { data: [], meta: {} };
            return;
        }
        if (type === "graph") {
            let chartData = [];
            for (let yidx = 0; yidx < theYear.length; yidx++) {
                const month = theYear[yidx];
                let chartItem = await strapi.entityService
                    .findMany("api::money-allocation.money-allocation", {
                    filters: {
                        date: {
                            $gte: month.startDate,
                            $lte: month.endDate,
                        },
                        network: {
                            id: netId,
                        },
                    },
                })
                    .then((it) => it.reduce((acc, curr) => {
                    acc += curr.amount;
                    return acc;
                }, 0));
                chartData.push({
                    month: month.name,
                    total: chartItem,
                });
            }
            ctx.body = {
                data: chartData.reverse(),
                meta: {},
            };
            return;
        }
        let campuses = network.campuses;
        let inOneYear = [];
        // loop through all campuses in the network
        for (let cidx = 0; cidx < campuses.length; cidx++) {
            let campus = campuses[cidx];
            let singleNetwork = [];
            for (let yidx = 0; yidx < theYear.length; yidx++) {
                const month = theYear[yidx];
                let results = await strapi.entityService.findMany("api::money-allocation.money-allocation", {
                    filters: {
                        date: {
                            $gte: month.startDate,
                            $lte: month.endDate,
                        },
                        campus: {
                            id: {
                                $eq: campus.id,
                            },
                        },
                    },
                    populate: "*",
                });
                let allocation = results.reduce((acc, curr) => curr.amount + acc, 0);
                singleNetwork.push({
                    month: month.name,
                    allocation,
                });
            }
            inOneYear.push({
                name: campus.name,
                allocations: singleNetwork.reverse(),
            });
        }
        let week = await findNetworkallocations(network, strapi, (0, helpers_1.getStartOfWeek)());
        let month = await findNetworkallocations(network, strapi, (0, helpers_1.getStartOfMonth)());
        let lastMonth = await findNetworkallocations(network, strapi, (0, helpers_1.getStartOfPreviousMonth)());
        let day = await findNetworkallocations(network, strapi, (0, helpers_1.getMidnightToday)());
        let res = {
            network,
            day,
            week,
            month,
            lastMonth,
        };
        ctx.body = {
            data: {
                ...res,
                campuses: inOneYear,
            },
            meta: {},
        };
        return ctx.body.data;
    },
    async campus(ctx) {
        var _a;
        let campusId = ctx.params.id;
        let theYear = (0, helpers_1.getMonthsForYearFromDate)(new Date());
        let type = ((_a = ctx === null || ctx === void 0 ? void 0 : ctx.query) === null || _a === void 0 ? void 0 : _a.type) || "";
        let recent = await strapi.entityService.findMany("api::money-allocation.money-allocation", {
            filters: {
                campus: { id: campusId },
            },
            sort: "date:desc",
            populate: "*",
            limit: 8,
        });
        let campus = await strapi.entityService.findOne("api::campus.campus", campusId);
        if (!campus) {
            ctx.body = { data: [], meta: {} };
            return;
        }
        if (type === "graph") {
            let chartData = [];
            for (let yidx = 0; yidx < theYear.length; yidx++) {
                const month = theYear[yidx];
                let chartItem = await strapi.entityService
                    .findMany("api::money-allocation.money-allocation", {
                    filters: {
                        date: {
                            $gte: month.startDate,
                            $lte: month.endDate,
                        },
                        campus: {
                            id: campusId,
                        },
                    },
                })
                    .then((it) => it.reduce((acc, curr) => {
                    acc += curr.amount;
                    return acc;
                }, 0));
                chartData.push({
                    month: month.name,
                    total: chartItem,
                });
            }
            ctx.body = {
                data: chartData.reverse(),
                meta: {},
            };
            return;
        }
        for (let index = 0; index < recent.length; index++) {
            const expense = recent[index];
            recent[index].campus = await strapi.entityService.findOne("api::campus.campus", expense.campus.id, {
                populate: "network",
            });
        }
        recent = (0, campus_1.omitFieldsRecursively)(recent);
        let yearInfo = (0, helpers_1.getYearMonthsFromToday)();
        let recordsForTheYear = [];
        for (let yidx = 0; yidx < yearInfo.length; yidx++) {
            const info = yearInfo[yidx];
            let expenses = await strapi.entityService.findMany("api::money-allocation.money-allocation", {
                filters: {
                    campus: {
                        id: campusId,
                    },
                    date: {
                        $gte: info.startDate,
                        $lte: info.endDate,
                    },
                },
            });
            let total = expenses.reduce((acc, expense) => acc + expense.amount, 0);
            recordsForTheYear.push({
                month: info.name,
                total,
            });
        }
        ctx.body = {
            data: {
                recent,
                year: recordsForTheYear.reverse(),
            },
        };
    },
}));
async function findNetworkallocations(network, strapi, period) {
    let campusIds = await strapi.entityService
        .findMany("api::campus.campus", {
        filters: {
            network: {
                id: network.id,
            },
        },
    })
        .then((it) => it.map((campus) => campus.id));
    let allocations = await strapi.entityService.findMany("api::money-allocation.money-allocation", {
        filters: {
            date: {
                $gte: period,
            },
            campus: {
                id: {
                    $in: campusIds,
                },
            },
        },
        populate: "*",
    });
    // let grouped = groupByNest(allocations, "campus.name");
    let bymap = allocations.reduce((prev, allocation) => {
        if (allocation.campus.name in prev) {
            prev[allocation.campus.name].push(allocation);
        }
        else {
            prev[allocation.campus.name] = [];
            prev[allocation.campus.name].push(allocation);
        }
        return prev;
    }, {});
    // bymap = {campus:[allocation]}
    let networkSummary = Object.keys(bymap).map((key) => {
        let allocation = bymap[key].reduce((sum, ex) => ex.amount + sum, 0);
        return { campus: key, allocation };
    });
    let reduced = networkSummary.reduce((sum, it) => sum + it.allocation, 0);
    return {
        allocation: reduced,
        entries: networkSummary,
    };
}
