/**
 * 智能选择器 - 支持多策略元素查找
 */
class SmartSelector {
  constructor(page) {
    this.page = page;
    this.strategies = [];
  }
  
  /**
   * 从配置构建选择器
   * @param {Object|Array|string} config - 选择器配置
   * @param {Object} page - Puppeteer page 对象
   * @returns {SmartSelector}
   */
  static fromConfig(config, page) {
    const selector = new SmartSelector(page);
    
    if (typeof config === 'string') {
      // 简单 CSS 选择器
      selector.css(config);
    } else if (Array.isArray(config)) {
      // 多策略
      config.forEach(strategy => {
        if (strategy.css) selector.css(strategy.css);
        if (strategy.xpath) selector.xpath(strategy.xpath);
        if (strategy.text) {
          const textOptions = {
            exact: strategy.exact,
            caseInsensitive: strategy.caseInsensitive,
            selector: strategy.selector,
            filterDisabled: strategy.filterDisabled,
            filterHidden: strategy.filterHidden
          };
          selector.text(strategy.text, textOptions);
        }
        if (strategy.placeholder) selector.placeholder(strategy.placeholder);
        if (strategy.label) selector.label(strategy.label);
        if (strategy.type) selector.type(strategy.type);
        if (strategy.role) selector.role(strategy.role);
        if (strategy.testid) selector.testid(strategy.testid);
        if (strategy.name) selector.name(strategy.name);
      });
    } else if (typeof config === 'object') {
      // 单个策略对象
      if (config.css) selector.css(config.css);
      if (config.xpath) selector.xpath(config.xpath);
      if (config.text) {
        const textOptions = {
          exact: config.exact,
          caseInsensitive: config.caseInsensitive,
          selector: config.selector,
          filterDisabled: config.filterDisabled,
          filterHidden: config.filterHidden
        };
        selector.text(config.text, textOptions);
      }
      if (config.placeholder) selector.placeholder(config.placeholder);
      if (config.label) selector.label(config.label);
      if (config.type) selector.type(config.type);
      if (config.role) selector.role(config.role);
      if (config.testid) selector.testid(config.testid);
      if (config.name) selector.name(config.name);
    }
    
    return selector;
  }
  
  css(selector) {
    this.strategies.push({
      type: 'css',
      find: async () => await this.page.$(selector)
    });
    return this;
  }
  
  xpath(xpath) {
    this.strategies.push({
      type: 'xpath',
      find: async () => {
        const elements = await this.page.$x(xpath);
        return elements[0] || null;
      }
    });
    return this;
  }
  
  /**
   * 文本选择器（通用方法 - 框架级）
   * 根据文本内容查找元素，不限定元素类型
   * 用户可通过 selector 参数指定查找范围
   */
  text(text, options = {}) {
    const { 
      exact = true,  // 默认精确匹配（更安全）
      caseInsensitive = true,
      selector = '*',  // 默认查找所有元素（通用）
      filterDisabled = false,
      filterHidden = true
    } = options;
    
    this.strategies.push({
      type: 'text',
      find: async () => {
        return await this._findByText(text, selector, { exact, caseInsensitive, filterDisabled, filterHidden });
      }
    });
    return this;
  }
  
  /**
   * 内部方法：按文本查找元素（使用指定的 CSS 选择器）
   */
  async _findByText(searchText, cssSelector, options) {
    const { exact, caseInsensitive, filterDisabled, filterHidden } = options;
    
    const element = await this.page.evaluateHandle(
      ({ searchText, exact, caseInsensitive, cssSelector, filterDisabled, filterHidden }) => {
        const elements = Array.from(document.querySelectorAll(cssSelector));
        
        for (const el of elements) {
          // 过滤 disabled
          if (filterDisabled && (el.tagName === 'BUTTON' || el.tagName === 'INPUT') && el.disabled) {
            continue;
          }
          
          // 过滤隐藏元素
          if (filterHidden && el.offsetParent === null) continue;
          
          // 获取文本
          const text = (el.textContent || '').trim();
          if (!text) continue;
          
          // 标准化空格
          const normalizedText = text.replace(/\s+/g, ' ');
          const normalizedSearch = searchText.replace(/\s+/g, ' ');
          
          // 匹配
          let matches = false;
          if (exact) {
            matches = caseInsensitive
              ? normalizedText.toLowerCase() === normalizedSearch.toLowerCase()
              : normalizedText === normalizedSearch;
          } else {
            matches = caseInsensitive
              ? normalizedText.toLowerCase().includes(normalizedSearch.toLowerCase())
              : normalizedText.includes(normalizedSearch);
          }
          
          if (matches) return el;
        }
        
        return null;
      }, 
      { searchText, exact, caseInsensitive, cssSelector, filterDisabled, filterHidden }
    );
    
    if (element) {
      const elementHandle = element.asElement();
      if (elementHandle) return elementHandle;
    }
    
    return null;
  }
  
  placeholder(placeholder) {
    this.strategies.push({
      type: 'placeholder',
      find: async () => await this.page.$(`[placeholder="${placeholder}"]`)
    });
    return this;
  }
  
  label(labelText) {
    this.strategies.push({
      type: 'label',
      find: async () => {
        return await this.page.evaluateHandle((text) => {
          const labels = Array.from(document.querySelectorAll('label'));
          const label = labels.find(l => l.textContent.trim() === text.trim());
          if (label && label.htmlFor) {
            return document.getElementById(label.htmlFor);
          }
          return null;
        }, labelText);
      }
    });
    return this;
  }
  
  type(inputType) {
    this.strategies.push({
      type: 'type',
      find: async () => await this.page.$(`input[type="${inputType}"]`)
    });
    return this;
  }
  
  role(role) {
    this.strategies.push({
      type: 'role',
      find: async () => await this.page.$(`[role="${role}"]`)
    });
    return this;
  }
  
  testid(testid) {
    this.strategies.push({
      type: 'testid',
      find: async () => await this.page.$(`[data-testid="${testid}"]`)
    });
    return this;
  }
  
  name(name) {
    this.strategies.push({
      type: 'name',
      find: async () => await this.page.$(`[name="${name}"]`)
    });
    return this;
  }
  
  /**
   * 查找元素（尝试所有策略）
   * @param {number} timeout - 超时时间（毫秒）
   * @returns {Promise<ElementHandle|null>}
   */
  async find(timeout = 10000) {
    const startTime = Date.now();
    
    while (Date.now() - startTime < timeout) {
      for (const strategy of this.strategies) {
        try {
          const element = await strategy.find();
          if (element && element.asElement && element.asElement()) {
            return element.asElement();
          }
          if (element) {
            return element;
          }
        } catch (error) {
          // 继续尝试下一个策略
          continue;
        }
      }
      
      // 等待一小段时间再重试
      await new Promise(resolve => setTimeout(resolve, 500));
    }
    
    return null;
  }
}

module.exports = SmartSelector;
