import type { SandboxSession } from '../sandbox/session';
type AnyFunction = (...args: any[]) => any;
export type ScriptedSandboxMethod = {
    [TKey in keyof SandboxSession]-?: NonNullable<SandboxSession[TKey]> extends AnyFunction ? TKey : never;
}[keyof SandboxSession];
type SandboxMethodFunction<TMethod extends ScriptedSandboxMethod> = Extract<NonNullable<SandboxSession[TMethod]>, AnyFunction>;
type SandboxMethodArgs<TMethod extends ScriptedSandboxMethod> = Parameters<SandboxMethodFunction<TMethod>>;
type SandboxMethodResult<TMethod extends ScriptedSandboxMethod> = Awaited<ReturnType<SandboxMethodFunction<TMethod>>>;
type ScriptedSandboxResponderResult<TMethod extends ScriptedSandboxMethod> = ReturnType<SandboxMethodFunction<TMethod>> extends PromiseLike<unknown> ? SandboxMethodResult<TMethod> | PromiseLike<SandboxMethodResult<TMethod>> : ReturnType<SandboxMethodFunction<TMethod>>;
export type RecordedSandboxCall = Readonly<{
    /** The zero-based position of this call in `calls`. */
    index: number;
    /** The invoked method. New SDK versions may add method names. */
    method: string;
    /** Detached invocation-time arguments in parameter order. */
    args: readonly unknown[];
}>;
export type ScriptedSandboxCallFor<TMethod extends ScriptedSandboxMethod> = Readonly<{
    index: number;
    method: TMethod;
    args: Readonly<SandboxMethodArgs<TMethod>>;
}>;
type ScriptedSandboxMatcher<TMethod extends ScriptedSandboxMethod> = (...args: SandboxMethodArgs<TMethod>) => boolean | void;
type ScriptedSandboxResponder<TMethod extends ScriptedSandboxMethod> = (call: ScriptedSandboxCallFor<TMethod>) => ScriptedSandboxResponderResult<TMethod>;
type ScriptedSandboxStepBase<TMethod extends ScriptedSandboxMethod> = {
    method: TMethod;
    match?: ScriptedSandboxMatcher<TMethod>;
};
type ScriptedSandboxResultStep<TMethod extends ScriptedSandboxMethod> = ScriptedSandboxStepBase<TMethod> & {
    result: SandboxMethodResult<TMethod>;
    respond?: never;
    error?: never;
};
type ScriptedSandboxResponderStep<TMethod extends ScriptedSandboxMethod> = ScriptedSandboxStepBase<TMethod> & {
    respond: ScriptedSandboxResponder<TMethod>;
    result?: never;
    error?: never;
};
type ScriptedSandboxErrorStep<TMethod extends ScriptedSandboxMethod> = ScriptedSandboxStepBase<TMethod> & {
    error: unknown;
    result?: never;
    respond?: never;
};
type ScriptedSandboxStep<TMethod extends ScriptedSandboxMethod> = ScriptedSandboxResultStep<TMethod> | ScriptedSandboxResponderStep<TMethod> | ScriptedSandboxErrorStep<TMethod>;
export type ScriptedSandboxInput<TMethod extends ScriptedSandboxMethod = ScriptedSandboxMethod> = {
    [TCurrentMethod in TMethod]: ScriptedSandboxStep<TCurrentMethod>;
}[TMethod];
export type ScriptedSandboxSession<TMethod extends ScriptedSandboxMethod = never> = SandboxSession & Required<Pick<SandboxSession, TMethod>> & {
    /** All calls recorded by this session in invocation order. */
    readonly calls: readonly RecordedSandboxCall[];
    /** The number of scripted steps that have not been consumed. */
    readonly remainingSteps: number;
    /** Throws when the script still contains unconsumed steps. */
    assertComplete(): void;
};
export type InvalidScriptedSandboxStepReason = 'invalid_input' | 'unknown_method' | 'invalid_matcher' | 'invalid_outcome';
export declare class InvalidScriptedSandboxStepError extends Error {
    readonly reason: InvalidScriptedSandboxStepReason;
    /** The zero-based position of the invalid factory input. */
    readonly inputIndex: number;
    readonly method?: string;
    constructor(options: {
        reason: InvalidScriptedSandboxStepReason;
        inputIndex: number;
        message: string;
        method?: string;
    });
}
export declare class UnexpectedSandboxCallError extends Error {
    /** The zero-based position of the call in `calls`. */
    readonly callIndex: number;
    readonly actualMethod: string;
    readonly expectedMethod?: string;
    readonly remainingSteps: number;
    constructor(options: {
        callIndex: number;
        actualMethod: string;
        expectedMethod?: string;
        remainingSteps: number;
    });
}
export declare class SandboxCallMatcherError extends Error {
    /** The zero-based position of the call in `calls`. */
    readonly callIndex: number;
    readonly method: string;
    constructor(call: RecordedSandboxCall);
}
export declare class UnconsumedSandboxStepsError extends Error {
    readonly remainingSteps: number;
    readonly pendingMethods: readonly string[];
    constructor(pendingMethods: readonly string[]);
}
/**
 * Creates a deterministic sandbox session with only the scripted optional
 * methods installed on the returned object.
 */
export declare function scriptedSandboxSession<const TInputs extends readonly ScriptedSandboxInput[]>(inputs: TInputs): ScriptedSandboxSession<TInputs[number]['method']>;
export declare function scriptedSandboxSession<TMethod extends ScriptedSandboxMethod>(inputs: Iterable<ScriptedSandboxInput<TMethod>>): ScriptedSandboxSession<TMethod>;
export declare function scriptedSandboxSession(): ScriptedSandboxSession<never>;
export {};
