"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTopMetricFailures = void 0;
const drizzle_orm_1 = require("drizzle-orm");
const constants_1 = require("../../../constants");
const database_1 = require("../../../database");
const tables_1 = require("../../../database/tables");
const workspaceUtils_1 = require("./workspaceUtils");
const getTopMetricFailures = async (params) => {
    try {
        const db = (0, database_1.getDb)();
        const { projectIds, applicationId, start, end, type, limit = 5 } = params || {};
        if (!projectIds || projectIds.length === 0) {
            return {
                status: 0,
                message: 'Project IDs are required',
            };
        }
        if (!type || (type !== 'functional' && type !== 'security')) {
            return {
                status: 0,
                message: 'Type must be either "functional" or "security"',
            };
        }
        // Parse dates using shared utility
        const dateStart = (0, workspaceUtils_1.parseStartDate)(start, 7);
        const dateEnd = (0, workspaceUtils_1.parseEndDate)(end);
        // Build date filter conditions for test runs
        const dateConditions = [
            (0, drizzle_orm_1.gte)(tables_1.testRunsTable.createdAt, dateStart),
            (0, drizzle_orm_1.lte)(tables_1.testRunsTable.createdAt, dateEnd),
        ];
        // Build application filter condition
        const applicationConditions = [];
        if (applicationId) {
            applicationConditions.push((0, drizzle_orm_1.sql) `${tables_1.testRunsTable.applicationIds} @> ${JSON.stringify([applicationId])}::jsonb`);
        }
        // Build test run type condition
        const testRunType = type === 'functional' ? constants_1.TEST_RUN_TYPE.EVAL : constants_1.TEST_RUN_TYPE.SECURITY;
        // Fetch test runs in date range
        const testRunsWhereConditions = [
            (0, drizzle_orm_1.inArray)(tables_1.testRunsTable.projectId, projectIds),
            (0, drizzle_orm_1.eq)(tables_1.testRunsTable.status, constants_1.TEST_RUN_STATUS.COMPLETED),
            (0, drizzle_orm_1.eq)(tables_1.testRunsTable.type, testRunType),
            ...dateConditions,
            ...applicationConditions,
        ];
        const testRuns = await db
            .select({
            id: tables_1.testRunsTable.id,
        })
            .from(tables_1.testRunsTable)
            .where((0, drizzle_orm_1.and)(...testRunsWhereConditions));
        if (testRuns.length === 0) {
            return {
                status: 1,
                response: {
                    topFailures: [],
                },
            };
        }
        // Get eval IDs for all test runs
        const testRunIds = testRuns.map((tr) => tr.id);
        const testRunToEvals = await db
            .select({
            evalId: tables_1.testRunsToEvalsTable.evalId,
        })
            .from(tables_1.testRunsToEvalsTable)
            .where((0, drizzle_orm_1.inArray)(tables_1.testRunsToEvalsTable.testRunId, testRunIds));
        if (testRunToEvals.length === 0) {
            return {
                status: 1,
                response: {
                    topFailures: [],
                },
            };
        }
        // Get all eval results
        const allEvalIds = Array.from(new Set(testRunToEvals.map((rel) => rel.evalId)));
        const evalResults = await db
            .select({
            gradingResult: tables_1.evalResultsTable.gradingResult,
        })
            .from(tables_1.evalResultsTable)
            .where((0, drizzle_orm_1.inArray)(tables_1.evalResultsTable.evalId, allEvalIds));
        // Aggregate metric failures
        const metricStats = new Map();
        for (const result of evalResults) {
            if (result?.gradingResult?.componentResults) {
                for (const componentResult of result.gradingResult.componentResults) {
                    // Skip human assertions
                    const assertion = componentResult?.assertion;
                    if (assertion?.type === 'human') {
                        continue;
                    }
                    const metricName = assertion?.displayLabel ||
                        assertion?.type ||
                        'Unknown';
                    if (!metricStats.has(metricName)) {
                        metricStats.set(metricName, {
                            total: 0,
                            failed: 0,
                            metricName,
                        });
                    }
                    const stats = metricStats.get(metricName);
                    stats.total += 1;
                    if (!componentResult?.pass) {
                        stats.failed += 1;
                    }
                }
            }
        }
        // Convert to array and calculate failure rate
        const topFailures = Array.from(metricStats.values())
            .map((stats) => ({
            metricName: stats.metricName,
            total: stats.total,
            failed: stats.failed,
            failureRate: stats.total > 0 ? (stats.failed / stats.total) * 100 : 0,
        }))
            .filter((stats) => stats.failed > 0) // Only include metrics with failures
            .sort((a, b) => {
            // Sort by failure count descending, then by failure rate descending
            if (b.failed !== a.failed) {
                return b.failed - a.failed;
            }
            return b.failureRate - a.failureRate;
        })
            .slice(0, limit);
        return {
            status: 1,
            response: {
                topFailures,
            },
        };
    }
    catch (error) {
        console.error('Error fetching top metric failures:', error);
        return {
            status: 0,
            message: 'Error fetching top metric failures',
            error,
        };
    }
};
exports.getTopMetricFailures = getTopMetricFailures;
//# sourceMappingURL=getTopMetricFailures.js.map