import { IStepConfig, StepType, INodeContext, IWorkflowContext } from '../types/index.js';

/**
 * MARK: - Step
 * @class Step
 * @description 代表工作流中的一个步骤实例
 */
export class Step {
  public readonly config: IStepConfig;

  constructor(config: IStepConfig) {
    // 可以在这里添加对 config 的验证
    if (!config.id) throw new Error("步骤配置必须包含 'id'");
    if (!config.type) throw new Error(`步骤 "${config.id}" 必须包含 'type'`);

    // 设置默认值
    this.config = {
      maxRetries: 0,
      retryDelay: 0,
      compensateOnFailure: false,
      ...config,
    };
  }

  /**
   * MARK: - Getters
   * 获取步骤 ID
   */
  get id(): string {
    return this.config.id;
  }

  /**
   * MARK: - Getters
   * 获取步骤类型
   */
  get type(): StepType {
    return this.config.type;
  }

  /**
   * MARK: nextStepId
   * 获取下一个顺序步骤的 ID
   */
  get nextStepId(): string | undefined {
    return this.config.nextStepId;
  }

  /**
   * 评估条件 (仅用于 CONDITION 类型)
   * @param context - 工作流上下文
   * @returns 条件评估结果 (布尔值或分支键名)
   * @throws 如果步骤类型不是 CONDITION 或未提供条件/分支，则抛出错误
   */
  evaluateCondition(context: IWorkflowContext): boolean | string {
    if (this.type !== StepType.CONDITION) {
      throw new Error(`步骤 "${this.id}" 不是条件类型，无法评估条件。`);
    }
    if (!this.config.condition) {
      throw new Error(`条件步骤 "${this.id}" 未定义 'condition' 函数或表达式。`);
    }

    try {
      const result = this.config.condition(context);
      if (typeof result === 'boolean') {
        // 如果是布尔值，通常用于决定是否执行 nextStepId
        return result;
      } else if (typeof result === 'string') {
        // 如果是字符串，用作分支的 key
        if (!this.config.branches || !this.config.branches[result]) {
          console.warn(`[Step: ${this.id}] 条件评估结果 "${result}" 没有对应的分支目标。`);
          // 可以选择抛出错误或返回一个默认行为（例如 false）
          // throw new Error(`条件步骤 "${this.id}" 的分支中未找到键 "${result}"。`);
          return false; // 或者返回一个特殊值表示无匹配分支
        }
        return result; // 返回分支的 key
      } else {
        throw new Error(`条件步骤 "${this.id}" 的 'condition' 函数返回了无效类型: ${typeof result}`);
      }
    } catch (error: any) {
      console.error(`[Step: ${this.id}] 评估条件时出错:`, error);
      throw new Error(`评估步骤 "${this.id}" 的条件时失败: ${error.message}`);
    }
  }

   /**
   * 获取条件分支的目标步骤 ID (仅用于 CONDITION 类型)
   * @param branchKey - evaluateCondition 返回的分支键名
   * @returns 目标步骤 ID
   * @throws 如果步骤类型不是 CONDITION 或未提供分支，或找不到对应的分支键，则抛出错误
   */
    getBranchTarget(branchKey: string): string {
        if (this.type !== StepType.CONDITION) {
          throw new Error(`步骤 "${this.id}" 不是条件类型，无法获取分支目标。`);
        }
        if (!this.config.branches) {
          throw new Error(`条件步骤 "${this.id}" 未定义 'branches'。`);
        }
        const targetStepId = this.config.branches[branchKey];
        if (!targetStepId) {
          throw new Error(`条件步骤 "${this.id}" 的分支中未找到键 "${branchKey}"。`);
        }
        return targetStepId;
      }

  /**
   * 获取并行步骤的配置 (仅用于 PARALLEL 类型)
   * @returns 并行步骤配置数组
   * @throws 如果步骤类型不是 PARALLEL 或未提供并行步骤，则抛出错误
   */
  getParallelSteps(): IStepConfig[] {
    if (this.type !== StepType.PARALLEL) {
      throw new Error(`步骤 "${this.id}" 不是并行类型，无法获取并行步骤。`);
    }
    if (!this.config.parallelSteps || this.config.parallelSteps.length === 0) {
      throw new Error(`并行步骤 "${this.id}" 未定义 'parallelSteps' 或为空。`);
    }
    return this.config.parallelSteps;
  }

  /**
   * 获取子工作流 ID (仅用于 SUB_WORKFLOW 类型)
   * @returns 子工作流定义 ID
   * @throws 如果步骤类型不是 SUB_WORKFLOW 或未提供子工作流 ID，则抛出错误
   */
  getSubWorkflowId(): string {
    if (this.type !== StepType.SUB_WORKFLOW) {
      throw new Error(`步骤 "${this.id}" 不是子工作流类型。`);
    }
    if (!this.config.subWorkflowId) {
      throw new Error(`子工作流步骤 "${this.id}" 未定义 'subWorkflowId'。`);
    }
    return this.config.subWorkflowId;
  }

  /**
   * 获取传递给子工作流的输入 (仅用于 SUB_WORKFLOW 类型)
   */
  getSubWorkflowInput(): Record<string, any> | undefined {
      if (this.type !== StepType.SUB_WORKFLOW) {
          throw new Error(`步骤 "${this.id}" 不是子工作流类型。`);
      }
      return this.config.subWorkflowInput;
  }

  /**
   * 获取关联的节点 ID (仅用于 TASK 类型)
   */
  getNodeId(): string | undefined {
      if (this.type !== StepType.TASK) {
          // 对于非 TASK 类型，可能没有 nodeId
          // console.warn(`步骤 "${this.id}" 不是 TASK 类型，但尝试获取 nodeId。`);
          return undefined;
      }
      if (!this.config.nodeId) {
          throw new Error(`任务步骤 "${this.id}" 未定义 'nodeId'。`);
      }
      return this.config.nodeId;
  }

   /**
   * 获取事件名称 (仅用于 EVENT_* 类型)
   */
    getEventName(): string {
        if (this.type !== StepType.EVENT_TRIGGER && this.type !== StepType.EVENT_LISTENER) {
            throw new Error(`步骤 "${this.id}" 不是事件类型。`);
        }
        if (!this.config.event) {
            throw new Error(`事件步骤 "${this.id}" 未定义 'event' 名称。`);
        }
        return this.config.event;
    }

   /**
    * 获取步骤的静态输入或输入映射
    */
    getInputConfig(): Record<string, any> | undefined {
        return this.config.input;
    }

   /**
    * 获取步骤的输出映射
    */
    getOutputMapping(): Record<string, string> | undefined {
        return this.config.outputMapping;
    }

   /**
    * 获取超时时间
    */
    getTimeout(): number | undefined {
        return this.config.timeout;
    }

   /**
    * 获取最大重试次数
    */
    getMaxRetries(): number {
        return this.config.maxRetries ?? 0;
    }

   /**
    * 获取重试延迟
    */
    getRetryDelay(): number {
        return this.config.retryDelay ?? 0;
    }

    /**
     * 获取失败补偿设置
     */
    getCompensateOnFailure(): boolean | string {
        return this.config.compensateOnFailure ?? false;
    }

    /**
     * 获取执行此步骤所需的角色
     */
    getRequiredRoles(): string[] | undefined {
        return this.config.requiredRoles;
    }

    /**
     * 获取 SLA 配置
     */
    getSla(): number | undefined {
        return this.config.sla;
    }
}