"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.evalComponentRowId = evalComponentRowId;
exports.denormalizeEvalResult = denormalizeEvalResult;
const types_1 = require("../../../types");
const getPluginId_1 = require("./getPluginId");
const metricIdentity_1 = require("./metricIdentity");
const resolveTraceIds_1 = require("./resolveTraceIds");
const types_2 = require("./types");
function pick(row, camel, snake) {
    const c = row[camel];
    if (c !== undefined && c !== null) {
        return c;
    }
    const s = row[snake];
    if (s !== undefined && s !== null) {
        return s;
    }
    return undefined;
}
/** Deterministic row id from source keys (no random UUID). */
function evalComponentRowId(evalResultId, componentIndex) {
    return `${evalResultId}:${componentIndex}`;
}
function countGradingComponentResults(components) {
    let componentPassCount = 0;
    let componentFailCount = 0;
    for (const component of components) {
        if (component.pass) {
            componentPassCount += 1;
        }
        else {
            componentFailCount += 1;
        }
    }
    return { componentPassCount, componentFailCount };
}
function parseCreatedAt(row) {
    const raw = pick(row, 'createdAt', 'created_at');
    if (raw instanceof Date) {
        return raw;
    }
    if (typeof raw === 'string') {
        return new Date(raw);
    }
    return new Date();
}
function buildComponentRow(base, componentIndex, component, syntheticMetricKey) {
    const fields = component ? (0, metricIdentity_1.componentMetricFields)(component) : { assertionType: null, assertionDisplayLabel: null, metricKey: null };
    const metricKey = syntheticMetricKey ?? fields.metricKey;
    const assertionType = syntheticMetricKey ?? fields.assertionType;
    const assertionExtras = (0, metricIdentity_1.assertionRuntimeExtras)(component?.assertion);
    return {
        id: evalComponentRowId(base.evalResultId, componentIndex),
        ...base,
        componentIndex,
        assertionType,
        assertionDisplayLabel: syntheticMetricKey ? null : fields.assertionDisplayLabel,
        metricKey,
        componentPass: component?.pass ? 1 : 0,
        componentScore: component?.score ?? 0,
        componentReason: component?.reason ?? null,
        assertionExpected: assertionExtras?.expected === null || assertionExtras?.expected === undefined
            ? null
            : String(assertionExtras.expected),
        assertionActual: assertionExtras?.actual === null || assertionExtras?.actual === undefined
            ? null
            : String(assertionExtras.actual),
    };
}
/**
 * Pure denormalization: one analytics summary + zero or more component rows per eval result.
 */
function denormalizeEvalResult(row, denormVersion = types_2.DENORM_VERSION_BACKFILL) {
    const evalResultId = row.id;
    const createdAt = parseCreatedAt(row);
    const isRedteam = Number(pick(row, 'isRedteam', 'is_redteam') ?? 0);
    const failureReason = Number(pick(row, 'failureReason', 'failure_reason') ?? types_1.ResultFailureReason.NONE);
    const gradingResult = pick(row, 'gradingResult', 'grading_result') ?? null;
    const testCase = (pick(row, 'testCase', 'test_case') ?? {});
    const pluginId = isRedteam === 1 ? (0, getPluginId_1.getPluginIdFromEvalRow)(row) : null;
    const traceIds = (0, resolveTraceIds_1.resolveTraceIds)(row);
    const primaryTraceId = pick(row, 'traceId', 'trace_id') ?? traceIds[0] ?? null;
    const componentBase = {
        evalResultId,
        projectId: pick(row, 'projectId', 'project_id') ?? null,
        applicationId: pick(row, 'applicationId', 'application_id') ?? null,
        workspaceId: pick(row, 'workspaceId', 'workspace_id') ?? null,
        createdAt,
        traceId: primaryTraceId,
        sessionId: pick(row, 'sessionId', 'session_id') ?? null,
        traceIds,
        testRunId: pick(row, 'testRunId', 'test_run_id') ?? null,
        evalId: pick(row, 'evalId', 'eval_id') ?? null,
        isRedteam,
        failureReason,
        error: pick(row, 'error', 'error') ?? null,
        pluginId,
        denormVersion,
    };
    const components = [];
    const rawComponents = Array.isArray(gradingResult?.componentResults) ? gradingResult.componentResults : [];
    if (failureReason === types_1.ResultFailureReason.ERROR) {
        const syntheticKeys = (0, metricIdentity_1.syntheticMetricKeysFromTestCase)(testCase);
        if (syntheticKeys.length > 0) {
            syntheticKeys.forEach((key, idx) => {
                components.push(buildComponentRow(componentBase, idx, null, key));
            });
        }
        else {
            components.push(buildComponentRow(componentBase, 0, null, ''));
        }
    }
    else if (rawComponents.length > 0) {
        rawComponents.forEach((cr, idx) => {
            const built = buildComponentRow(componentBase, idx, cr, null);
            if (isRedteam === 0 && !built.metricKey) {
                return;
            }
            components.push(built);
        });
    }
    else if (gradingResult) {
        components.push(buildComponentRow(componentBase, 0, gradingResult, null));
    }
    const functionalComponents = isRedteam === 0 ? components : [];
    const metricKeys = [...new Set(functionalComponents.map((c) => c.metricKey).filter((k) => Boolean(k?.length)))];
    const failedMetricKeys = [
        ...new Set(functionalComponents.filter((c) => c.componentPass === 0 && c.metricKey).map((c) => c.metricKey)),
    ];
    let componentPassCount = 0;
    let componentFailCount = 0;
    if (rawComponents.length > 0) {
        ({ componentPassCount, componentFailCount } = countGradingComponentResults(rawComponents));
    }
    else {
        for (const c of components) {
            if (c.componentPass === 1) {
                componentPassCount += 1;
            }
            else {
                componentFailCount += 1;
            }
        }
    }
    const gradingPass = gradingResult?.pass ? 1 : 0;
    const analytics = {
        evalResultId,
        createdAt,
        projectId: componentBase.projectId,
        applicationId: componentBase.applicationId,
        workspaceId: componentBase.workspaceId,
        traceId: componentBase.traceId,
        sessionId: componentBase.sessionId,
        traceIds: componentBase.traceIds,
        isRedteam,
        testRunId: componentBase.testRunId,
        evalId: componentBase.evalId,
        testIdx: pick(row, 'testIdx', 'test_idx') ?? null,
        failureReason,
        error: componentBase.error,
        gradingPass,
        gradingScore: gradingResult?.score ?? 0,
        gradingReason: gradingResult?.reason ?? null,
        componentPassCount,
        componentFailCount,
        metricKeys: isRedteam === 0 ? metricKeys : [],
        failedMetricKeys: isRedteam === 0 ? failedMetricKeys : [],
        pluginId,
        pluginPass: isRedteam === 1 ? gradingPass : null,
        denormVersion,
    };
    return { analytics, components };
}
//# sourceMappingURL=denormalize.js.map