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

/**
 * 填充表单动作
 */
class FillFormAction extends BaseAction {
  async execute() {
    const fields = this.config.fields;
    const humanLike = this.config.humanLike !== false; // 默认使用人类行为
    
    if (!fields || typeof fields !== 'object') {
      throw new Error('表单字段配置无效');
    }
    
    this.log('info', `填写表单，共 ${Object.keys(fields).length} 个字段`);
    
    // 填写每个字段
    for (const [key, fieldConfig] of Object.entries(fields)) {
      await this.fillField(key, fieldConfig, humanLike);
    }
    
    this.log('info', '✓ 表单填写完成');
    
    return { success: true };
  }
  
  /**
   * 填写单个字段
   */
  async fillField(key, fieldConfig, humanLike) {
    let selector, value;
    
    // 支持两种配置格式
    if (typeof fieldConfig === 'object' && fieldConfig.find) {
      // 完整配置: { find: [...], value: "..." }
      selector = fieldConfig.find;
      value = this.replaceVariables(fieldConfig.value);
    } else {
      // 简化配置: { selector: value }
      selector = key;
      value = this.replaceVariables(fieldConfig);
    }
    
    // 查找元素
    const smartSelector = SmartSelector.fromConfig(selector, this.page);
    const element = await smartSelector.find(10000);
    
    if (!element) {
      throw new Error(`无法找到字段: ${JSON.stringify(selector)}`);
    }
    
    this.log('debug', `  → 填写字段: ${key}`);
    
    // 检查字段类型
    const fieldType = fieldConfig.type || 'input';
    
    if (fieldType === 'select') {
      // 下拉框选择（需要 CSS 选择器）
      const cssSelector = selector.css || selector[0]?.css;
      if (!cssSelector) {
        throw new Error(`select 类型字段需要 css 选择器: ${JSON.stringify(selector)}`);
      }
      await this.page.select(cssSelector, value);
      this.log('debug', `  → 已选择: ${value}`);
      return;
    }
    
    // 普通输入框
    // 清空字段（增强清空逻辑，支持 Stripe 等复杂表单）
    await element.click({ clickCount: 3 });
    await new Promise(resolve => setTimeout(resolve, 100));
    
    // 多次 Backspace 确保彻底清空
    const clearTimes = fieldConfig.clearTimes || this.config.clearTimes || 25;
    for (let i = 0; i < clearTimes; i++) {
      await this.page.keyboard.press('Backspace');
    }
    await new Promise(resolve => setTimeout(resolve, 200));
    
    if (humanLike) {
      // 人类行为模拟
      await this.typeHumanLike(element, value);
    } else {
      // 直接输入
      await element.type(value, { delay: 100 });
    }
    
    // 触发事件
    await this.page.evaluate((el) => {
      el.dispatchEvent(new Event('input', { bubbles: true }));
      el.dispatchEvent(new Event('change', { bubbles: true }));
    }, element);
  }
  
  /**
   * 模拟人类输入
   */
  async typeHumanLike(element, text) {
    for (const char of text) {
      await element.type(char, {
        delay: Math.random() * 100 + 50 // 50-150ms 随机延迟
      });
    }
    
    // 随机暂停
    if (Math.random() > 0.7) {
      await new Promise(resolve => setTimeout(resolve, Math.random() * 500 + 200));
    }
  }
  
  /**
   * 提交表单
   */
  async submitForm(submitConfig) {
    this.log('info', '  → 提交表单');
    
    const selector = submitConfig.find || submitConfig;
    const smartSelector = SmartSelector.fromConfig(selector, this.page);
    const button = await smartSelector.find(10000);
    
    if (!button) {
      throw new Error(`无法找到提交按钮: ${JSON.stringify(selector)}`);
    }
    
    // 等待按钮可点击
    await this.waitForButtonEnabled(button);
    
    // 点击
    await button.click();
    
    // 等待提交后的延迟
    if (submitConfig.waitAfter) {
      await new Promise(resolve => setTimeout(resolve, submitConfig.waitAfter));
    }
  }
  
  /**
   * 等待按钮启用
   */
  async waitForButtonEnabled(button, timeout = 30000) {
    const startTime = Date.now();
    
    while (Date.now() - startTime < timeout) {
      const isEnabled = await this.page.evaluate((btn) => {
        return !btn.disabled;
      }, button);
      
      if (isEnabled) {
        return;
      }
      
      await new Promise(resolve => setTimeout(resolve, 500));
    }
    
    throw new Error('按钮未启用（超时）');
  }
}

module.exports = FillFormAction;
