"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PulseEvaluationController = void 0;
const date_fns_1 = require("date-fns");
const lodash_1 = __importDefault(require("lodash"));
const logger_1 = __importDefault(require("../../../logger"));
const pulseEvaluationService_1 = require("../../services/pulseEvaluationService");
const pulseMonitoringService_1 = require("../../services/pulseMonitoringService");
const get_upgrade_meta_1 = require("../../../util/get-upgrade-meta");
const decimal_js_1 = __importDefault(require("decimal.js"));
const pulseService_1 = require("../../services/pulseService");
const callControlPlaneApi_1 = require("../../../util/callContolPlane/callControlPlaneApi");
const restriction_message_1 = require("../../constants/restriction.message");
const PulseEvaluationController = {
    async runEvaluation(req, res) {
        try {
            const { traceId } = req.params;
            const { projectId, orgId } = req.body;
            const upgradeData = await (0, get_upgrade_meta_1.getUpgradeMetaByOrgId)(orgId, {
                fetchMetricUsage: true,
            }, true);
            const { restrictionsData, wallet, isStarter, thresholds, notifications, usages, isEnterprise, } = upgradeData;
            const skipMap = new Map();
            const renewalNotificationMap = new Map();
            const usageNotificationMap = new Map();
            const exhaustedNotificationMap = new Map();
            if (!isEnterprise
                && restrictionsData?.metrics > 0
                && new decimal_js_1.default(usages?.metric ?? 0).gte(restrictionsData?.metrics ?? 0)
                && !exhaustedNotificationMap?.get(orgId)?.metric) {
                if (isStarter) {
                    if (notifications?.canSendMetricUsageExceeded) {
                        await (0, callControlPlaneApi_1.callControlPlane)(`/trusys-emails/limit-reached`, {
                            method: 'POST',
                            params: {
                                orgId: orgId,
                                type: 'Metric',
                                currentUsage: usages?.metric ?? 0,
                            },
                        }, '');
                    }
                    res.status(400).json({
                        success: false,
                        message: restriction_message_1.ERROR_RESTRICTION_MESSAGE.metrics.title,
                        showToast: true,
                        toastMetadata: {
                            text: restriction_message_1.ERROR_RESTRICTION_MESSAGE.metrics.message,
                            type: 'error',
                        },
                    });
                    return;
                }
                if (!isStarter
                    && notifications?.canSendMetricRenewal) {
                    if (renewalNotificationMap) {
                        renewalNotificationMap.set(orgId, {
                            spans: renewalNotificationMap?.get(orgId)?.spans ?? false,
                            metric: true,
                        });
                    }
                    await (0, callControlPlaneApi_1.callControlPlane)(`/trusys-emails/limit-renewal`, {
                        method: 'POST',
                        params: {
                            orgId: orgId,
                            type: 'Metric',
                            currentUsage: usages?.metric ?? 0,
                        },
                    }, '');
                }
            }
            if (!isEnterprise
                && new decimal_js_1.default(wallet?.credits ?? 0).lte(0)) {
                if (notifications?.canSendWalletUsageExceeded) {
                    await (0, callControlPlaneApi_1.callControlPlane)(`/trusys-emails/limit-reached`, {
                        method: 'POST',
                        params: {
                            orgId: orgId,
                            type: 'Wallet',
                            currentUsage: wallet?.credits ?? 0,
                        },
                    }, '');
                }
                res.status(400).json({
                    success: false,
                    message: restriction_message_1.ERROR_RESTRICTION_MESSAGE.lowCredits.title,
                    showToast: true,
                    toastMetadata: {
                        text: restriction_message_1.ERROR_RESTRICTION_MESSAGE.lowCredits.message,
                        type: 'error',
                    },
                });
                return;
            }
            else if (!isEnterprise
                && new decimal_js_1.default(wallet?.credits ?? 0).gt(0)
                && new decimal_js_1.default(wallet?.credits ?? 0).lte(thresholds?.walletNotificationThreshold ?? 0)
                && notifications?.canSendLowWalletBalance) {
                if (usageNotificationMap) {
                    usageNotificationMap.set(orgId, {
                        spans: usageNotificationMap?.get(orgId)?.spans ?? false,
                        metric: usageNotificationMap?.get(orgId)?.metric ?? false,
                        wallet: true,
                    });
                }
                await (0, callControlPlaneApi_1.callControlPlane)(`/trusys-emails/limit-reaching`, {
                    method: 'POST',
                    params: {
                        orgId: orgId,
                        type: 'Wallet',
                        currentUsage: wallet?.credits ?? 0,
                    },
                }, '');
            }
            logger_1.default.info(`Running evaluation for trace ${traceId}`);
            if (lodash_1.default.isEmpty(traceId)) {
                res.status(400).json({
                    success: false,
                    message: 'Trace ID is required',
                });
                return;
            }
            const spans = await pulseService_1.pulseService.getReportData({ traceId });
            if (!lodash_1.default.isArray(spans) || spans.length === 0) {
                res.status(404).json({
                    success: false,
                    message: 'Trace not found',
                });
                return;
            }
            let applicationId = '';
            for (const span of spans) {
                if (lodash_1.default.isEmpty(span.resourceAttributes?.['service.name']) === false) {
                    applicationId = span.resourceAttributes['service.name'];
                    break;
                }
            }
            if (lodash_1.default.isEmpty(applicationId)) {
                res.status(404).json({
                    success: false,
                    message: 'Application ID not found',
                });
                return;
            }
            const pulseMonitoringService = new pulseMonitoringService_1.PulseMonitoringService();
            const monitoringConfig = await pulseMonitoringService.getMonitoring({ applicationId });
            if (lodash_1.default.isEmpty(monitoringConfig?.metrics) && lodash_1.default.isEmpty(monitoringConfig?.pluginsByCategory)) {
                res.status(400).json({
                    success: false,
                    message: 'No metrics or plugins configured for this application',
                });
                return;
            }
            const evaluationService = new pulseEvaluationService_1.PulseEvaluationService();
            const evaluation = await evaluationService.runEvaluation({
                applicationId,
                traceId,
                spans,
                monitoringConfig,
                projectId,
                skipMap,
                orgRestrictions: restrictionsData,
                renewalNotificationMap,
                usageNotificationMap,
                exhaustedNotificationMap,
                workspaceId: orgId,
            });
            res.json({
                success: true,
                data: evaluation,
            });
        }
        catch (error) {
            logger_1.default.error(`Error in evaluation controller: ${error}`);
            res.status(500).json({
                success: false,
                message: error.message,
                error: error.message,
            });
        }
    },
    async getEvalResult(req, res) {
        try {
            const { traceId } = req.params;
            const { orgId } = req.query;
            // const limit = Number(req.query.limit) || 50;
            // const offset = Number(req.query.offset) || 0;
            // const filter = String(req.query.filter || 'all');
            // const searchText = req.query.search ? String(req.query.search) : '';
            // const metricFilter = req.query.metric ? String(req.query.metric) : '';
            const { upgradeMetadata, restrictionsData, isEnterprise, usages, isStarter, wallet, } = await (0, get_upgrade_meta_1.getUpgradeMetaByOrgId)(orgId);
            logger_1.default.info(`Getting evaluation result for trace ${traceId}`);
            if (lodash_1.default.isEmpty(traceId)) {
                res.status(400).json({
                    success: false,
                    message: 'Trace ID is required',
                });
                return;
            }
            const evaluationService = new pulseEvaluationService_1.PulseEvaluationService();
            const evaluation = await evaluationService.getEvaluation({
                traceId,
            });
            if (lodash_1.default.isEmpty(evaluation)) {
                res.status(404).json({
                    success: false,
                    message: 'Evaluation not found',
                });
                return;
            }
            if (!isEnterprise && new decimal_js_1.default(wallet?.credits ?? 0).lte(0)) {
                upgradeMetadata.upgradeRequired = false;
                upgradeMetadata.topUpRequired = true;
                upgradeMetadata.upgradeTitle = restriction_message_1.RESTRICTION_MESSAGE.lowCredits.title;
                upgradeMetadata.upgradeMessage = restriction_message_1.RESTRICTION_MESSAGE.lowCredits.message;
                upgradeMetadata.currentPlan = restrictionsData?.currentPlan ?? '';
                upgradeMetadata.currentPlanId = restrictionsData?.currentPlanId ?? '';
            }
            if (isStarter && restrictionsData?.metrics > 0 && new decimal_js_1.default(usages?.metric ?? 0).gte(restrictionsData?.metrics ?? 0)) {
                upgradeMetadata.upgradeRequired = true;
                upgradeMetadata.topUpRequired = false;
                upgradeMetadata.upgradeTitle = restriction_message_1.RESTRICTION_MESSAGE.metrics.title;
                upgradeMetadata.upgradeMessage = restriction_message_1.RESTRICTION_MESSAGE.metrics.message;
                upgradeMetadata.currentPlan = restrictionsData?.currentPlan ?? '';
                upgradeMetadata.currentPlanId = restrictionsData?.currentPlanId ?? '';
                // const count = await pulseService.getSpansUsage({
                //   timeLimit: pulseService.getTimeLimit(restrictionsData?.spans_timespan ?? 'lifetime'),
                //   orgId: orgId as string,
                // });
                // if (count !== 0 && new Decimal(count).gte(restrictionsData?.spans ?? 0)) {
                //   upgradeMetadata.upgradeRequired = true;
                //   upgradeMetadata.upgradeMessage = restrictionsData?.upgradeMessage ?? 'Please upgrade your plan to run more Trace Evaluations';
                //   upgradeMetadata.currentPlan = restrictionsData?.currentPlan ?? '';
                //   upgradeMetadata.currentPlanId = restrictionsData?.currentPlanId ?? '';
                // }
            }
            res.json({
                success: true,
                data: evaluation,
                upgradeMetadata,
            });
        }
        catch (error) {
            logger_1.default.error(`Error in getEvalResult controller: ${error}`);
            res.status(500).json({
                success: false,
                message: error.message,
                error: error.message,
            });
        }
    },
    async getAllEvalResultsForProject(req, res) {
        try {
            const { applicationId } = req.params;
            const { start: startDate, end: endDate } = req.query;
            if (lodash_1.default.isEmpty(applicationId)) {
                res.status(400).json({
                    success: false,
                    message: 'Application ID is required',
                });
                return;
            }
            const evaluationService = new pulseEvaluationService_1.PulseEvaluationService();
            const results = await evaluationService.getAllEvalResultsForProject(applicationId, startDate, endDate);
            res.json({
                success: true,
                data: results,
            });
        }
        catch (error) {
            logger_1.default.error(`Error in getAllEvalResultsForProject controller: ${error}`);
            res.status(500).json({
                success: false,
                message: error.message,
                error: error.message,
            });
        }
    },
    async getEvaluationSecurityOverviewForProject(req, res) {
        try {
            const { applicationId } = req.params;
            const { start: startDate, end: endDate } = req.query;
            if (lodash_1.default.isEmpty(applicationId)) {
                res.status(400).json({
                    success: false,
                    message: 'Application ID is required',
                });
                return;
            }
            const evaluationService = new pulseEvaluationService_1.PulseEvaluationService();
            const results = await evaluationService.getEvaluationSecurityOverviewForProject(applicationId, startDate, endDate);
            res.json({
                success: true,
                data: results,
            });
        }
        catch (error) {
            logger_1.default.error(`Error in getEvaluationSecurityOverviewForProject controller: ${error}`);
            res.status(500).json({
                success: false,
                message: error.message,
                error: error.message,
            });
        }
    },
    async getEvaluationTestRunsForProject(req, res) {
        try {
            const { applicationId } = req.params;
            const { start: startDate, end: endDate } = req.query;
            if (lodash_1.default.isEmpty(applicationId)) {
                res.status(400).json({
                    success: false,
                    message: 'Application ID is required',
                });
                return;
            }
            const evaluationService = new pulseEvaluationService_1.PulseEvaluationService();
            const testRuns = await evaluationService.getEvaluationTestRunsForProject(applicationId, startDate, endDate);
            res.json({
                success: true,
                data: testRuns,
            });
        }
        catch (error) {
            logger_1.default.error(`Error in getEvaluationTestRunsForProject controller: ${error}`);
            res.status(500).json({
                success: false,
                message: error.message,
                error: error.message,
            });
        }
    },
    async getEvaluationSecurityTestRunsForProject(req, res) {
        try {
            const { applicationId } = req.params;
            const { start: startDate, end: endDate } = req.query;
            if (lodash_1.default.isEmpty(applicationId)) {
                res.status(400).json({
                    success: false,
                    message: 'Application ID is required',
                });
                return;
            }
            const evaluationService = new pulseEvaluationService_1.PulseEvaluationService();
            const securityTestRuns = await evaluationService.getEvaluationSecurityTestRunsForProject(applicationId, startDate, endDate);
            res.json({
                success: true,
                data: securityTestRuns,
            });
        }
        catch (error) {
            logger_1.default.error(`Error in getEvaluationSecurityTestRunsForProject controller: ${error}`);
            res.status(500).json({
                success: false,
                message: error.message,
                error: error.message,
            });
        }
    },
    async getEvaluationSecurityVulnerabilitiesOverTimeForProject(req, res) {
        try {
            const { applicationId } = req.params;
            const { start, end, type } = req.query;
            if (lodash_1.default.isEmpty(applicationId)) {
                res.status(400).json({
                    success: false,
                    message: 'Application ID is required',
                });
                return;
            }
            if (lodash_1.default.isEmpty(start) || lodash_1.default.isEmpty(end) || lodash_1.default.isEmpty(type)) {
                res.status(400).json({
                    success: false,
                    message: 'start, end and type are required',
                });
                return;
            }
            const evaluationService = new pulseEvaluationService_1.PulseEvaluationService();
            const chartData = await evaluationService.getEvaluationSecurityVulnerabilitiesOverTimeForProject(applicationId, String(type), String(start), String(end));
            res.json({
                success: true,
                data: chartData,
            });
        }
        catch (error) {
            logger_1.default.error(`Error in getEvaluationSecurityVulnerabilitiesOverTimeForProject controller: ${error}`);
            res.status(500).json({
                success: false,
                message: error.message,
                error: error.message,
            });
        }
    },
    async getEvaluationSecurityCategoryWiseVolumeForProject(req, res) {
        try {
            const { applicationId } = req.params;
            const { start, end } = req.query;
            if (lodash_1.default.isEmpty(applicationId)) {
                res.status(400).json({
                    success: false,
                    message: 'Application ID is required',
                });
                return;
            }
            const evaluationService = new pulseEvaluationService_1.PulseEvaluationService();
            const chartData = await evaluationService.getEvaluationSecurityCategoryWiseVolumeForProject(applicationId, start, end);
            res.json({
                success: true,
                data: chartData,
            });
        }
        catch (error) {
            logger_1.default.error(`Error in getEvaluationSecurityCategoryWiseVolumeForProject controller: ${error}`);
            res.status(500).json({
                success: false,
                message: error.message,
                error: error.message,
            });
        }
    },
    async getEvaluationSecurityTestSuitesTableForProject(req, res) {
        try {
            const { applicationId } = req.params;
            const { start, end } = req.query;
            if (lodash_1.default.isEmpty(applicationId)) {
                res.status(400).json({
                    success: false,
                    message: 'Application ID is required',
                });
                return;
            }
            const evaluationService = new pulseEvaluationService_1.PulseEvaluationService();
            const data = await evaluationService.getEvaluationSecurityTestSuitesTableForProject(applicationId, start, end);
            res.json({
                success: true,
                data,
            });
        }
        catch (error) {
            logger_1.default.error(`Error in getEvaluationSecurityTestSuitesTableForProject controller: ${error}`);
            res.status(500).json({
                success: false,
                message: error.message,
                error: error.message,
            });
        }
    },
    async getEvaluationSecurityTestSuitePluginSidebarForProject(req, res) {
        try {
            const { applicationId } = req.params;
            const { start, end, pluginId } = req.query;
            if (lodash_1.default.isEmpty(applicationId)) {
                res.status(400).json({
                    success: false,
                    message: 'Application ID is required',
                });
                return;
            }
            if (pluginId == null || String(pluginId).trim() === '') {
                res.status(400).json({
                    success: false,
                    message: 'pluginId is required',
                });
                return;
            }
            const evaluationService = new pulseEvaluationService_1.PulseEvaluationService();
            const data = await evaluationService.getEvaluationSecurityTestSuitePluginSidebarForProject(applicationId, String(pluginId), start, end);
            res.json({
                success: true,
                data,
            });
        }
        catch (error) {
            logger_1.default.error(`Error in getEvaluationSecurityTestSuitePluginSidebarForProject controller: ${error}`);
            res.status(500).json({
                success: false,
                message: error.message,
                error: error.message,
            });
        }
    },
    /** Security board chart: metric card – total security probes (runs) count */
    async getSecurityProbes(req, res) {
        try {
            const { applicationId, start, end } = req.query;
            if (lodash_1.default.isEmpty(applicationId)) {
                res.status(400).json({ success: false, message: 'Application ID is required' });
                return;
            }
            const evaluationService = new pulseEvaluationService_1.PulseEvaluationService();
            const results = await evaluationService.getAllEvalResultsForProject(applicationId, start, end);
            const value = (results?.securityTestRuns ?? []).length;
            res.json({ success: true, data: value });
        }
        catch (error) {
            logger_1.default.error(`Error in getSecurityProbes: ${error}`);
            res.status(500).json({
                success: false,
                message: error.message,
                error: error.message,
            });
        }
    },
    /** Security board chart: metric card – vulnerabilities (failures) count */
    async getVulnerabilitiesDetected(req, res) {
        try {
            const { applicationId, start, end } = req.query;
            if (lodash_1.default.isEmpty(applicationId)) {
                res.status(400).json({ success: false, message: 'Application ID is required' });
                return;
            }
            const evaluationService = new pulseEvaluationService_1.PulseEvaluationService();
            const results = await evaluationService.getAllEvalResultsForProject(applicationId, start, end);
            const stats = results?.securityTestStats;
            const failures = typeof stats === 'object' && stats !== null && 'failures' in stats
                ? stats.failures
                : 0;
            const total = typeof stats === 'object' && stats !== null && 'total' in stats
                ? stats.total
                : 0;
            res.json({ success: true, data: { failures, total } });
        }
        catch (error) {
            logger_1.default.error(`Error in getVulnerabilitiesDetected: ${error}`);
            res.status(500).json({
                success: false,
                message: error.message,
                error: error.message,
            });
        }
    },
    /** Security board chart: bar chart – vulnerabilities over time */
    async getVulnerabilitiesOverTime(req, res) {
        try {
            const { applicationId, start, end, type } = req.query;
            if (lodash_1.default.isEmpty(applicationId) || lodash_1.default.isEmpty(start) || lodash_1.default.isEmpty(end)) {
                res.status(400).json({
                    success: false,
                    message: 'Application ID, start, and end are required',
                });
                return;
            }
            const evaluationService = new pulseEvaluationService_1.PulseEvaluationService();
            const results = await evaluationService.getAllEvalResultsForProject(applicationId, start, end);
            const securityTestRuns = results?.securityTestRuns ?? [];
            const useWeekly = type === '3M' || type === '6M';
            const startDate = (0, date_fns_1.parseISO)(start);
            const endDate = (0, date_fns_1.parseISO)(end);
            let barData;
            if (useWeekly) {
                const weekCounts = {};
                securityTestRuns.forEach((run) => {
                    const componentResults = run?.grading_result?.componentResults ?? [];
                    const createdAt = run?.created_at;
                    if (!createdAt) {
                        return;
                    }
                    const weekStartDate = (0, date_fns_1.startOfWeek)((0, date_fns_1.parseISO)(createdAt), { weekStartsOn: 1 });
                    const weekEndDate = (0, date_fns_1.endOfWeek)((0, date_fns_1.parseISO)(createdAt), { weekStartsOn: 1 });
                    const weekKey = (0, date_fns_1.format)(weekStartDate, 'yyyy-MM-dd');
                    if (!weekCounts[weekKey]) {
                        weekCounts[weekKey] = { count: 0, weekStart: weekStartDate, weekEnd: weekEndDate };
                    }
                    componentResults.forEach((item) => {
                        if (item.pass === false) {
                            weekCounts[weekKey].count += 1;
                        }
                    });
                });
                const weekKeys = [];
                let current = (0, date_fns_1.startOfWeek)(startDate, { weekStartsOn: 1 });
                const last = (0, date_fns_1.endOfWeek)(endDate, { weekStartsOn: 1 });
                while (current <= last) {
                    weekKeys.push((0, date_fns_1.format)(current, 'yyyy-MM-dd'));
                    current = new Date(current.getTime() + 7 * 24 * 60 * 60 * 1000);
                }
                barData = weekKeys.map((weekKey) => {
                    const week = weekCounts[weekKey];
                    return {
                        x: weekKey,
                        y: week ? week.count : 0,
                        weekStart: week ? week.weekStart : (0, date_fns_1.parseISO)(weekKey),
                        weekEnd: week ? week.weekEnd : (0, date_fns_1.endOfWeek)((0, date_fns_1.parseISO)(weekKey), { weekStartsOn: 1 }),
                    };
                });
            }
            else {
                const days = (0, date_fns_1.eachDayOfInterval)({ start: startDate, end: endDate });
                const dayCounts = {};
                securityTestRuns.forEach((run) => {
                    const componentResults = run?.grading_result?.componentResults ?? [];
                    const createdAt = run?.created_at;
                    if (!createdAt) {
                        return;
                    }
                    const day = (0, date_fns_1.format)((0, date_fns_1.parseISO)(createdAt), 'yyyy-MM-dd');
                    componentResults.forEach((item) => {
                        if (item.pass === false) {
                            dayCounts[day] = (dayCounts[day] || 0) + 1;
                        }
                    });
                });
                barData = days.map((date) => ({
                    x: (0, date_fns_1.format)(date, 'yyyy-MM-dd'),
                    y: dayCounts[(0, date_fns_1.format)(date, 'yyyy-MM-dd')] || 0,
                    date,
                }));
            }
            res.json({ success: true, data: barData });
        }
        catch (error) {
            logger_1.default.error(`Error in getVulnerabilitiesOverTime: ${error}`);
            res.status(500).json({
                success: false,
                message: error.message,
                error: error.message,
            });
        }
    },
    /** Security board chart: polar/radar – category-wise volume */
    async getCategoryWiseVolumeAnalysis(req, res) {
        try {
            const { applicationId, start, end } = req.query;
            if (lodash_1.default.isEmpty(applicationId)) {
                res.status(400).json({ success: false, message: 'Application ID is required' });
                return;
            }
            const evaluationService = new pulseEvaluationService_1.PulseEvaluationService();
            const data = await evaluationService.getEvaluationSecurityCategoryWiseVolumeForProject(applicationId, start, end);
            res.json({ success: true, data });
        }
        catch (error) {
            logger_1.default.error(`Error in getCategoryWiseVolumeAnalysis: ${error}`);
            res.status(500).json({
                success: false,
                message: error.message,
                error: error.message,
            });
        }
    },
    /** Security board: trend of security evaluation runs over time (line chart) */
    async getSecurityEvaluationsTrend(req, res) {
        try {
            const { applicationId, start, end } = req.query;
            if (lodash_1.default.isEmpty(applicationId)) {
                res.status(400).json({ success: false, message: 'Application ID is required' });
                return;
            }
            const evaluationService = new pulseEvaluationService_1.PulseEvaluationService();
            const results = await evaluationService.getAllEvalResultsForProject(applicationId, start, end);
            const securityTestRuns = results?.securityTestRuns ?? [];
            const startDate = (0, date_fns_1.parseISO)(start);
            const endDate = (0, date_fns_1.parseISO)(end);
            const days = (0, date_fns_1.eachDayOfInterval)({ start: startDate, end: endDate });
            const countByDay = {};
            days.forEach((d) => {
                countByDay[(0, date_fns_1.format)(d, 'yyyy-MM-dd')] = 0;
            });
            securityTestRuns.forEach((run) => {
                const createdAt = run?.created_at;
                if (!createdAt) {
                    return;
                }
                const day = (0, date_fns_1.format)((0, date_fns_1.parseISO)(createdAt), 'yyyy-MM-dd');
                if (countByDay[day] !== undefined) {
                    countByDay[day] += 1;
                }
            });
            const trendData = days.map((d) => ({
                timestamp: (0, date_fns_1.format)(d, 'yyyy-MM-dd'),
                count: countByDay[(0, date_fns_1.format)(d, 'yyyy-MM-dd')] ?? 0,
            }));
            res.json({ success: true, data: trendData });
        }
        catch (error) {
            logger_1.default.error(`Error in getSecurityEvaluationsTrend: ${error}`);
            res.status(500).json({
                success: false,
                message: error.message,
                error: error.message,
            });
        }
    },
    /** Security board: recent security evaluation runs (table) */
    async getRecentSecurityEvaluations(req, res) {
        try {
            const { applicationId, start, end, limit } = req.query;
            if (lodash_1.default.isEmpty(applicationId)) {
                res.status(400).json({ success: false, message: 'Application ID is required' });
                return;
            }
            const evaluationService = new pulseEvaluationService_1.PulseEvaluationService();
            const results = await evaluationService.getAllEvalResultsForProject(applicationId, start, end);
            const securityTestRuns = (results?.securityTestRuns ?? [])
                .sort((a, b) => {
                const t1 = a?.created_at ? new Date(a.created_at).getTime() : 0;
                const t2 = b?.created_at ? new Date(b.created_at).getTime() : 0;
                return t2 - t1;
            })
                .slice(0, Math.min(Number(limit) || 20, 100));
            const data = securityTestRuns.map((run) => ({
                traceId: run?.trace_id ?? run?.traceId,
                evalId: run?.eval_id ?? run?.evalId,
                createdAt: run?.created_at ?? run?.createdAt,
                success: run?.grading_result?.pass ?? run?.success,
                status: run?.error && run?.failure_reason ? 'error' : run?.grading_result?.pass ? 'pass' : 'fail',
            }));
            res.json({ success: true, data });
        }
        catch (error) {
            logger_1.default.error(`Error in getRecentSecurityEvaluations: ${error}`);
            res.status(500).json({
                success: false,
                message: error.message,
                error: error.message,
            });
        }
    },
    /** Security board: total probes, passed, failed (for KPI cards) */
    async getSecurityProbesStats(req, res) {
        try {
            const { applicationId, start, end } = req.query;
            if (lodash_1.default.isEmpty(applicationId)) {
                res.status(400).json({ success: false, message: 'Application ID is required' });
                return;
            }
            const evaluationService = new pulseEvaluationService_1.PulseEvaluationService();
            const results = await evaluationService.getAllEvalResultsForProject(applicationId, start, end);
            const securityTestRuns = results?.securityTestRuns ?? [];
            let totalProbes = 0;
            let probesPassed = 0;
            let probesFailed = 0;
            securityTestRuns.forEach((run) => {
                const componentResults = run?.grading_result?.componentResults ?? [];
                componentResults.forEach((item) => {
                    totalProbes += 1;
                    if (item?.pass === true) {
                        probesPassed += 1;
                    }
                    else {
                        probesFailed += 1;
                    }
                });
            });
            res.json({
                success: true,
                data: { totalProbes, probesPassed, probesFailed },
            });
        }
        catch (error) {
            logger_1.default.error(`Error in getSecurityProbesStats: ${error}`);
            res.status(500).json({
                success: false,
                message: error.message,
                error: error.message,
            });
        }
    },
    /** Security board: probe results over time (stacked bar – pass vs fail per day) */
    async getProbeResultsOverTime(req, res) {
        try {
            const { applicationId, start, end } = req.query;
            if (lodash_1.default.isEmpty(applicationId) || lodash_1.default.isEmpty(start) || lodash_1.default.isEmpty(end)) {
                res.status(400).json({
                    success: false,
                    message: 'Application ID, start, and end are required',
                });
                return;
            }
            const evaluationService = new pulseEvaluationService_1.PulseEvaluationService();
            const results = await evaluationService.getAllEvalResultsForProject(applicationId, start, end);
            const securityTestRuns = results?.securityTestRuns ?? [];
            const startDate = (0, date_fns_1.parseISO)(start);
            const endDate = (0, date_fns_1.parseISO)(end);
            const days = (0, date_fns_1.eachDayOfInterval)({ start: startDate, end: endDate });
            const passByDay = {};
            const failByDay = {};
            days.forEach((d) => {
                const key = (0, date_fns_1.format)(d, 'yyyy-MM-dd');
                passByDay[key] = 0;
                failByDay[key] = 0;
            });
            securityTestRuns.forEach((run) => {
                const componentResults = run?.grading_result?.componentResults ?? [];
                const createdAt = run?.created_at;
                if (!createdAt) {
                    return;
                }
                const day = (0, date_fns_1.format)((0, date_fns_1.parseISO)(createdAt), 'yyyy-MM-dd');
                if (passByDay[day] === undefined) {
                    return;
                }
                componentResults.forEach((item) => {
                    if (item?.pass === true) {
                        passByDay[day] += 1;
                    }
                    else {
                        failByDay[day] += 1;
                    }
                });
            });
            const chartData = days.map((date) => {
                const x = (0, date_fns_1.format)(date, 'yyyy-MM-dd');
                return [
                    [x, passByDay[x] ?? 0, 'Success'],
                    [x, failByDay[x] ?? 0, 'Fail'],
                ];
            });
            const flat = chartData.flat();
            res.json({ success: true, data: flat });
        }
        catch (error) {
            logger_1.default.error(`Error in getProbeResultsOverTime: ${error}`);
            res.status(500).json({
                success: false,
                message: error.message,
                error: error.message,
            });
        }
    },
    /** Security board: top security control failures (by plugin/assertion) */
    async getTopSecurityControlFailures(req, res) {
        try {
            const { applicationId, start, end } = req.query;
            if (lodash_1.default.isEmpty(applicationId)) {
                res.status(400).json({ success: false, message: 'Application ID is required' });
                return;
            }
            const evaluationService = new pulseEvaluationService_1.PulseEvaluationService();
            const results = await evaluationService.getAllEvalResultsForProject(applicationId, start, end);
            const securityTestRuns = results?.securityTestRuns ?? [];
            const failureByControl = {};
            securityTestRuns.forEach((run) => {
                const componentResults = run?.grading_result?.componentResults ?? [];
                componentResults.forEach((item) => {
                    const label = item?.metadata?.pluginId ??
                        item?.assertion?.displayLabel ??
                        item?.assertion?.type ??
                        'Unknown';
                    if (!failureByControl[label]) {
                        failureByControl[label] = { failures: 0, total: 0 };
                    }
                    failureByControl[label].total += 1;
                    if (item?.pass !== true) {
                        failureByControl[label].failures += 1;
                    }
                });
            });
            const data = Object.entries(failureByControl)
                .filter(([, v]) => v.failures > 0)
                .map(([control, v]) => ({
                control,
                failureCount: v.failures,
                total: v.total,
                passCount: v.total - v.failures,
            }))
                .sort((a, b) => b.failureCount - a.failureCount)
                .slice(0, 50);
            res.json({ success: true, data });
        }
        catch (error) {
            logger_1.default.error(`Error in getTopSecurityControlFailures: ${error}`);
            res.status(500).json({
                success: false,
                message: error.message,
                error: error.message,
            });
        }
    },
    async getEvaluationAudio(req, res) {
        try {
            const { traceId } = req.params;
            const { applicationId } = req.query;
            if (lodash_1.default.isEmpty(traceId) || lodash_1.default.isEmpty(applicationId)) {
                res.status(400).json({
                    success: false,
                    message: 'Trace ID and application ID are required',
                });
                return;
            }
            const evaluationService = new pulseEvaluationService_1.PulseEvaluationService();
            const evaluation = await evaluationService.getEvaluationAudio({
                traceId,
                applicationId: applicationId,
            });
            if (!evaluation?.success || lodash_1.default.isEmpty(evaluation)) {
                res.status(404).json({
                    success: false,
                    message: evaluation?.message || 'Evaluation not found',
                });
                return;
            }
            const audioUrl = evaluation.data;
            res.json({
                success: true,
                data: audioUrl,
            });
        }
        catch (error) {
            logger_1.default.error(`Error in getEvaluationAudio controller: ${error}`);
            res.status(500).json({
                success: false,
                message: error.message,
                error: error.message,
            });
        }
    },
};
exports.PulseEvaluationController = PulseEvaluationController;
//# sourceMappingURL=pulse-evaluation.js.map