"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getGuardrailsData = void 0;
const date_fns_1 = require("date-fns");
const drizzle_orm_1 = require("drizzle-orm");
const database_1 = require("../../../database");
const tables_1 = require("../../../database/tables");
const clickhouseService_1 = require("../../services/clickhouseService");
const workspaceUtils_1 = require("./workspaceUtils");
// Helper function to get date range data for guardrails
const getDateRangeData = (startDate, endDate) => {
    const days = [];
    const start = new Date(startDate);
    start.setUTCHours(0, 0, 0, 0);
    const end = new Date(endDate);
    end.setUTCHours(23, 59, 59, 999);
    const currentDate = new Date(start);
    while (currentDate <= end) {
        const year = currentDate.getUTCFullYear();
        const month = String(currentDate.getUTCMonth() + 1).padStart(2, '0');
        const day = String(currentDate.getUTCDate()).padStart(2, '0');
        days.push({
            date: `${year}-${month}-${day}`,
            count: 0,
        });
        currentDate.setUTCDate(currentDate.getUTCDate() + 1);
    }
    return days;
};
// Helper function to get daily data for validation failures over time
const getDailyData = (startDate, endDate) => {
    const days = [];
    const start = new Date(startDate);
    start.setUTCHours(0, 0, 0, 0);
    const end = new Date(endDate);
    end.setUTCHours(23, 59, 59, 999);
    const currentDate = new Date(start);
    while (currentDate <= end) {
        const year = currentDate.getUTCFullYear();
        const month = String(currentDate.getUTCMonth() + 1).padStart(2, '0');
        const day = String(currentDate.getUTCDate()).padStart(2, '0');
        days.push({
            month: `${month}/${day}/${String(year).slice(-2)}`,
            input: 0,
            output: 0,
        });
        currentDate.setUTCDate(currentDate.getUTCDate() + 1);
    }
    return days;
};
// Helper function to get monthly data for validation failures over time
const getMonthlyData = (startDate, endDate) => {
    const months = [];
    const start = new Date(startDate);
    start.setUTCDate(1);
    start.setUTCHours(0, 0, 0, 0);
    const end = new Date(endDate);
    end.setUTCDate(1);
    end.setUTCHours(0, 0, 0, 0);
    const currentDate = new Date(start);
    while (currentDate <= end) {
        const year = currentDate.getUTCFullYear();
        const month = String(currentDate.getUTCMonth() + 1).padStart(2, '0');
        months.push({
            month: `${month}/${String(year).slice(-2)}`,
            input: 0,
            output: 0,
        });
        currentDate.setUTCMonth(currentDate.getUTCMonth() + 1);
    }
    return months;
};
const getGuardrailsData = 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',
            };
        }
        // Parse dates using shared utility
        const dateStart = (0, workspaceUtils_1.parseStartDate)(start, 7);
        const dateEnd = (0, workspaceUtils_1.parseEndDate)(end);
        // Calculate date range in days to determine grouping
        const daysDiff = Math.ceil((dateEnd.getTime() - dateStart.getTime()) / (1000 * 60 * 60 * 24));
        const useDailyGrouping = daysDiff <= 90; // Use daily grouping for ranges <= 90 days
        // Initialize default values
        let totalValidationRequests = 0;
        let inputValidationFailures = 0;
        let outputValidationFailures = 0;
        const guardrailsLast7DaysData = getDateRangeData(dateStart, dateEnd);
        const validationFailuresOverTime = useDailyGrouping
            ? getDailyData(dateStart, dateEnd)
            : getMonthlyData(dateStart, dateEnd);
        try {
            // Get applications with guardrails enabled
            const guardrailsAppsWhereConditions = [
                (0, drizzle_orm_1.inArray)(tables_1.applicationsTable.projectId, projectIds),
            ];
            if (applicationId) {
                guardrailsAppsWhereConditions.push((0, drizzle_orm_1.eq)(tables_1.applicationsTable.id, applicationId));
            }
            const guardrailsApps = await db
                .select({
                applicationId: tables_1.applicationGuardrailsTable.applicationId,
            })
                .from(tables_1.applicationGuardrailsTable)
                .innerJoin(tables_1.applicationsTable, (0, drizzle_orm_1.eq)(tables_1.applicationGuardrailsTable.applicationId, tables_1.applicationsTable.id))
                .where((0, drizzle_orm_1.and)(...guardrailsAppsWhereConditions, (0, drizzle_orm_1.eq)(tables_1.applicationGuardrailsTable.enable_guard_rails, true)));
            const guardrailsAppIds = guardrailsApps.map((app) => app.applicationId);
            if (guardrailsAppIds.length > 0) {
                // Format dates for ClickHouse query
                const dateStartFormatted = (0, date_fns_1.format)(dateStart, 'yyyy-MM-dd HH:mm:ss');
                const dateEndFormatted = (0, date_fns_1.format)(dateEnd, 'yyyy-MM-dd HH:mm:ss');
                const appIdsString = guardrailsAppIds.map((id) => `'${id}'`).join(',');
                const projectIdsString = projectIds.map((id) => `'${id}'`).join(',');
                const baseConditions = [
                    `application_id IN (${appIdsString})`,
                    `project_id IN (${projectIdsString})`,
                    `created_at >= '${dateStartFormatted}'`,
                    `created_at <= '${dateEndFormatted}'`,
                ];
                // Reduce ClickHouse round-trips:
                // - one query for request counts over time (no ARRAY JOIN)
                // - one query for failed component counts over time by stage (ARRAY JOIN)
                const requestsOverTimeQuery = useDailyGrouping
                    ? `
            SELECT 
              toDate(created_at) as bucket,
              COUNT(*) as count
            FROM guardrail_results
            WHERE ${baseConditions.join(' AND ')}
            GROUP BY bucket
            ORDER BY bucket
          `
                    : `
            SELECT 
              toStartOfMonth(created_at) as bucket,
              COUNT(*) as count
            FROM guardrail_results
            WHERE ${baseConditions.join(' AND ')}
            GROUP BY bucket
            ORDER BY bucket
          `;
                const requestsOverTimeResult = await clickhouseService_1.clickHouseService.query(requestsOverTimeQuery);
                // Total requests across range
                totalValidationRequests = requestsOverTimeResult.reduce((acc, row) => acc + Number(row?.count || 0), 0);
                // Map ClickHouse results to our data structure
                requestsOverTimeResult.forEach((row) => {
                    try {
                        const dateObj = new Date(row.bucket);
                        if (!Number.isNaN(dateObj.getTime())) {
                            const year = dateObj.getUTCFullYear();
                            const month = String(dateObj.getUTCMonth() + 1).padStart(2, '0');
                            const day = String(dateObj.getUTCDate()).padStart(2, '0');
                            const date = `${year}-${month}-${day}`;
                            const dayData = guardrailsLast7DaysData.find((d) => d.date === date);
                            if (dayData) {
                                dayData.count = Number(row.count || 0);
                            }
                        }
                    }
                    catch (error) {
                        console.warn(`Error parsing date from ClickHouse result: ${row.bucket}`, error);
                    }
                });
                // Validation failures over time (daily or monthly based on date range)
                const failuresOverTimeQuery = useDailyGrouping
                    ? `
            SELECT 
              toDate(created_at) as bucket,
              guardrail_stage,
              COUNT(*) as count
            FROM guardrail_results
            ARRAY JOIN JSONExtractArrayRaw(component_results) AS component
            WHERE ${baseConditions.join(' AND ')}
              AND JSONExtractBool(component, 'pass') = false
            GROUP BY bucket, guardrail_stage
            ORDER BY bucket
          `
                    : `
            SELECT 
              toStartOfMonth(created_at) as bucket,
              guardrail_stage,
              COUNT(*) as count
            FROM guardrail_results
            ARRAY JOIN JSONExtractArrayRaw(component_results) AS component
            WHERE ${baseConditions.join(' AND ')}
              AND JSONExtractBool(component, 'pass') = false
            GROUP BY bucket, guardrail_stage
            ORDER BY bucket
          `;
                const failuresOverTimeResult = await clickhouseService_1.clickHouseService.query(failuresOverTimeQuery);
                // Map ClickHouse results to data structure
                failuresOverTimeResult.forEach((row) => {
                    try {
                        if (useDailyGrouping) {
                            const dateObj = new Date(row.bucket);
                            if (!Number.isNaN(dateObj.getTime())) {
                                const year = dateObj.getUTCFullYear();
                                const month = String(dateObj.getUTCMonth() + 1).padStart(2, '0');
                                const day = String(dateObj.getUTCDate()).padStart(2, '0');
                                const dateKey = `${month}/${day}/${String(year).slice(-2)}`;
                                const dayData = validationFailuresOverTime.find((d) => d.month === dateKey);
                                if (dayData) {
                                    if (row.guardrail_stage === 'input') {
                                        const c = Number(row.count || 0);
                                        dayData.input = c;
                                        inputValidationFailures += c;
                                    }
                                    else if (row.guardrail_stage === 'output') {
                                        const c = Number(row.count || 0);
                                        dayData.output = c;
                                        outputValidationFailures += c;
                                    }
                                }
                            }
                        }
                        else {
                            const monthObj = new Date(row.bucket);
                            if (!Number.isNaN(monthObj.getTime())) {
                                const year = monthObj.getUTCFullYear();
                                const month = String(monthObj.getUTCMonth() + 1).padStart(2, '0');
                                const monthKey = `${month}/${String(year).slice(-2)}`;
                                const monthData = validationFailuresOverTime.find((m) => m.month === monthKey);
                                if (monthData) {
                                    if (row.guardrail_stage === 'input') {
                                        const c = Number(row.count || 0);
                                        monthData.input = c;
                                        inputValidationFailures += c;
                                    }
                                    else if (row.guardrail_stage === 'output') {
                                        const c = Number(row.count || 0);
                                        monthData.output = c;
                                        outputValidationFailures += c;
                                    }
                                }
                            }
                        }
                    }
                    catch (error) {
                        console.warn(`Error parsing date from ClickHouse result: ${row.bucket}`, error);
                    }
                });
            }
        }
        catch (error) {
            console.error('Error fetching guardrails data from ClickHouse:', error);
            // Continue with empty data if ClickHouse query fails
        }
        return {
            status: 1,
            response: {
                totalValidationRequests,
                inputValidationFailures,
                outputValidationFailures,
                validationFailuresOverTime,
                guardrailsLast7DaysData,
            },
        };
    }
    catch (error) {
        console.error('Error fetching guardrails data:', error);
        return {
            status: 0,
            message: 'Error fetching guardrails data',
            error,
        };
    }
};
exports.getGuardrailsData = getGuardrailsData;
//# sourceMappingURL=getGuardrailsData.js.map