"use strict";
/**
 * discipleship-group controller
 */
Object.defineProperty(exports, "__esModule", { value: true });
const strapi_1 = require("@strapi/strapi");
const campus_1 = require("../../campus/controllers/campus");
const helpers_1 = require("../../../utils/helpers");
const network_1 = require("../../network/controllers/network");
exports.default = strapi_1.factories.createCoreController("api::discipleship-group.discipleship-group", ({ strapi }) => ({
    async org(ctx) {
        let type = ctx.query.type || "";
        let data = await getOrgSummary(strapi, type);
        return { data: data, meta: {} };
    },
    async myf(ctx) {
        let type = "graph";
        let data = (await getOrgSummary(strapi, type));
        data = data.map((it) => ({
            month: it.month,
            total: it.myf,
        }));
        let total = data.reduce((acc, curr) => {
            acc += curr.total;
            return acc;
        }, 0);
        return { data: data, meta: {} };
    },
    async visitors(ctx) {
        let type = "graph";
        let data = (await getOrgSummary(strapi, type));
        data = data.map((it) => ({
            month: it.month,
            total: it.visitors,
        }));
        let total = data.reduce((acc, curr) => {
            acc += curr.total;
            return acc;
        }, 0);
        return { data: data, meta: {} };
    },
    async mavunoKids(ctx) {
        let type = "graph";
        let data = (await getOrgSummary(strapi, type));
        data = data.map((it) => ({
            month: it.month,
            total: it.mavunoKids,
        }));
        let total = data.reduce((acc, curr) => {
            acc += curr.total;
            return acc;
        }, 0);
        return { data: data, meta: {} };
    },
    async salvations(ctx) {
        let type = "graph";
        let data = (await getOrgSummary(strapi, type));
        data = data.map((it) => ({
            month: it.month,
            total: it.salvations,
        }));
        let total = data.reduce((acc, curr) => {
            acc += curr.total;
            return acc;
        }, 0);
        return { data: data, meta: {} };
    },
    async campusTrend(ctx) {
        let type = "graph";
        let data = (await getOrgSummary(strapi, type));
        data = data.map((it) => ({
            month: it.month,
            total: it.campusTrend,
        }));
        let total = data.reduce((acc, curr) => {
            acc += curr.total;
            return acc;
        }, 0);
        return { data: data, meta: {} };
    },
    async dgs(ctx) {
        let type = "graph";
        let data = (await getOrgSummary(strapi, type));
        data = data.map((it) => ({
            month: it.month,
            total: it.discipleshipGroup,
        }));
        let total = data.reduce((acc, curr) => {
            acc += curr.total;
            return acc;
        }, 0);
        return { data: data, meta: {} };
    },
    async network(ctx) {
        let type = ctx.query.type || "";
        if ((0, helpers_1.isValidInteger)(ctx.params.id) === false) {
            return;
        }
        let data = await getNetworkSummary(strapi, ctx.params.id, type);
        ctx.body = { data, meta: {} };
    },
    async myfN(ctx) {
        if ((0, helpers_1.isValidInteger)(ctx.params.id) === false) {
            return;
        }
        let type = "graph";
        let data = (await getNetworkSummary(strapi, ctx.params.id, type));
        data = data.map((it) => ({
            month: it.month,
            total: it.myf,
        }));
        let total = data.reduce((acc, curr) => {
            acc += curr.total;
            return acc;
        }, 0);
        return { data: data, meta: {} };
    },
    async visitorsN(ctx) {
        if ((0, helpers_1.isValidInteger)(ctx.params.id) === false) {
            return;
        }
        let type = "graph";
        let data = (await getNetworkSummary(strapi, ctx.params.id, type));
        data = data.map((it) => ({
            month: it.month,
            total: it.visitors,
        }));
        let total = data.reduce((acc, curr) => {
            acc += curr.total;
            return acc;
        }, 0);
        return { data: data, meta: {} };
    },
    async mavunoKidsN(ctx) {
        let type = "graph";
        let data = (await getNetworkSummary(strapi, ctx.params.id, type));
        data = data.map((it) => ({
            month: it.month,
            total: it.mavunoKids,
        }));
        let total = data.reduce((acc, curr) => {
            acc += curr.total;
            return acc;
        }, 0);
        return { data: data, meta: {} };
    },
    async salvationsN(ctx) {
        let type = "graph";
        let data = (await getNetworkSummary(strapi, ctx.params.id, type));
        data = data.map((it) => ({
            month: it.month,
            total: it.salvations,
        }));
        let total = data.reduce((acc, curr) => {
            acc += curr.total;
            return acc;
        }, 0);
        return { data: data, meta: {} };
    },
    async campusTrendN(ctx) {
        let type = "graph";
        let data = (await getNetworkSummary(strapi, ctx.params.id, type));
        data = data.map((it) => ({
            month: it.month,
            total: it.campusTrend,
        }));
        let total = data.reduce((acc, curr) => {
            acc += curr.total;
            return acc;
        }, 0);
        return { data: data, meta: {} };
    },
    async dgsN(ctx) {
        let type = "graph";
        let data = (await getNetworkSummary(strapi, ctx.params.id, type));
        data = data.map((it) => ({
            month: it.month,
            total: it.discipleshipGroup,
        }));
        let total = data.reduce((acc, curr) => {
            acc += curr.total;
            return acc;
        }, 0);
        return { data: data, meta: {} };
    },
    async campus(ctx) {
        let type = ctx.query.type || "";
        if ((0, helpers_1.isValidInteger)(ctx.params.id) === false) {
            return;
        }
        let data = await getCampusSummary(strapi, ctx.params.id, type);
        ctx.body = { data, meta: {} };
    },
    async myfC(ctx) {
        if ((0, helpers_1.isValidInteger)(ctx.params.id) === false) {
            return;
        }
        let type = "graph";
        let data = (await getCampusSummary(strapi, ctx.params.id, type));
        data = data.map((it) => ({
            month: it.month,
            total: it.myf,
        }));
        let total = data.reduce((acc, curr) => {
            acc += curr.total;
            return acc;
        }, 0);
        return { data: data, meta: {} };
    },
    async mavunoKidsC(ctx) {
        let type = "graph";
        let data = (await getNetworkSummary(strapi, ctx.params.id, type));
        data = data.map((it) => ({
            month: it.month,
            total: it.mavunoKids,
        }));
        let total = data.reduce((acc, curr) => {
            acc += curr.total;
            return acc;
        }, 0);
        return { data: data, meta: {} };
    },
    async visitorsC(ctx) {
        if ((0, helpers_1.isValidInteger)(ctx.params.id) === false) {
            return;
        }
        let type = "graph";
        let data = (await getCampusSummary(strapi, ctx.params.id, type));
        data = data.map((it) => ({
            month: it.month,
            total: it.mavunoKids,
        }));
        let total = data.reduce((acc, curr) => {
            acc += curr.total;
            return acc;
        }, 0);
        return { data: data, meta: {} };
    },
    async salvationsC(ctx) {
        let type = "graph";
        let data = (await getCampusSummary(strapi, ctx.params.id, type));
        data = data.map((it) => ({
            month: it.month,
            total: it.salvations,
        }));
        let total = data.reduce((acc, curr) => {
            acc += curr.total;
            return acc;
        }, 0);
        return { data: data, meta: {} };
    },
    async campusTrendC(ctx) {
        let type = "graph";
        let data = (await getCampusSummary(strapi, ctx.params.id, type));
        data = data.map((it) => ({
            month: it.month,
            total: it.discipleshipGroup,
        }));
        let total = data.reduce((acc, curr) => {
            acc += curr.total;
            return acc;
        }, 0);
        return { data: data, meta: {} };
    },
    async dgsC(ctx) {
        let type = "graph";
        let data = (await getCampusSummary(strapi, ctx.params.id, type));
        data = data.map((it) => ({
            month: it.month,
            total: it.discipleshipGroup,
        }));
        let total = data.reduce((acc, curr) => {
            acc += curr.total;
            return acc;
        }, 0);
        return { data: data, meta: {} };
    },
    async zone(ctx) {
        if ((0, helpers_1.isValidInteger)(ctx.params.id) === false) {
            return;
        }
        let data = await dgListingLevel(strapi, ctx.params.id);
        ctx.body = { data, meta: {} };
    },
}));
async function getOrgSummary(strapi, type) {
    let dgThisMonth = await strapi.entityService.count("api::discipleship-group.discipleship-group", {
        filters: {
            createdAt: {
                $gte: (0, helpers_1.getStartOfMonth)(),
            },
        },
    });
    let dgLastMonth = await strapi.entityService.count("api::discipleship-group.discipleship-group", {
        filters: {
            createdAt: {
                $lte: (0, helpers_1.getStartOfMonth)(),
                $gte: (0, helpers_1.getStartOfPreviousMonth)(),
            },
        },
    });
    let campusTrendThisMonth = await strapi.entityService
        .findMany("api::campus-trend.campus-trend", {
        filters: {
            date: {
                $gte: (0, helpers_1.getStartOfMonth)(),
            },
        },
    })
        .then((data) => data.reduce((acc, item) => {
        return acc + item.total;
    }, 0));
    let campusTrendLastMonth = await strapi.entityService
        .findMany("api::campus-trend.campus-trend", {
        filters: {
            date: {
                $lte: (0, helpers_1.getStartOfMonth)(),
                $gte: (0, helpers_1.getStartOfPreviousMonth)(),
            },
        },
    })
        .then((data) => data.reduce((acc, item) => {
        return acc + item.total;
    }, 0));
    let networkServicesThisMonth = await attendamceSAggregationOrg(strapi, {
        $gte: (0, helpers_1.getStartOfMonth)(),
    });
    let networkServicesLastMonth = await attendamceSAggregationOrg(strapi, {
        $lte: (0, helpers_1.getStartOfMonth)(),
        $gte: (0, helpers_1.getStartOfPreviousMonth)(),
    });
    let monthsInfo = (0, helpers_1.getYearMonthsFromToday)();
    let yearItems = [];
    for (const month of monthsInfo) {
        let oneItem = await attendamceSAggregationOrg(strapi, {
            $gte: month.startDate,
            $lte: month.endDate,
        });
        let campusTrend = await strapi.entityService
            .findMany("api::campus-trend.campus-trend", {
            filters: {
                date: {
                    $gte: month.startDate,
                    $lte: month.endDate,
                },
            },
        })
            .then((data) => data.reduce((acc, item) => {
            return acc + item.total;
        }, 0));
        let discipleshipGroup = await strapi.entityService.count("api::discipleship-group.discipleship-group", {
            filters: {
                createdAt: {
                    $gte: month.startDate,
                    $lte: month.endDate,
                },
            },
        });
        yearItems.push({
            month: month.name,
            ...oneItem,
            campusTrend,
            discipleshipGroup,
        });
    }
    yearItems.reverse();
    let myfTrend = (0, network_1.getTrend)(networkServicesThisMonth.myf, networkServicesLastMonth.myf);
    let visitorsTrend = (0, network_1.getTrend)(networkServicesThisMonth.visitors, networkServicesLastMonth.visitors);
    let mavunoKidsTrend = (0, network_1.getTrend)(networkServicesThisMonth.mavunoKids, networkServicesLastMonth.mavunoKids);
    let salvationsTrend = (0, network_1.getTrend)(networkServicesThisMonth.salvations, networkServicesLastMonth.salvations);
    let dgTrend = (0, network_1.getTrend)(dgThisMonth, dgLastMonth);
    let trendForCampusTrend = (0, network_1.getTrend)(campusTrendThisMonth, campusTrendLastMonth);
    if (type == "graph") {
        return yearItems;
    }
    else {
        return {
            thisMonth: {
                ...networkServicesThisMonth,
                campusTrend: campusTrendThisMonth,
                discipleshipGroup: dgThisMonth,
            },
            lastMonth: {
                ...networkServicesLastMonth,
                campusTrend: campusTrendLastMonth,
                discipleshipGroup: dgLastMonth,
            },
            myfTrend,
            dgTrend,
            visitorsTrend,
            mavunoKidsTrend,
            salvationsTrend,
            trendForCampusTrend,
            // yearItems,
        };
    }
}
async function getNetworkSummary(strapi, id, type) {
    let network = await strapi.entityService.findOne("api::network.network", id);
    let dgThisMonth = await strapi.entityService.count("api::discipleship-group.discipleship-group", {
        filters: {
            network: {
                id: {
                    $eq: id,
                },
            },
            createdAt: {
                $gte: (0, helpers_1.getStartOfMonth)(),
            },
        },
    });
    let dgLastMonth = await strapi.entityService.count("api::discipleship-group.discipleship-group", {
        filters: {
            network: {
                id: {
                    $eq: id,
                },
            },
            createdAt: {
                $lte: (0, helpers_1.getStartOfMonth)(),
                $gte: (0, helpers_1.getStartOfPreviousMonth)(),
            },
        },
    });
    let campusTrendThisMonth = await strapi.entityService
        .findMany("api::campus-trend.campus-trend", {
        filters: {
            network: {
                id: {
                    $eq: id,
                },
            },
            date: {
                $gte: (0, helpers_1.getStartOfMonth)(),
            },
        },
    })
        .then((data) => data.reduce((acc, item) => {
        return acc + item.total;
    }, 0));
    let campusTrendLastMonth = await strapi.entityService
        .findMany("api::campus-trend.campus-trend", {
        filters: {
            network: {
                id: {
                    $eq: id,
                },
            },
            date: {
                $lte: (0, helpers_1.getStartOfMonth)(),
                $gte: (0, helpers_1.getStartOfPreviousMonth)(),
            },
        },
    })
        .then((data) => data.reduce((acc, item) => {
        return acc + item.total;
    }, 0));
    let networkServicesThisMonth = await attendamceSAggregationNetwork(network.id, strapi, {
        $gte: (0, helpers_1.getStartOfMonth)(),
    });
    let networkServicesLastMonth = await attendamceSAggregationNetwork(network.id, strapi, {
        $lte: (0, helpers_1.getStartOfMonth)(),
        $gte: (0, helpers_1.getStartOfPreviousMonth)(),
    });
    let monthsInfo = (0, helpers_1.getYearMonthsFromToday)();
    let yearItems = [];
    for (const month of monthsInfo) {
        let oneItem = await attendamceSAggregationNetwork(network.id, strapi, {
            $gte: month.startDate,
            $lte: month.endDate,
        });
        let campusTrend = await strapi.entityService
            .findMany("api::campus-trend.campus-trend", {
            filters: {
                network: {
                    id: {
                        $eq: id,
                    },
                },
                date: {
                    $gte: month.startDate,
                    $lte: month.endDate,
                },
            },
        })
            .then((data) => data.reduce((acc, item) => {
            return acc + item.total;
        }, 0));
        let dgLastMonth = await strapi.entityService.count("api::discipleship-group.discipleship-group", {
            filters: {
                network: {
                    id: {
                        $eq: id,
                    },
                },
                createdAt: {
                    $gte: month.startDate,
                    $lte: month.endDate,
                },
            },
        });
        yearItems.push({ month: month.name, ...oneItem, campusTrend, dgLastMonth });
    }
    yearItems.reverse();
    let myfTrend = (0, network_1.getTrend)(networkServicesThisMonth.myf, networkServicesLastMonth.myf);
    let visitorsTrend = (0, network_1.getTrend)(networkServicesThisMonth.visitors, networkServicesLastMonth.visitors);
    let mavunoKidsTrend = (0, network_1.getTrend)(networkServicesThisMonth.mavunoKids, networkServicesLastMonth.mavunoKids);
    let salvationsTrend = (0, network_1.getTrend)(networkServicesThisMonth.salvations, networkServicesLastMonth.salvations);
    let dgTrend = (0, network_1.getTrend)(dgThisMonth, dgLastMonth);
    let trendForCampusTrend = (0, network_1.getTrend)(campusTrendThisMonth, campusTrendLastMonth);
    if (type == "graph") {
        return yearItems;
    }
    else {
        return {
            thisMonth: {
                ...networkServicesThisMonth,
                campusTrend: campusTrendThisMonth,
                discipleshipGroup: dgThisMonth,
            },
            lastMonth: {
                ...networkServicesLastMonth,
                campusTrend: campusTrendLastMonth,
                discipleshipGroup: dgLastMonth,
            },
            myfTrend,
            dgTrend,
            visitorsTrend,
            mavunoKidsTrend,
            salvationsTrend,
            trendForCampusTrend,
            // yearItems,
        };
    }
}
async function getCampusSummary(strapi, id, type) {
    let campus = await strapi.entityService.findOne("api::campus.campus", id, {
        populate: {
            pastor: true,
        },
    });
    if (campus === null) {
        return {};
    }
    const zones = await strapi.entityService.findMany("api::zone.zone", {
        filters: {
            campus: {
                id: campus.id,
            },
        },
        populate: "*",
    });
    campus["zoneCount"] = zones.length;
    for (const zone of zones) {
        // @ts-ignore
        zone.coordinates.color =
            "#" + Math.floor(Math.random() * 16777215).toString(16);
        const groups = await strapi.entityService.findMany("api::discipleship-group.discipleship-group", {
            filters: {
                zone: {
                    id: zone.id,
                },
            },
            populate: "*",
        });
        delete zone.discipleship_groups;
        zone["discipleshipGroupsCount"] = groups.length;
        zone["memberCount"] = groups.reduce((acc, group) => {
            return acc + group.members.length;
        }, 0);
    }
    campus["totalMemberCount"] = await strapi.entityService.count("api::member.member", {
        filters: {
            campus: {
                id: campus.id,
            },
        },
    });
    let result = (0, campus_1.omitFieldsRecursively)({ campus, zones });
    return result;
}
async function dgListingLevel(strapi, zoneId) {
    const zone = await strapi.entityService.findOne("api::zone.zone", zoneId, {
        populate: "*",
    });
    const groups = await strapi.entityService
        .findMany("api::discipleship-group.discipleship-group", {
        filters: {
            zone: {
                id: zoneId,
            },
        },
        populate: ["members", "dgleader", "coordinates"],
    })
        .then((groups) => groups.map((group) => ({ ...group, memberCount: group.members.length })));
    groups.forEach((group) => {
        // @ts-ignore
        group["coordinates"].color =
            "#" + Math.floor(Math.random() * 16777215).toString(16);
    });
    zone.discipleship_groups = groups;
    zone["discipleshipGroupsCount"] = groups.length;
    zone["memberCount"] = groups.reduce((acc, group) => {
        return acc + group.members.length;
    }, 0);
    return (0, campus_1.omitFieldsRecursively)(zone);
}
async function attendamceSAggregationNetwork(networkId, strapi, dateFiter) {
    return await strapi.entityService
        .findMany("api::services-tracker-form.services-tracker-form", {
        filters: {
            network: {
                id: {
                    $eq: networkId,
                },
            },
            date: dateFiter,
        },
        populate: "*",
    })
        .then((it) => it.reduce((acc, it) => {
        acc.myf += it.firstService.myf + it.secondService.myf;
        acc.visitors +=
            it.firstService.visitorsInService +
                it.secondService.visitorsInService;
        acc.mavunoKids +=
            it.firstService.mavunoKids + it.secondService.mavunoKids;
        acc.salvations +=
            it.firstService.salvations + it.secondService.salvations;
        return acc;
    }, {
        myf: 0,
        visitors: 0,
        mavunoKids: 0,
        salvations: 0,
    }));
}
async function attendamceSAggregationOrg(strapi, dateFiter) {
    return await strapi.entityService
        .findMany("api::services-tracker-form.services-tracker-form", {
        filters: {
            date: dateFiter,
        },
        populate: "*",
    })
        .then((it) => it.reduce((acc, it) => {
        acc.myf += it.firstService.myf + it.secondService.myf;
        acc.visitors +=
            it.firstService.visitorsInService +
                it.secondService.visitorsInService;
        acc.mavunoKids +=
            it.firstService.mavunoKids + it.secondService.mavunoKids;
        acc.salvations +=
            it.firstService.salvations + it.secondService.salvations;
        return acc;
    }, {
        myf: 0,
        visitors: 0,
        mavunoKids: 0,
        salvations: 0,
    }));
}
