"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getWorkspaceDetails = 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");
// Helper function to get date range data
const getDateRangeData = (startDate, endDate) => {
    const days = [];
    const start = new Date(startDate);
    start.setHours(0, 0, 0, 0);
    const end = new Date(endDate);
    end.setHours(23, 59, 59, 999);
    const currentDate = new Date(start);
    while (currentDate <= end) {
        days.push({
            date: currentDate.toISOString().split('T')[0],
            count: 0,
        });
        currentDate.setDate(currentDate.getDate() + 1);
    }
    return days;
};
// Helper function to calculate stats for multiple test runs in batch
const calculateTestRunStatsBatch = async (testRunIds) => {
    const statsMap = new Map();
    // Initialize stats for all test runs
    testRunIds.forEach((id) => {
        statsMap.set(id, { total: 0, successes: 0, failures: 0, errors: 0 });
    });
    if (testRunIds.length === 0) {
        return statsMap;
    }
    try {
        const db = (0, database_1.getDb)();
        // Fetch all test run to eval relations in one query
        const testRunEvals = await db
            .select()
            .from(tables_1.testRunsToEvalsTable)
            .where((0, drizzle_orm_1.inArray)(tables_1.testRunsToEvalsTable.testRunId, testRunIds));
        if (testRunEvals.length === 0) {
            return statsMap;
        }
        // Group eval IDs by test run ID
        const evalIdsByTestRun = new Map();
        for (const rel of testRunEvals) {
            if (!evalIdsByTestRun.has(rel.testRunId)) {
                evalIdsByTestRun.set(rel.testRunId, []);
            }
            evalIdsByTestRun.get(rel.testRunId).push(rel.evalId);
        }
        // Get all unique eval IDs
        const allEvalIds = Array.from(new Set(testRunEvals.map((rel) => rel.evalId)));
        if (allEvalIds.length > 0) {
            // Fetch all eval results in one query
            const evalResults = await db
                .select({
                evalId: tables_1.evalResultsTable.evalId,
                gradingResult: tables_1.evalResultsTable.gradingResult,
            })
                .from(tables_1.evalResultsTable)
                .where((0, drizzle_orm_1.inArray)(tables_1.evalResultsTable.evalId, allEvalIds));
            // Create a map of eval ID to test run IDs (an eval can belong to multiple test runs)
            const evalToTestRuns = new Map();
            for (const rel of testRunEvals) {
                if (!evalToTestRuns.has(rel.evalId)) {
                    evalToTestRuns.set(rel.evalId, []);
                }
                evalToTestRuns.get(rel.evalId).push(rel.testRunId);
            }
            // Process results and aggregate stats per test run
            for (const result of evalResults) {
                const testRunIdsForEval = evalToTestRuns.get(result.evalId) || [];
                if (result?.gradingResult?.componentResults) {
                    // Count each component result for all test runs this eval belongs to
                    result.gradingResult.componentResults.forEach((componentResult) => {
                        for (const testRunId of testRunIdsForEval) {
                            const stats = statsMap.get(testRunId);
                            if (stats) {
                                stats.total += 1;
                                if (componentResult?.pass) {
                                    stats.successes += 1;
                                }
                                else {
                                    stats.failures += 1;
                                }
                            }
                        }
                    });
                }
            }
        }
    }
    catch (error) {
        console.error(`Error calculating stats for test runs:`, error);
    }
    return statsMap;
};
const getWorkspaceDetails = async (params) => {
    try {
        const db = (0, database_1.getDb)();
        const { projectIds, applicationId, start, end } = params || {};
        if (!projectIds || projectIds.length === 0) {
            return {
                status: 0,
                message: 'Project IDs are required',
            };
        }
        // Build date filter conditions
        const dateConditions = [];
        if (start) {
            dateConditions.push((0, drizzle_orm_1.gte)(tables_1.testRunsTable.createdAt, new Date(start)));
        }
        if (end) {
            dateConditions.push((0, drizzle_orm_1.lte)(tables_1.testRunsTable.createdAt, new Date(end)));
        }
        // Build application filter condition
        const applicationConditions = [];
        let selectedApp = null;
        if (applicationId) {
            // Filter test runs where the applicationId is in the applicationIds array
            applicationConditions.push((0, drizzle_orm_1.sql) `${tables_1.testRunsTable.applicationIds} @> ${JSON.stringify([applicationId])}::jsonb`);
            selectedApp = await db
                .select({ name: tables_1.applicationsTable.name })
                .from(tables_1.applicationsTable)
                .where((0, drizzle_orm_1.eq)(tables_1.applicationsTable.id, applicationId))
                .limit(1);
        }
        // Build security config target filter condition
        const securityConfigConditions = [
            (0, drizzle_orm_1.inArray)(tables_1.securityConfigTable.projectId, projectIds),
            (0, drizzle_orm_1.eq)(tables_1.securityConfigTable.is_archived, false),
        ];
        if (applicationId) {
            // Workspace expects security config target.label to match selected application name.
            const selectedApplicationName = selectedApp?.[0]?.name;
            if (selectedApplicationName) {
                securityConfigConditions.push((0, drizzle_orm_1.eq)((0, drizzle_orm_1.sql) `${tables_1.securityConfigTable.config} -> 'target' ->> 'label'`, selectedApplicationName));
            }
        }
        // Eval test runs (latest + total count in one query)
        const evalWhereConditions = [
            (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, constants_1.TEST_RUN_TYPE.EVAL),
            ...dateConditions,
            ...applicationConditions,
        ];
        // Security test runs (latest + total count in one query)
        const securityWhereConditions = [
            (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, constants_1.TEST_RUN_TYPE.SECURITY),
            ...dateConditions,
            ...applicationConditions,
        ];
        const [evalRows, securityRows] = await Promise.all([
            db
                .select({
                id: tables_1.testRunsTable.id,
                type: tables_1.testRunsTable.type,
                createdAt: tables_1.testRunsTable.createdAt,
                updatedAt: tables_1.testRunsTable.updatedAt,
                status: tables_1.testRunsTable.status,
                projectId: tables_1.testRunsTable.projectId,
                applicationIds: tables_1.testRunsTable.applicationIds,
                libraryId: tables_1.testRunsTable.libraryId,
                totalTestCase: tables_1.testRunsTable.totalTestCase,
                libraryName: tables_1.promptsLibraryTable.name,
                totalCount: (0, drizzle_orm_1.sql) `count(*) over()`,
            })
                .from(tables_1.testRunsTable)
                .leftJoin(tables_1.promptsLibraryTable, (0, drizzle_orm_1.eq)(tables_1.testRunsTable.libraryId, tables_1.promptsLibraryTable.id))
                .where((0, drizzle_orm_1.and)(...evalWhereConditions))
                .orderBy((0, drizzle_orm_1.sql) `${tables_1.testRunsTable.createdAt} DESC`)
                .limit(2),
            db
                .select({
                id: tables_1.testRunsTable.id,
                type: tables_1.testRunsTable.type,
                createdAt: tables_1.testRunsTable.createdAt,
                updatedAt: tables_1.testRunsTable.updatedAt,
                status: tables_1.testRunsTable.status,
                projectId: tables_1.testRunsTable.projectId,
                applicationIds: tables_1.testRunsTable.applicationIds,
                libraryId: tables_1.testRunsTable.libraryId,
                totalTestCase: tables_1.testRunsTable.totalTestCase,
                securityConfigName: tables_1.securityConfigTable.name,
                totalCount: (0, drizzle_orm_1.sql) `count(*) over()`,
            })
                .from(tables_1.testRunsTable)
                .leftJoin(tables_1.testRunsToSecurityConfigsTable, (0, drizzle_orm_1.eq)(tables_1.testRunsTable.id, tables_1.testRunsToSecurityConfigsTable.testRunId))
                .leftJoin(tables_1.securityConfigTable, (0, drizzle_orm_1.eq)(tables_1.testRunsToSecurityConfigsTable.securityConfigId, tables_1.securityConfigTable.id))
                .where((0, drizzle_orm_1.and)(...securityWhereConditions))
                .orderBy((0, drizzle_orm_1.sql) `${tables_1.testRunsTable.createdAt} DESC`)
                .limit(2),
        ]);
        const functionEvalCount = Number(evalRows?.[0]?.totalCount ?? 0);
        const securityCount = Number(securityRows?.[0]?.totalCount ?? 0);
        const functionalEvaltestRuns = evalRows.map(({ totalCount: _totalCount, ...row }) => ({
            ...row,
            applicationName: selectedApp?.[0]?.name,
        }));
        const securityEvaltestRuns = securityRows.map(({ totalCount: _totalCount, ...row }) => row);
        // Fetch applications in parallel with stats calculation
        const [functionalStatsMap, applications, promptLibraries, securityConfigs] = await Promise.all([
            // Calculate stats for all functional test runs in batch
            calculateTestRunStatsBatch(functionalEvaltestRuns.map((tr) => tr.id)),
            // Fetch applications
            db
                .select()
                .from(tables_1.applicationsTable)
                .where(applicationId === undefined
                ? undefined
                : (0, drizzle_orm_1.eq)(tables_1.applicationsTable.id, applicationId))
                .limit(2)
                .orderBy((0, drizzle_orm_1.sql) `${tables_1.applicationsTable.createdAt} DESC`),
            // Fetch prompt libraries (latest)
            db
                .select({
                id: tables_1.promptsLibraryTable.id,
                name: tables_1.promptsLibraryTable.name,
                createdAt: tables_1.promptsLibraryTable.createdAt,
                updatedAt: tables_1.promptsLibraryTable.updatedAt,
            })
                .from(tables_1.promptsLibraryTable)
                .where((0, drizzle_orm_1.and)((0, drizzle_orm_1.inArray)(tables_1.promptsLibraryTable.projectId, projectIds), (0, drizzle_orm_1.eq)(tables_1.promptsLibraryTable.is_archived, false)))
                .limit(2)
                .orderBy((0, drizzle_orm_1.sql) `${tables_1.promptsLibraryTable.createdAt} DESC`),
            // Fetch security configs (latest)
            db
                .select({
                id: tables_1.securityConfigTable.id,
                name: tables_1.securityConfigTable.name,
                createdAt: tables_1.securityConfigTable.createdAt,
                updatedAt: tables_1.securityConfigTable.updatedAt,
            })
                .from(tables_1.securityConfigTable)
                .where((0, drizzle_orm_1.and)(...securityConfigConditions))
                .limit(2)
                .orderBy((0, drizzle_orm_1.sql) `${tables_1.securityConfigTable.createdAt} DESC`),
        ]);
        // Add stats to functional eval test runs
        for (const testRun of functionalEvaltestRuns) {
            testRun.totalStats = functionalStatsMap.get(testRun.id) || { total: 0, successes: 0, failures: 0, errors: 0 };
        }
        // Calculate stats for all security test runs in batch
        const securityStatsMap = await calculateTestRunStatsBatch(securityEvaltestRuns.map((tr) => tr.id));
        // Add stats to security eval test runs
        for (const testRun of securityEvaltestRuns) {
            testRun.totalStats = securityStatsMap.get(testRun.id) || { total: 0, successes: 0, failures: 0, errors: 0 };
            testRun.applicationName = applications.find((app) => app.id === testRun.applicationIds[0])?.name;
        }
        // Calculate date range for chart data
        // Use provided date range or default to last 7 days
        const dateStart = start ? new Date(start) : (() => {
            const d = new Date();
            d.setDate(d.getDate() - 7);
            d.setHours(0, 0, 0, 0);
            return d;
        })();
        const dateEnd = end ? new Date(end) : new Date();
        // Build chart data date filter conditions
        const chartDateConditions = [
            (0, drizzle_orm_1.gte)(tables_1.testRunsTable.createdAt, dateStart),
            (0, drizzle_orm_1.lte)(tables_1.testRunsTable.createdAt, dateEnd),
        ];
        // Chart data: aggregate in SQL (avoid fetching every row)
        const functionalLast7DaysWhereConditions = [
            (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, constants_1.TEST_RUN_TYPE.EVAL),
            ...chartDateConditions,
            ...applicationConditions,
        ];
        const functionalLast7DaysAgg = await db
            .select({
            date: (0, drizzle_orm_1.sql) `DATE(${tables_1.testRunsTable.createdAt})`,
            count: (0, drizzle_orm_1.sql) `count(*)`,
        })
            .from(tables_1.testRunsTable)
            .where((0, drizzle_orm_1.and)(...functionalLast7DaysWhereConditions))
            .groupBy((0, drizzle_orm_1.sql) `DATE(${tables_1.testRunsTable.createdAt})`);
        const securityLast7DaysWhereConditions = [
            (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, constants_1.TEST_RUN_TYPE.SECURITY),
            ...chartDateConditions,
            ...applicationConditions,
        ];
        const securityLast7DaysAgg = await db
            .select({
            date: (0, drizzle_orm_1.sql) `DATE(${tables_1.testRunsTable.createdAt})`,
            count: (0, drizzle_orm_1.sql) `count(*)`,
        })
            .from(tables_1.testRunsTable)
            .where((0, drizzle_orm_1.and)(...securityLast7DaysWhereConditions))
            .groupBy((0, drizzle_orm_1.sql) `DATE(${tables_1.testRunsTable.createdAt})`);
        // Aggregate by date
        const functionalEvalLast7DaysData = getDateRangeData(dateStart, dateEnd);
        for (const row of functionalLast7DaysAgg) {
            const date = String(row.date);
            const dayData = functionalEvalLast7DaysData.find((d) => d.date === date);
            if (dayData) {
                dayData.count = Number(row.count ?? 0);
            }
        }
        const securityEvalLast7DaysData = getDateRangeData(dateStart, dateEnd);
        for (const row of securityLast7DaysAgg) {
            const date = String(row.date);
            const dayData = securityEvalLast7DaysData.find((d) => d.date === date);
            if (dayData) {
                dayData.count = Number(row.count ?? 0);
            }
        }
        // Fetch monitored applications
        const monitoredApplications = await db
            .select({
            id: tables_1.applicationsTable.id,
            name: tables_1.applicationsTable.name,
            createdAt: tables_1.applicationsTable.createdAt,
        })
            .from(tables_1.pulseMonitoringTable)
            .innerJoin(tables_1.applicationsTable, (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringTable.applicationId, tables_1.applicationsTable.id))
            .where((0, drizzle_orm_1.inArray)(tables_1.applicationsTable.projectId, projectIds))
            .limit(2)
            .orderBy((0, drizzle_orm_1.sql) `${tables_1.applicationsTable.createdAt} DESC`);
        // Whether at least one non-archived application exists for the project(s)
        const appPresentResult = await db
            .select({ id: tables_1.applicationsTable.id })
            .from(tables_1.applicationsTable)
            .where((0, drizzle_orm_1.and)((0, drizzle_orm_1.inArray)(tables_1.applicationsTable.projectId, projectIds), (0, drizzle_orm_1.eq)(tables_1.applicationsTable.is_archived, false)))
            .limit(1);
        const isApplicationPresent = (appPresentResult?.length ?? 0) > 0;
        // For the selected application, expose whether monitoring / guardrails are enabled.
        let isMonitoringEnabled = false;
        let isGuardrailsEnabled = false;
        if (applicationId) {
            const [monitoringRow, guardrailsRow] = await Promise.all([
                db
                    .select({ id: tables_1.pulseMonitoringTable.id })
                    .from(tables_1.pulseMonitoringTable)
                    .where((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringTable.applicationId, applicationId))
                    .limit(1),
                db
                    .select({ enable: tables_1.applicationGuardrailsTable.enable_guard_rails })
                    .from(tables_1.applicationGuardrailsTable)
                    .where((0, drizzle_orm_1.eq)(tables_1.applicationGuardrailsTable.applicationId, applicationId))
                    .limit(1),
            ]);
            isMonitoringEnabled = (monitoringRow?.length ?? 0) > 0;
            isGuardrailsEnabled = Boolean(guardrailsRow?.[0]?.enable);
        }
        return {
            status: 1,
            response: {
                functionalEvaltestRuns,
                securityEvaltestRuns,
                functionEvalCount,
                securityCount,
                functionalEvalLast7DaysData,
                securityEvalLast7DaysData,
                monitoredApplications,
                promptLibraries,
                securityConfigs,
                isApplicationPresent,
                isMonitoringEnabled,
                isGuardrailsEnabled,
            },
        };
    }
    catch (error) {
        console.error('Error fetching workspace details:', error);
        return {
            status: 0,
            message: 'Error fetching workspace details',
            error,
        };
    }
};
exports.getWorkspaceDetails = getWorkspaceDetails;
//# sourceMappingURL=getWorkspaceDetails.js.map