// src/flow/FlowTypes.ts
//
// ARCHITECTURAL NOTE: Generic defaults MUST use `any` for flow builder pattern.
//
// The issue is function contravariance: a function accepting `unknown` cannot
// be assigned to/from a function accepting a specific type `T`. This means:
// - fn: (input: unknown) => unknown CANNOT store fn: (input: T) => U
// - This is fundamental to TypeScript's type system, not a workaround
//
// The pattern used by RxJS, Redux, and other pipeline libraries:
// - Internal storage uses `any` (necessary for heterogeneous arrays)
// - Builder API provides type safety through explicit generic parameters
// - Consumers get full type inference and safety at the API boundary

export type LocalStageKind = 'local-map' | 'local-filter';
export type RemoteStageKind = 'remote-rr' | 'remote-sink';
export type FlowStageKind = LocalStageKind | RemoteStageKind;

export interface IBaseStage {
  id: string;
  kind: FlowStageKind;
  description?: string;
}

/**
 * Local map stage - transforms input to output.
 * Generic defaults allow heterogeneous storage; builder provides type safety.
 */
export interface ILocalMapStage<TIn = unknown, TOut = unknown> extends IBaseStage {
  kind: 'local-map';
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  fn: (input: any) => any | Promise<any>;
}

/**
 * Local filter stage - predicate to include/exclude values.
 */
export interface ILocalFilterStage<T = unknown> extends IBaseStage {
  kind: 'local-filter';
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  fn: (input: any) => boolean | Promise<boolean>;
}

/**
 * Remote request/response stage.
 * Input becomes the RR payload; the result becomes the new value.
 */
export interface IRemoteRRStage<TReq = unknown, TRes = unknown> extends IBaseStage {
  kind: 'remote-rr';
  mount: string;
  op: string;
  timeoutMs?: number;
}

/**
 * Remote sink stage: RR side-effect whose result is ignored; failure aborts
 * the flow; input value flows through unchanged.
 */
export interface IRemoteSinkStage<T = unknown> extends IBaseStage {
  kind: 'remote-sink';
  mount: string;
  op: string;
  timeoutMs?: number;
}

/**
 * Union of all stage types for heterogeneous storage.
 */
export type AnyStage =
  | ILocalMapStage
  | ILocalFilterStage
  | IRemoteRRStage
  | IRemoteSinkStage;
