export const CONCURRENCY_SCHEDULE_KINDS = [
  "double-submit",
  "lost-update",
  "compare-and-swap-conflict",
  "lock-expiry",
  "retry-overlap",
  "out-of-order-delivery",
] as const;

export type ConcurrencyScheduleKind = (typeof CONCURRENCY_SCHEDULE_KINDS)[number];

export type ScheduleStepRef = {
  taskId: string;
  stepId: string;
};

export type ConcurrencySchedule = {
  id: string;
  kind: ConcurrencyScheduleKind;
  interleaving: readonly ScheduleStepRef[];
};

export type TraceEntry = {
  index: number;
  taskId: string;
  stepId: string;
  yieldPoints: readonly string[];
};

export type StepContext<TState> = {
  state: TState;
  yield: (point: string) => Promise<void>;
};

export type InstrumentedStep<TState> = (ctx: StepContext<TState>) => Promise<void>;

export type InstrumentedTask<TState> = {
  steps: readonly string[];
  runStep: (stepId: string, ctx: StepContext<TState>) => Promise<void>;
};

export type InstrumentedSystem<TState> = {
  id: string;
  createState: () => TState | Promise<TState>;
  tasks: Readonly<Record<string, InstrumentedTask<TState>>>;
  assertOutcome: (state: TState) => void;
};

export type ConcurrencyScheduleResult = {
  id: string;
  kind: ConcurrencyScheduleKind;
  holds: boolean;
  trace: readonly TraceEntry[];
  finalState?: unknown;
  error?: string;
};

export type NamedScheduleOptions = {
  id: string;
};
