// src/types/config.ts
import { IWorkflowContext, INodeContext } from './runtime';

// --- Node Definition ---
export type NodeFunction<Input = any, Output = any> = (
  context: INodeContext, // Pass full context
  input: Input // Keep typed input for convenience if desired, or rely solely on context.input
) => Promise<Output | void>; // Allow void return if output set via context

export interface NodeMetadata {
  id: string; // Unique Node ID/Name
  description?: string;
  inputSchema?: object; // Optional JSON schema for input validation
  outputSchema?: object; // Optional JSON schema for output validation
}

// --- Step Configuration ---
export enum StepType {
  TASK = 'TASK',
  CONDITION = 'CONDITION',
  PARALLEL = 'PARALLEL',
  SUB_WORKFLOW = 'SUB_WORKFLOW',
  EVENT_TRIGGER = 'EVENT_TRIGGER', // Added from Root
  EVENT_LISTENER = 'EVENT_LISTENER',// Added from Root
  // Could add others like WAIT, MANUAL_APPROVAL etc.
}

export interface RetryOptions {
  maxRetries: number;
  delayMs: number; // Delay between retries
  backoffFactor?: number; // Optional exponential backoff
}

// Base configuration for all steps
export interface BaseStepConfig {
  id: string; // Unique ID within the workflow definition
  description?: string;
  nextStepId?: string; // Default next step (used by TASK, SUB_WORKFLOW etc.)
  // --- Features from Root ---
  timeoutMs?: number;
  retryOptions?: RetryOptions;
  compensateOnFailure?: boolean | string; // Boolean or step ID for compensation task
  requiredRoles?: string[]; // Optional role check
  // --- Input/Output Mapping (Crucial from Root) ---
  // Maps context variables (e.g., 'variables.userId') or step outputs ('steps.prevStep.output.data') to node input fields
  inputMapping?: Record<string, string>; // e.g., { nodeInputField: 'variables.someData' }
  // Maps node output fields back to workflow variables
  outputMapping?: Record<string, string>; // e.g., { 'variables.resultData': 'output.processedValue' }
}

// Specific Step Configurations
export interface TaskStepConfig extends BaseStepConfig {
  type: StepType.TASK;
  nodeId: string; // ID of the registered node to execute
  input?: Record<string, any>; // Static input values (can be overridden by inputMapping)
}

export type ConditionFunction = (context: IWorkflowContext) => Promise<string | boolean> | string | boolean;

export interface ConditionStepConfig extends BaseStepConfig {
  type: StepType.CONDITION;
  condition: ConditionFunction;
  branches: Record<string, string>; // Map condition result (true/false/'branchName') to next step ID
  // `nextStepId` is typically not used here
}

export interface ParallelStepConfig extends BaseStepConfig {
  type: StepType.PARALLEL;
  // Define parallel branches - each branch is a mini-workflow definition (array of steps)
  // Simpler approach: Just list step configs to run in parallel
  parallelSteps: StepConfig[]; // Array of steps to execute concurrently
  // `nextStepId` points to the step after ALL parallel branches complete
}

export interface SubWorkflowStepConfig extends BaseStepConfig {
  type: StepType.SUB_WORKFLOW;
  subWorkflowId: string; // ID of the workflow definition to call
  input?: Record<string, any>; // Static input (overridden by mapping)
  waitForCompletion?: boolean; // Default true
}

// --- Event Step Configurations (from Root) ---
export interface EventTriggerStepConfig extends BaseStepConfig {
    type: StepType.EVENT_TRIGGER;
    eventName: string;
    eventDataMapping?: Record<string, string>; // Map context to event payload
}

export interface EventListenerStepConfig extends BaseStepConfig {
    type: StepType.EVENT_LISTENER;
    eventName: string;
    // outputMapping maps event payload to variables
    // Often used as a starting step, so no `nextStepId` might be needed initially if handled by definition.setStartStep
}


// Union type for any step configuration
export type StepConfig =
  | TaskStepConfig
  | ConditionStepConfig
  | ParallelStepConfig
  | SubWorkflowStepConfig
  | EventTriggerStepConfig
  | EventListenerStepConfig;

// --- Workflow Definition Structure ---
export interface WorkflowDefinitionData {
  id: string;
  name?: string;
  description?: string;
  steps: Record<string, StepConfig>; // Map of stepId to StepConfig
  startStepId?: string;
  version?: number; // Optional versioning
  // Metadata like owner, tags etc.
}