import { Simplify } from "../../helpers/types.js";
import { FoundStep } from "../InngestStepTools.js";
import { MetadataUpdate } from "../InngestMetadata.js";
import { BasicFoundStep, InngestExecutionFactory, MemoizedOp } from "./InngestExecution.js";
import { OutgoingOp } from "../../types.js";
import { StepError } from "../StepError.js";
import { LazyOps } from "./lazyOps.js";

//#region src/components/execution/engine.d.ts
declare namespace engine_d_exports {
  export { Checkpoints, ExecutionState, _internals, createExecutionEngine };
}
declare const createExecutionEngine: InngestExecutionFactory;
/**
 * Types of checkpoints that can be reached during execution.
 */
interface Checkpoints {
  "steps-found": {
    steps: [FoundStep, ...FoundStep[]];
  };
  "function-rejected": {
    error: unknown;
  };
  "function-resolved": {
    data: unknown;
  };
  "step-not-found": {
    step: OutgoingOp;
    foundSteps: BasicFoundStep[];
    totalFoundSteps: number;
  };
  "checkpointing-runtime-reached": {};
  "checkpointing-buffer-interval-reached": {};
}
type Checkpoint = { [K in keyof Checkpoints]: Simplify<{
  type: K;
} & Checkpoints[K]> }[keyof Checkpoints];
interface ExecutionState {
  /**
   * A value that indicates that we're executing this step. Can be used to
   * ensure steps are not accidentally nested until we support this across all
   * platforms.
   */
  executingStep?: Readonly<Omit<OutgoingOp, "id">>;
  /**
   * A map of step IDs to their data, used to fill previously-completed steps
   * with state from the executor.
   */
  stepState: Record<string, MemoizedOp>;
  /**
   * Hashed defer step IDs the backend has already received. Used to skip
   * re-emitting `DeferAdd` ops on replay. Defer ops aren't memoized like
   * normal steps (they have no result), so this lives separately from
   * `stepState`.
   */
  priorDefers: Record<string, unknown>;
  /**
   * The number of steps we expect to fulfil based on the state passed from the
   * Executor.
   */
  stepsToFulfill: number;
  /**
   * A map of step IDs to their functions to run. The executor can request a
   * specific step to run, so we need to store the function to run here.
   */
  steps: Map<string, FoundStep>;
  /**
   * A flag which represents whether or not steps are understood to be used in
   * this function. This is used to determine whether or not we should run
   * some steps (such as `step.sendEvent`) inline as they are found.
   */
  hasSteps: boolean;
  /**
   * The core loop - a generator used to take an action upon finding the next
   * checkpoint. Manages the flow of execution and cleaning up after itself.
   */
  loop: AsyncGenerator<Checkpoint, void, void>;
  /**
   * A function that resolves the `Promise` returned by `waitForNextDecision`.
   */
  setCheckpoint: (data: Checkpoint) => void;
  /**
   * Returns whether or not all state passed from the executor has been used to
   * fulfill found steps.
   */
  allStateUsed: () => boolean;
  /**
   * An ordered list of step IDs that represents the order in which their
   * execution was completed.
   */
  stepCompletionOrder: string[];
  /**
   * An set of step IDs that have yet to be seen in this execution. Used to
   * decide when to trigger middleware based on the current state.
   */
  remainingStepsToBeSeen: Set<string>;
  /**
   * If defined, this is the error that purposefully thrown when memoizing step
   * state in order to support per-step errors.
   *
   * We use this so that if the function itself rejects with the same error, we
   * know that it was entirely uncaught (or at the very least rethrown), so we
   * should send a `NonRetriableError` to stop needless execution of a function
   * that will continue to fail.
   *
   * TODO This is imperfect, as this state is currently kept around for longer
   * than it needs to be. It should disappear as soon as we've seen that the
   * error did not immediately throw. It may need to be refactored to work a
   * little more smoothly with the core loop.
   */
  recentlyRejectedStepError?: StepError;
  /**
   * If defined, this indicates that we're running a checkpointed function run,
   * and contains the data needed to report progress back to Inngest.
   */
  checkpointedRun?: {
    fnId: string;
    appId: string;
    token?: string;
    realtimeToken: string;
  };
  /**
   * Set when the checkpointing max runtime has been reached. Rather than
   * immediately returning a DiscoveryRequest (which re-invokes user code
   * between steps), we defer until the next step boundary so the user's code
   * between steps can complete.
   */
  checkpointingRuntimeExceeded?: boolean;
  /**
   * A buffer of steps that are currently queued to be checkpointed.
   */
  checkpointingStepBuffer: OutgoingOp[];
  /**
   * Buffer for opcode-only sync ops (e.g. `DeferAdd`) awaiting shipment
   * on the next outbound wire message. See `ARCHITECTURE.md` and
   * `lazyOps.ts` for the rationale.
   */
  lazyOps: LazyOps;
  /**
   * Metadata collected during execution to be sent with outgoing ops.
   */
  metadata?: Map<string, Array<MetadataUpdate>>;
}
/**
 * Result of resolving a step ID collision.
 */
interface CollisionResolutionResult {
  /** The final ID to use (either original or with index suffix). */
  finalId: string;
  /** The index used, if collision was detected. */
  index?: number;
}
/**
 * Resolves step ID collisions by appending an index suffix if needed.
 * Consolidates the duplicated collision detection logic.
 *
 * @param baseId - The original step ID
 * @param stepsMap - Map of existing steps (keyed by hashed ID)
 * @param expectedIndexes - Map tracking expected next index for each base ID
 * @returns The final ID to use and optional index
 */
declare function resolveStepIdCollision({
  baseId,
  expectedIndexes,
  stepsMap
}: {
  baseId: string;
  expectedIndexes: Map<string, number>;
  stepsMap: Map<string, FoundStep>;
}): CollisionResolutionResult;
/**
 * Exported for testing.
 */
declare const _internals: {
  hashOp: (op: OutgoingOp) => OutgoingOp;
  hashId: (id: string) => string;
  resolveStepIdCollision: typeof resolveStepIdCollision;
};
//#endregion
export { engine_d_exports };
//# sourceMappingURL=engine.d.ts.map