"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertResultsToTable = convertResultsToTable;
const types_1 = require("../types");
const invariant_1 = __importDefault(require("../util/invariant"));
function convertResultsToTable(eval_, filter) {
    (0, invariant_1.default)(eval_.prompts, `Prompts are required in this version of the results file, this needs to be results file version >= 4, version: ${eval_.version}`);
    // first we need to get our prompts, we can get that from any of the results in each column
    const results = eval_.results;
    const varsForHeader = new Set();
    const varValuesForRow = new Map();
    const rowMap = {};
    for (const result of results.results) {
        // vars
        for (const varName of Object.keys(result.vars || {})) {
            varsForHeader.add(varName);
        }
        const row = rowMap[`${result.testIdx}${result.evalId}${result.promptId}`] || {
            description: result.description || undefined,
            outputs: [],
            vars: result.vars
                ? Object.values(varsForHeader)
                    .map((varName) => {
                    const varValue = result.vars?.[varName] || '';
                    if (typeof varValue === 'string') {
                        return varValue;
                    }
                    return JSON.stringify(varValue);
                })
                    .flat()
                : [],
            test: result.testCase,
            evalId: result.evalId,
        };
        if (result.vars && result.metadata?.redteamFinalPrompt) {
            const varKeys = Object.keys(result.vars);
            if (varKeys.length === 1 && varKeys[0] !== 'harmCategory') {
                result.vars[varKeys[0]] = result.metadata.redteamFinalPrompt;
            }
            else if (varKeys.length > 1) {
                // NOTE: This is a hack. We should use config.redteam.injectVar to determine which key to update but we don't have access to the config here
                const targetKeys = ['prompt', 'query', 'question'];
                const keyToUpdate = targetKeys.find((key) => result.vars[key]);
                if (keyToUpdate) {
                    result.vars[keyToUpdate] = result.metadata.redteamFinalPrompt;
                }
            }
        }
        varValuesForRow.set(`${result.testIdx}${result.evalId}`, result.vars);
        rowMap[`${result.testIdx}${result.evalId}${result.promptId}`] = row;
        // format text
        let resultText;
        const failReasons = (result.gradingResult?.componentResults || [])
            .filter((result) => (result ? !result.pass : false))
            .map((result) => result.reason)
            .join(' --- ');
        // Use anonymized_output if available, otherwise fall back to original output
        const outputToDisplay = result.response?.anonymized_output === undefined
            ? result.response?.output
            : result.response?.output;
        const outputTextDisplay = (typeof outputToDisplay === 'object'
            ? JSON.stringify(outputToDisplay)
            : outputToDisplay || result.error || '');
        if (result.testCase.assert) {
            if (result.success) {
                resultText = `${outputTextDisplay || result.error || ''}`;
            }
            else {
                resultText = `${result.error || failReasons}\n---\n${outputTextDisplay}`;
            }
        }
        else if (result.error) {
            resultText = `${result.error}`;
        }
        else {
            resultText = outputTextDisplay;
        }
        let outputIdx = result.promptIdx;
        if (result.promptIdx > 0 && !row.outputs[result.promptIdx - 1]) {
            outputIdx = 0;
        }
        if (row.outputs[outputIdx]) {
            const providerLabel = row?.outputs[outputIdx]?.provider;
            if (providerLabel !== result.provider.label) {
                outputIdx++;
            }
        }
        row.outputs[outputIdx] = {
            id: result.id || `${result.testIdx}-${result.promptIdx}`,
            ...result,
            text: resultText || '',
            prompt: result.prompt.raw,
            provider: result.provider?.label || result.provider?.id || 'unknown provider',
            providerId: result.provider?.id || 'unknown provider',
            pass: Boolean(result.success),
            failureReason: result.failureReason,
            cost: result.cost || 0,
            audio: result.response?.audio
                ? {
                    id: result.response.audio.id,
                    expiresAt: result.response.audio.expiresAt,
                    data: result.response.audio.data,
                    transcript: result.response.audio.transcript,
                    format: result.response.audio.format,
                }
                : undefined,
        };
        (0, invariant_1.default)(result.promptId, 'Prompt ID is required');
        row.testIdx = result.testIdx;
    }
    let rows = Object.values(rowMap).sort((a, b) => a.testIdx - b.testIdx);
    const sortedVars = [...varsForHeader].sort();
    for (const row of rows) {
        row.vars = sortedVars.map((varName) => varValuesForRow.get(`${row.testIdx}${row.evalId}`)?.[varName] || '');
    }
    // Apply filtering if filter is provided
    if (filter && filter !== 'all') {
        rows = rows.filter((row) => {
            let outputsPassFilter = true;
            if (filter === 'failures') {
                outputsPassFilter = row.outputs.some((output) => !output.pass && output.failureReason !== types_1.ResultFailureReason.ERROR);
            }
            else if (filter === 'errors') {
                outputsPassFilter = row.outputs.some((output) => output.failureReason === types_1.ResultFailureReason.ERROR);
            }
            else if (filter === 'different') {
                outputsPassFilter = !row.outputs.every((output) => output.text === row.outputs[0].text);
            }
            else if (filter === 'highlights') {
                outputsPassFilter = row.outputs.some((output) => output.gradingResult?.comment?.startsWith('!highlight'));
            }
            else if (filter === 'reviewed') {
                outputsPassFilter = row.outputs.some((output) => output.gradingResult?.reviewedBy);
            }
            else if (filter === 'unreviewed') {
                outputsPassFilter = row.outputs.some((output) => !output.gradingResult?.reviewedBy);
            }
            return outputsPassFilter;
        });
    }
    return {
        head: {
            prompts: eval_.prompts,
            vars: [...varsForHeader].sort(),
        },
        body: rows,
    };
}
//# sourceMappingURL=convertEvalResultsToTable.js.map