import { Resource, SolType, Ref, AppliedGuard, Flow } from '@lifi/compose-spec';
import { TypedRef, InputSchema, InputDecl, TypedGuard, OutputKind } from '../types.cjs';
import { InputHandle, OutputHandle, ResourceInputHandle } from './handles.cjs';

/**
 * Arguments for calling an operation node in a flow.
 */
interface CallArgs {
    /** Maps parameter names to input/output handles or raw `$ref` pointers. */
    readonly bind: Record<string, AnyBindable>;
    /** Optional operation-specific configuration. */
    readonly config?: object;
    /** Optional guards (e.g. slippage checks) applied to this operation's outputs. */
    readonly guards?: readonly TypedGuard[];
}
/**
 * Any value that can be bound to an operation parameter: an input handle,
 * an output handle from a previous operation, or a typed `$ref` pointer.
 *
 * Use `raw.ref<T>()` to create a typed ref from a raw path string.
 */
type AnyBindable = InputHandle | OutputHandle | TypedRef;
/**
 * Provides references to runtime context values available inside a flow.
 * Access via `builder.context`.
 */
interface ContextAccessor {
    /** A `$ref` pointing to the transaction sender (signer) address. */
    readonly sender: TypedRef<'address'>;
    /** A `$ref` pointing to the on-chain execution (proxy) address. */
    readonly executionAddress: TypedRef<'address'>;
}
type InputHandleOf<D extends InputDecl> = D extends Resource ? ResourceInputHandle : D extends SolType ? InputHandle<D> : InputHandle;
/**
 * A mapped type that converts an input schema into typed handles.
 * Resource inputs produce {@link ResourceInputHandle}; scalar inputs produce {@link InputHandle}.
 *
 * @typeParam T - The flow's input schema.
 */
type InputHandles<T extends InputSchema> = {
    readonly [K in keyof T]: InputHandleOf<T[K]>;
};
/**
 * Options for creating a new flow builder.
 *
 * @typeParam T - The flow's input schema.
 */
interface FlowOptions<T extends InputSchema> {
    /** Optional human-readable name for the flow. Defaults to a random UUID. */
    readonly name?: string;
    /** Input declarations mapping names to resource or scalar types. */
    readonly inputs: T;
}
/**
 * A Flow document branded with its input schema for type-safe request building.
 *
 * The `__inputs` field is a phantom type — it exists only at compile time for
 * TypeScript inference and is never present at runtime.
 */
type TypedFlow<T extends InputSchema = InputSchema> = Flow & {
    readonly __inputs?: T;
};
/**
 * Core flow builder interface providing low-level access to flow construction.
 *
 * For most use cases, prefer the {@link FlowBuilder} type returned by `sdk.flow()`
 * which adds generated operation methods and a `compile` method.
 *
 * @typeParam T - The flow's input schema.
 */
interface FlowBuilderCore<T extends InputSchema = InputSchema> {
    /** Runtime context references (sender address, execution address). */
    readonly context: ContextAccessor;
    /** Typed handles for each declared flow input, used to bind inputs to operations. */
    readonly inputs: InputHandles<T>;
    /**
     * Appends an untyped operation node to the flow. This is an escape hatch
     * for operations not yet covered by the generated methods.
     *
     * Use `raw.ref<T>()` to reference this node's outputs in subsequent typed
     * operations.
     *
     * @param id - Unique node identifier within the flow.
     * @param op - The operation name (e.g. `"custom.vaultQuery"`).
     * @param args - Bind map, config, and optional guards for the node.
     * @throws Error if a node with the same `id` already exists in the flow.
     */
    readonly untypedOp: (id: string, op: string, args: {
        readonly bind: Record<string, Ref>;
        readonly config: Record<string, unknown>;
        readonly guards?: readonly AppliedGuard[];
    }) => void;
    /** Serialises the builder state into a {@link TypedFlow} document. */
    readonly build: () => TypedFlow<T>;
}
/** Maps output port names to their output kind for compile-time and runtime validation. */
type OutputSpec = Record<string, OutputKind>;
/** Internal interface exposed to bindGeneratedOps — not part of the public API. */
interface FlowBuilderInternal<T extends InputSchema = InputSchema> extends FlowBuilderCore<T> {
    readonly call: <O extends OutputSpec>(nodeId: string, op: string, args: CallArgs, outputs: O) => {
        readonly [K in keyof O & string]: OutputHandle<O[K]>;
    };
}
/**
 * Creates a new flow builder targeting the given chain.
 *
 * @param chainId - The EVM chain ID (e.g. `1` for Ethereum mainnet).
 * @param options - Flow configuration including input declarations.
 * @returns A {@link FlowBuilderInternal} instance.
 * @internal
 */
declare const createFlowBuilderCore: <T extends InputSchema>(chainId: number, options: FlowOptions<T>) => FlowBuilderInternal<T>;

export { type AnyBindable, type CallArgs, type ContextAccessor, type FlowBuilderCore, type FlowBuilderInternal, type FlowOptions, type InputHandles, type OutputSpec, type TypedFlow, createFlowBuilderCore };
