"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.compareTestRuns = void 0;
const drizzle_orm_1 = require("drizzle-orm");
const lodash_1 = __importDefault(require("lodash"));
const database_1 = require("../../../database");
const tables_1 = require("../../../database/tables");
const logger_1 = __importDefault(require("../../../logger"));
const get_result_details_1 = require("./get-result-details");
const compareTestRuns = async (req, res) => {
    try {
        const { testRunIds } = req.query;
        const { page = 1, limit = 10 } = req.query;
        if (!testRunIds || typeof testRunIds !== 'string') {
            res.status(400).json({
                success: false,
                message: 'testRunIds parameter is required',
            });
            return;
        }
        const testRunIdsArray = testRunIds.split(',').filter((id) => id.trim());
        if (testRunIdsArray.length < 2) {
            res.status(400).json({
                success: false,
                message: 'At least 2 test run IDs are required for comparison',
            });
            return;
        }
        const pageNum = Number.parseInt(page, 10);
        const limitNum = Number.parseInt(limit, 10);
        const offset = (pageNum - 1) * limitNum;
        const db = await (0, database_1.getDb)();
        const comparisonData = [];
        // Fetch data for each test run
        for (const testRunId of testRunIdsArray) {
            const testRun = await db
                .select({
                id: tables_1.testRunsTable.id,
                createdAt: tables_1.testRunsTable.createdAt,
                status: tables_1.testRunsTable.status,
                applicationIds: tables_1.testRunsTable.applicationIds,
                libraryId: tables_1.testRunsTable.libraryId,
            })
                .from(tables_1.testRunsTable)
                .where((0, drizzle_orm_1.eq)(tables_1.testRunsTable.id, testRunId))
                .limit(1);
            if (!testRun.length) {
                res.status(404).json({
                    success: false,
                    message: `Test run ${testRunId} not found`,
                });
                return;
            }
            const fetchParams = {
                db,
                resultId: testRunId,
                testRun,
                parsedLimit: 100,
                parsedPage: 1,
                offset: 0,
                filter: 'all',
            };
            const testRunData = await (0, get_result_details_1.fetchTestRunTable)(fetchParams);
            if (testRunData) {
                comparisonData.push({
                    testRunId,
                    createdAt: testRun[0].createdAt,
                    data: testRunData,
                });
            }
        }
        // Combine all data and apply pagination
        if (comparisonData.length > 0) {
            const allCombinedData = comparisonData[0]?.data?.resultTable?.body?.map((row, index) => {
                const parentPromptId = row?.test?.parentPromptId;
                const datasetRecordId = row?.test?.datasetRecordId;
                const vars = row?.test?.vars;
                const matchingRows = comparisonData
                    .slice(1)
                    .map((comparisonTableData) => {
                    const compRow = comparisonTableData?.data?.resultTable?.body?.find((compRow) => {
                        const comparedParentPromptId = compRow?.test?.parentPromptId;
                        const comparedDatasetRecordId = compRow?.test?.datasetRecordId;
                        const comparedVars = compRow?.test?.vars;
                        let comparison = false;
                        if (comparedParentPromptId === parentPromptId) {
                            if (lodash_1.default.isEmpty(datasetRecordId) === false &&
                                lodash_1.default.isEmpty(comparedDatasetRecordId) === false) {
                                comparison = datasetRecordId === comparedDatasetRecordId;
                            }
                            else {
                                // Check for vars equality: keys and values must be the same
                                if (lodash_1.default.isPlainObject(vars) && lodash_1.default.isPlainObject(comparedVars)) {
                                    const varsKeys = Object.keys(vars);
                                    const comparedVarsKeys = Object.keys(comparedVars);
                                    if (varsKeys.length === comparedVarsKeys.length &&
                                        varsKeys.every((key) => Object.prototype.hasOwnProperty.call(comparedVars, key) &&
                                            lodash_1.default.isEqual(vars[key], comparedVars[key]))) {
                                        comparison = true;
                                    }
                                    else {
                                        comparison = false;
                                    }
                                }
                                else {
                                    comparison = lodash_1.default.isEqual(vars, comparedVars);
                                }
                            }
                        }
                        return comparison;
                    });
                    return compRow ? compRow : {};
                })
                    .filter((r) => r !== undefined);
                return {
                    ...row,
                    outputs: [...row.outputs, ...(matchingRows.flatMap((r) => r?.outputs) || [])],
                };
            });
            const totalCount = allCombinedData.length;
            const paginatedData = allCombinedData.slice(offset, offset + limitNum);
            const combinedHeadColumns = comparisonData
                ?.map((data) => ({ ...data?.data?.resultTable?.head, testRunId: data?.testRunId }))
                .flatMap((head) => head?.columns?.map((column) => ({ ...column, testRunId: head.testRunId })));
            const combinedHead = {
                ...comparisonData[0]?.data?.resultTable?.head,
                columns: combinedHeadColumns,
            };
            const combinedTableData = {
                resultTable: {
                    head: combinedHead,
                    body: paginatedData,
                },
                pagination: {
                    total: totalCount,
                    page: pageNum,
                    limit: limitNum,
                    totalPages: Math.ceil(totalCount / limitNum),
                },
                reviewCounts: comparisonData.reduce((acc, testRun) => ({
                    total: acc.total + (testRun.data.reviewCounts?.total || 0),
                    reviewed: acc.reviewed + (testRun.data.reviewCounts?.reviewed || 0),
                }), { total: 0, reviewed: 0 }),
            };
            res.json({
                success: true,
                data: [
                    {
                        combinedTableData,
                        testRunIds: testRunIdsArray,
                    },
                ],
            });
        }
        else {
            res.json({
                success: true,
                data: [],
            });
        }
    }
    catch (error) {
        logger_1.default.error(`Failed to compare test runs: ${error.message}`);
        res.status(500).json({
            success: false,
            message: error.message || 'Failed to compare test runs',
        });
    }
};
exports.compareTestRuns = compareTestRuns;
//# sourceMappingURL=compare-test-runs.js.map