import { StateStack } from "../state/stateStack.js";
import { GlobalStore } from "../state/globalStore.js";
import { CheckpointStore } from "../state/checkpointStore.js";
import { PendingPromiseStore } from "../state/pendingPromiseStore.js";
/**
 * Creates a mock RuntimeContext for unit tests.
 * Includes all methods that runtime code calls on the context.
 */
export function makeMockCtx(opts = {}) {
    const stateStack = new StateStack();
    stateStack.nodesTraversed = ["start", "process"];
    const state = stateStack.getNewState();
    state.args = { input: "hello" };
    state.locals = { x: 42 };
    state.step = 3;
    const globals = GlobalStore.withTokenStats();
    globals.set("mod1", "count", 10);
    return {
        stateStack,
        globals,
        checkpoints: new CheckpointStore(),
        pendingPromises: new PendingPromiseStore(),
        debuggerState: opts.debuggerState ?? null,
        handlers: [],
        callbacks: {},
        _skipNextCheckpoint: false,
        _toolCallDepth: 0,
        _handlerChainDepth: 0,
        runId: null,
        traceConfig: {},
        pushHandler(fn) { this.handlers.push(fn); },
        popHandler() { this.handlers.pop(); },
        isCancelled() { return false; },
        enterToolCall() { this._toolCallDepth++; },
        exitToolCall() { this._toolCallDepth--; },
        interruptResponses: {},
        setInterruptResponses(responses) {
            this.interruptResponses = responses;
        },
        getInterruptResponse(id) {
            return this.interruptResponses[id]?.response;
        },
        threads: {
            create: () => "tid-1",
            createSubthread: () => "tid-sub-1",
            pushActive: () => { },
            popActive: () => { },
            activeId: () => undefined,
            get: () => ({ messages: [], parentId: null }),
            resumeExisting: () => { },
            openSession: (_name) => ({ id: "tid-1", existed: false }),
        },
        // Minimal statelogClient stub. runBatch (used by Runner.hook's
        // per-callback machinery) needs `snapshotStack` and
        // `runInBranchContext`; everything else is a no-op.
        statelogClient: {
            snapshotStack: () => [],
            runInBranchContext: (_stack, fn) => fn(),
            startSpan: () => "span-mock",
            endSpan: () => { },
            forkStart: () => { },
            forkEnd: () => { },
            forkBranchEnd: () => { },
            checkpointCreated: () => { },
            checkpointRestored: () => { },
            error: () => { },
            toolCall: () => { },
            interruptThrown: () => { },
            interruptResolved: () => { },
            handlerDecision: () => { },
            agentStart: () => { },
            agentEnd: () => { },
        },
        hasDebugger() { return this.debuggerState !== null; },
        hasTraceWriter() { return false; },
        isInsideToolCall() { return this._toolCallDepth > 0; },
        getRunId() { return this.runId || "mock-run-id"; },
        async writeCheckpointToTraceWriter() { },
        async pauseTraceWriter() { },
        async closeTraceWriter() { },
    };
}
