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

/**
 * 验证动作 - 检测页面状态并根据结果采取行动
 * 
 * 用途：验证操作结果（如支付成功/失败），支持轮询检测
 * 
 * Example:
 * - action: verify
 *   name: Verify payment result
 *   conditions:
 *     success:
 *       - urlNotContains: stripe.com
 *       - elementExists: .payment-success
 *     failure:
 *       - elementExists: .error-message
 *       - textContains: declined
 *   timeout: 10000
 *   pollInterval: 500
 *   onFailure: throw
 */
class VerifyAction extends BaseAction {
  async execute() {
    const {
      conditions,
      timeout = 10000,
      pollInterval = 500,
      onSuccess = 'continue',
      onFailure = 'throw',
      onTimeout = 'throw'
    } = this.config;
    
    if (!conditions) {
      throw new Error('Verify action 需要 conditions 参数');
    }
    
    this.log('debug', '开始验证...');
    
    const startTime = Date.now();
    
    while (Date.now() - startTime < timeout) {
      // 检查成功条件
      if (conditions.success) {
        const successResult = await this.checkConditions(conditions.success);
        if (successResult.matched) {
          this.log('success', `✓ 验证成功: ${successResult.reason}`);
          return this.handleResult('success', onSuccess);
        }
      }
      
      // 检查失败条件
      if (conditions.failure) {
        const failureResult = await this.checkConditions(conditions.failure);
        if (failureResult.matched) {
          this.log('error', `✗ 验证失败: ${failureResult.reason}`);
          return this.handleResult('failure', onFailure, failureResult.reason);
        }
      }
      
      // 等待后继续轮询
      await new Promise(resolve => setTimeout(resolve, pollInterval));
    }
    
    // 超时
    this.log('warn', `⚠ 验证超时（${timeout}ms）`);
    return this.handleResult('timeout', onTimeout, '验证超时');
  }
  
  /**
   * 检查条件组（任一满足即可）
   */
  async checkConditions(conditionList) {
    if (!Array.isArray(conditionList)) {
      conditionList = [conditionList];
    }
    
    for (const condition of conditionList) {
      const result = await this.checkSingleCondition(condition);
      if (result.matched) {
        return result;
      }
    }
    
    return { matched: false };
  }
  
  /**
   * 检查单个条件
   */
  async checkSingleCondition(condition) {
    // 条件类型1: urlContains / urlNotContains
    if (condition.urlContains !== undefined) {
      const currentUrl = this.page.url();
      const matched = currentUrl.includes(condition.urlContains);
      return {
        matched,
        reason: matched ? `URL 包含 "${condition.urlContains}"` : null
      };
    }
    
    if (condition.urlNotContains !== undefined) {
      const currentUrl = this.page.url();
      const matched = !currentUrl.includes(condition.urlNotContains);
      return {
        matched,
        reason: matched ? `URL 不包含 "${condition.urlNotContains}"` : null
      };
    }
    
    // 条件类型2: urlEquals
    if (condition.urlEquals !== undefined) {
      const currentUrl = this.page.url();
      const matched = currentUrl === condition.urlEquals;
      return {
        matched,
        reason: matched ? `URL 等于 "${condition.urlEquals}"` : null
      };
    }
    
    // 条件类型3: elementExists / elementNotExists
    if (condition.elementExists !== undefined) {
      const element = await this.page.$(condition.elementExists);
      const matched = !!element;
      return {
        matched,
        reason: matched ? `元素存在: ${condition.elementExists}` : null
      };
    }
    
    if (condition.elementNotExists !== undefined) {
      const element = await this.page.$(condition.elementNotExists);
      const matched = !element;
      return {
        matched,
        reason: matched ? `元素不存在: ${condition.elementNotExists}` : null
      };
    }
    
    // 条件类型4: elementVisible / elementHidden
    if (condition.elementVisible !== undefined) {
      const visible = await this.page.evaluate((selector) => {
        const el = document.querySelector(selector);
        if (!el) return false;
        const style = window.getComputedStyle(el);
        return style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0';
      }, condition.elementVisible);
      
      return {
        matched: visible,
        reason: visible ? `元素可见: ${condition.elementVisible}` : null
      };
    }
    
    if (condition.elementHidden !== undefined) {
      const hidden = await this.page.evaluate((selector) => {
        const el = document.querySelector(selector);
        if (!el) return true;
        const style = window.getComputedStyle(el);
        return style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0';
      }, condition.elementHidden);
      
      return {
        matched: hidden,
        reason: hidden ? `元素隐藏: ${condition.elementHidden}` : null
      };
    }
    
    // 条件类型5: textContains / textNotContains
    if (condition.textContains !== undefined) {
      const hasText = await this.page.evaluate((text) => {
        return document.body.textContent.includes(text);
      }, condition.textContains);
      
      return {
        matched: hasText,
        reason: hasText ? `页面包含文本: "${condition.textContains}"` : null
      };
    }
    
    if (condition.textNotContains !== undefined) {
      const hasText = await this.page.evaluate((text) => {
        return document.body.textContent.includes(text);
      }, condition.textNotContains);
      
      return {
        matched: !hasText,
        reason: !hasText ? `页面不包含文本: "${condition.textNotContains}"` : null
      };
    }
    
    // 条件类型6: elementTextContains
    if (condition.elementTextContains !== undefined) {
      const { selector, text } = condition.elementTextContains;
      const hasText = await this.page.evaluate((sel, txt) => {
        const el = document.querySelector(sel);
        return el && el.textContent.includes(txt);
      }, selector, text);
      
      return {
        matched: hasText,
        reason: hasText ? `元素 ${selector} 包含文本 "${text}"` : null
      };
    }
    
    // 条件类型7: custom - 自定义 JS 函数
    if (condition.custom !== undefined) {
      const matched = await this.page.evaluate(condition.custom);
      return {
        matched,
        reason: matched ? '自定义条件满足' : null
      };
    }
    
    return { matched: false };
  }
  
  /**
   * 处理验证结果
   */
  handleResult(resultType, action, reason = '') {
    switch (action) {
      case 'continue':
        // 继续执行，不做任何事
        return { success: true, result: resultType };
      
      case 'throw':
        // 抛出异常，触发重试或错误处理
        throw new Error(`验证${resultType}: ${reason}`);
      
      case 'return':
        // 返回结果，由调用者处理
        return { success: resultType === 'success', result: resultType, reason };
      
      default:
        return { success: true, result: resultType };
    }
  }
}

module.exports = VerifyAction;
