"use strict";
/**
 * Copyright: (c) Myia SAS 2026.
 * This file and its contents are licensed under the AGPLv3 License.
 * Please see the LICENSE file at the root of this repository
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.FailingStatementFinder = void 0;
// Locates the statement responsible for a test failure inside one
// `heal-traces.ndjson`. Used by `HealTracerReporter.onTestEnd` to
// surface a compact `FailingStatement` + `StatementError` on each
// attempt of the `execution.json` manifest.
//
// "Failing statement" = the deepest node in any root `statement`
// record's children tree whose `status === 'threw'`. Going deepest
// rather than first-seen surfaces the actual leaf call that threw
// (e.g. `page.locator(...).click()`) instead of the enclosing user
// step that propagated the error up.
//
// Returns null when the file is missing/torn, no statement threw,
// or the statement that threw has no error attached (defensive — the
// schema requires `error` on `status === 'threw'` but we tolerate
// older traces).
const fs = __importStar(require("fs"));
class FailingStatementFinder {
    find(ndjsonPath) {
        let body;
        try {
            body = fs.readFileSync(ndjsonPath, 'utf8');
        }
        catch {
            return null;
        }
        let deepest = null;
        for (const line of body.split('\n')) {
            const trimmed = line.trim();
            if (trimmed.length === 0)
                continue;
            let parsed;
            try {
                parsed = JSON.parse(trimmed);
            }
            catch {
                // Torn-write tolerance: skip unparseable lines. Mirrors the
                // discipline of `NdjsonTailInspector`.
                continue;
            }
            if (parsed?.kind !== 'statement' || !parsed.statement)
                continue;
            const found = findDeepestThrew(parsed.statement, 0);
            if (found && (!deepest || found.depth > deepest.depth)) {
                deepest = found;
            }
        }
        if (!deepest || !deepest.stmt.error)
            return null;
        return {
            statement: project(deepest.stmt),
            error: deepest.stmt.error,
        };
    }
}
exports.FailingStatementFinder = FailingStatementFinder;
function findDeepestThrew(stmt, depth) {
    let best = stmt.status === 'threw' ? { stmt, depth } : null;
    for (const child of stmt.children) {
        const found = findDeepestThrew(child, depth + 1);
        if (found && (!best || found.depth > best.depth)) {
            best = found;
        }
    }
    return best;
}
function project(stmt) {
    return {
        index: stmt.index,
        file: stmt.file,
        line: stmt.line,
        endLine: stmt.endLine,
        source: stmt.source,
        scope: stmt.scope,
        step: stmt.step,
        stepPath: stmt.stepPath,
    };
}
