const BaseAction = require('../core/base-action');

/**
 * 重试块动作 - 将一组步骤作为整体进行重试
 * 
 * 配置示例：
 * - action: retryBlock
 *   name: "支付流程"
 *   maxRetries: 5
 *   retryDelay: 2000
 *   onRetryBefore:
 *     - action: custom
 *       handler: "regenerateCard"
 *   steps:
 *     - action: fillForm
 *       fields: {...}
 *     - action: click
 *       selector: {...}
 */
class RetryBlockAction extends BaseAction {
  async execute() {
    const {
      steps = [],
      maxRetries = 3,
      retryDelay = 1000,
      onRetryBefore = [],
      onRetryAfter = []
    } = this.config;
    
    const blockName = this.config.name || 'RetryBlock';
    
    if (!steps || steps.length === 0) {
      throw new Error('RetryBlock 必须包含至少一个步骤');
    }
    
    let lastError = null;
    
    for (let attempt = 0; attempt <= maxRetries; attempt++) {
      try {
        if (attempt > 0) {
          this.log('info', `${blockName} - 第 ${attempt + 1} 次重试...`);
          
          // 执行重试前的钩子
          if (onRetryBefore.length > 0) {
            this.log('debug', '执行重试前钩子...');
            await this.executeHooks(onRetryBefore);
          }
          
          // 延迟
          if (retryDelay > 0) {
            await new Promise(resolve => setTimeout(resolve, retryDelay));
          }
        }
        
        // 执行步骤块
        this.log('debug', `执行 ${steps.length} 个步骤...`);
        await this.executeSteps(steps);
        
        // 执行成功后的钩子（仅首次成功时）
        if (attempt > 0 && onRetryAfter.length > 0) {
          this.log('debug', '执行重试后钩子...');
          await this.executeHooks(onRetryAfter);
        }
        
        // 成功，跳出循环
        if (attempt > 0) {
          this.log('success', `✓ ${blockName} 在第 ${attempt + 1} 次尝试后成功`);
        }
        
        return { success: true, attempts: attempt + 1 };
        
      } catch (error) {
        lastError = error;
        
        if (attempt < maxRetries) {
          this.log('warn', `${blockName} 执行失败: ${error.message}`);
          this.log('info', `准备重试 (${attempt + 1}/${maxRetries})...`);
        } else {
          this.log('error', `${blockName} 在 ${maxRetries + 1} 次尝试后仍然失败`);
        }
      }
    }
    
    // 所有重试都失败
    throw new Error(`${blockName} 失败: ${lastError.message}`);
  }
  
  /**
   * 执行钩子函数
   */
  async executeHooks(hooks) {
    for (const hookConfig of hooks) {
      await this.executeStep(hookConfig);
    }
  }
  
  /**
   * 执行步骤列表
   */
  async executeSteps(steps) {
    for (const stepConfig of steps) {
      await this.executeStep(stepConfig);
    }
  }
  
  /**
   * 执行单个步骤
   */
  async executeStep(stepConfig) {
    const actionType = stepConfig.action;
    
    // 动态加载对应的 Action
    const ActionClass = this.getActionClass(actionType);
    
    // 修复：BaseAction 构造函数签名是 (context, config)
    const action = new ActionClass(
      this.context,   // 第一个参数：context
      stepConfig      // 第二个参数：config
    );
    
    return await action.execute();
  }
  
  /**
   * 根据 action 类型获取 Action 类
   */
  getActionClass(actionType) {
    const actionMap = {
      navigate: require('./navigate-action'),
      fillForm: require('./fill-form-action'),
      click: require('./click-action'),
      wait: require('./wait-action'),
      custom: require('./custom-action'),
      scroll: require('./scroll-action'),
      verify: require('./verify-action')
    };
    
    const ActionClass = actionMap[actionType];
    
    if (!ActionClass) {
      throw new Error(`未知的 action 类型: ${actionType}`);
    }
    
    return ActionClass;
  }
}

module.exports = RetryBlockAction;
