/* eslint-disable */
// Browser-Use 页面元素高亮脚本
// 完全基于 simple-hint-system.js 的实现

(function () {
  'use strict';

  // ==================== 常量定义 ====================
  const ClickType = {
    Default: 0,
    edit: 1,
    MaxNotWeak: 1,
    attrListener: 2,
    MinWeak: 2,
    codeListener: 3,
    classname: 4,
    tabindex: 5,
    MaxWeak: 5,
    MinNotWeak: 6,
    MaxNotBox: 6,
    frame: 7,
    scrollX: 8,
    scrollY: 9,
  };

  const kNode = {
    TEXT_NODE: 3,
    ELEMENT_NODE: 1,
    DOCUMENT_FRAGMENT_NODE: 11,
  };

  // Configuration
  const CONFIG = {
    HIGHLIGHT_Z_INDEX: 2147483646,
    CONTAINER_ID: 'browser-use-highlights',
    SHADOW_ROOT_ID: 'browser-use-shadow-root',
    HINT_CHARS: 'sadfjklewcmpgh',
    MAX_HINTS: 200,
  };

  // 默认hint字符
  const DEFAULT_HINT_CHARS = 'asdfghjklqwertyuiopzxcvbnm';

  // 可点击的角色
  const CLICKABLE_ROLES =
    /^(button|link|menuitem|tab|checkbox|radio|combobox|option|switch|slider|spinbutton|textbox|searchbox|progressbar|tooltip|banner|main|navigation|region|article|section|complementary|contentinfo|form|search|application|document|img|figure|math|tree|grid|table|listbox|list|group|presentation|none|directory|menu|menubar|toolbar|status|alert|alertdialog|dialog|log|marquee|timer|tabpanel|tablist|columnheader|rowheader|gridcell|separator|scrollbar)$/i;

  // 可点击的类名模式（基于插件的真实定义）
  const CLICKABLE_CLASSES = /(?:\b|_)(?:b(?:utto|t)n|close|hate|like)|B(?:utto|t)n|Close/;

  // 不可编辑的input类型
  const UNEDITABLE_INPUTS = {
    button: 1,
    checkbox: 1,
    color: 1,
    file: 1,
    hidden: 1,
    image: 1,
    radio: 1,
    range: 1,
    reset: 1,
    submit: 1,
  };

  // Global state
  let shadowRoot = null;
  let hintsContainer = null;
  let currentHints = [];
  let hintChars = CONFIG.HINT_CHARS;

  // ==================== 工具函数 ====================

  /**
   * 获取元素的边界矩形
   */
  function getBoundingRect(element) {
    const rect = element.getBoundingClientRect();
    return {
      l: rect.left,
      t: rect.top,
      r: rect.right,
      b: rect.bottom,
      w: rect.width,
      h: rect.height,
    };
  }

  /**
   * 检查元素是否可见
   */
  function isVisible(element) {
    if (!element || element.offsetParent === null) return false;

    const style = getComputedStyle(element);
    if (style.visibility === 'hidden' || style.display === 'none') return false;
    if (parseFloat(style.opacity) <= 0.1) return false;

    const rect = getBoundingRect(element);
    return rect.w > 0 && rect.h > 0;
  }

  /**
   * 检查矩形是否在视窗内
   */
  function isInViewport(rect) {
    return rect.l < window.innerWidth && rect.r > 0 && rect.t < window.innerHeight && rect.b > 0;
  }

  /**
   * 获取可见的客户端矩形
   */
  function getVisibleClientRect(element) {
    if (!isVisible(element)) return null;

    const rect = getBoundingRect(element);
    if (!isInViewport(rect)) return null;

    // 裁剪到视窗范围
    return {
      l: Math.max(0, rect.l),
      t: Math.max(0, rect.t),
      r: Math.min(window.innerWidth, rect.r),
      b: Math.min(window.innerHeight, rect.b),
    };
  }

  /**
   * 检查元素是否被其他元素遮挡
   * 基于Vimium C插件的逻辑
   */
  function isElementReachable(element, rect) {
    if (!rect) return false;

    const centerX = (rect.l + rect.r) / 2;
    const centerY = (rect.t + rect.b) / 2;

    const fromPoint = document.elementFromPoint(centerX, centerY);

    // 基于插件逻辑：排除 fromPoint.contains(el) 的情况
    // Chrome: !fromPoint || el === fromPoint || contains_s(el, fromPoint)
    return !fromPoint || element === fromPoint || element.contains(fromPoint);
  }

  // ==================== 元素检测逻辑 ====================

  /**
   * 检查链接元素的可点击性
   * 基于插件逻辑：所有可见的A标签都应该是可点击的
   */
  function checkAnchorClickable(element) {
    // 插件逻辑：A标签只需要可见即可，不需要href等其他条件
    return true;
  }

  /**
   * 检查表单元素的可点击性
   */
  function checkFormElementClickable(element) {
    const tag = element.tagName.toLowerCase();

    if (tag === 'input') {
      const type = element.type ? element.type.toLowerCase() : 'text';
      if (UNEDITABLE_INPUTS[type]) {
        return !element.disabled;
      }
      return !element.disabled && !element.readOnly;
    }

    if (tag === 'textarea') {
      return !element.disabled && !element.readOnly;
    }

    if (tag === 'select' || tag === 'button') {
      return !element.disabled;
    }

    return false;
  }

  /**
   * 检查元素的事件监听器（增强版）
   */
  function hasEventListeners(element) {
    // 检查内联事件
    if (element.onclick || element.onmousedown || element.onmouseup) return true;

    // 检查属性事件
    const attrs = ['onclick', 'onmousedown', 'onmouseup', 'onmouseover'];
    for (const attr of attrs) {
      if (element.getAttribute(attr)) return true;
    }

    // 检查Angular和其他框架
    if (element.getAttribute('ng-click')) return true;
    if (element.getAttribute('v-on:click') || element.getAttribute('@click')) return true;

    // 检查JSAction
    const jsaction = element.getAttribute('jsaction');
    if (jsaction && jsaction.includes('click')) return true;

    return false;
  }

  /**
   * 检测通过JavaScript添加的事件监听器
   * 这是一个启发式方法，模拟插件的clickable_检测
   */
  function hasCodeEventListeners(element) {
    const tag = element.tagName.toLowerCase();

    // 排除装饰性元素，除非有明确的交互性指示
    if (tag === 'svg' || tag === 'use' || tag === 'path') {
      // SVG元素只有在有明确的cursor或事件属性时才认为是可点击的
      const style = getComputedStyle(element);
      return style.cursor === 'pointer' && element.onclick;
    }

    // 检查常见的交互性指示器
    const style = getComputedStyle(element);

    // 检查cursor样式
    if (style.cursor === 'pointer') return true;

    // 检查CSS类名中的交互性暗示
    const className = element.className;
    const classNameStr = typeof className === 'string' ? className : className.toString();
    if (
      classNameStr &&
      (classNameStr.includes('click') ||
        classNameStr.includes('btn') ||
        classNameStr.includes('button') ||
        classNameStr.includes('interactive') ||
        classNameStr.includes('action') ||
        classNameStr.includes('link'))
    ) {
      return true;
    }

    // 检查data属性
    if (element.dataset) {
      for (const key in element.dataset) {
        const value = element.dataset[key];
        if (
          key.includes('click') ||
          key.includes('action') ||
          (value && (value.includes('click') || value.includes('action')))
        ) {
          return true;
        }
      }
    }

    // 检查ID和类名的模式
    const idName = element.id || '';
    if (
      idName.includes('btn') ||
      idName.includes('button') ||
      idName.includes('click') ||
      idName.includes('action')
    ) {
      return true;
    }

    return false;
  }

  /**
   * 检查ARIA和角色属性
   */
  function checkAriaClickable(element) {
    const role = element.getAttribute('role');
    if (role && CLICKABLE_ROLES.test(role)) return true;

    const tabindex = element.getAttribute('tabindex');
    if (tabindex && parseInt(tabindex, 10) >= 0) return true;

    if (element.getAttribute('aria-selected') !== null) return true;
    if (element.getAttribute('data-tab') !== null) return true;

    return false;
  }

  /**
   * 检查CSS类名（增强版本）
   */
  function checkClickableClasses(element) {
    const className = element.className;
    const id = element.id;

    // 将className转换为字符串
    const classNameStr = typeof className === 'string' ? className : className.toString();

    // 检查类名
    if (classNameStr && CLICKABLE_CLASSES.test(classNameStr)) {
      return true;
    }

    // 检查ID
    if (typeof id === 'string' && CLICKABLE_CLASSES.test(id)) {
      return true;
    }

    // 检查data属性
    if (element.dataset) {
      for (const key in element.dataset) {
        if (CLICKABLE_CLASSES.test(key) || CLICKABLE_CLASSES.test(element.dataset[key])) {
          return true;
        }
      }
    }

    return false;
  }

  /**
   * 检查是否可滚动
   */
  function checkScrollable(element) {
    const style = getComputedStyle(element);
    const overflow = style.overflow + style.overflowX + style.overflowY;

    if (!overflow.includes('scroll') && !overflow.includes('auto')) return false;

    const scrollHeight = element.scrollHeight;
    const scrollWidth = element.scrollWidth;
    const clientHeight = element.clientHeight;
    const clientWidth = element.clientWidth;

    if (scrollHeight > clientHeight + 5) return ClickType.scrollY;
    if (scrollWidth > clientWidth + 5) return ClickType.scrollX;

    return false;
  }

  /**
   * 获取点击类型的中文名称
   */
  function getClickTypeName(type) {
    const typeNames = {
      [ClickType.Default]: '默认可点击',
      [ClickType.edit]: '可编辑',
      [ClickType.attrListener]: '事件监听器',
      [ClickType.codeListener]: '代码监听器',
      [ClickType.classname]: 'CSS类名',
      [ClickType.tabindex]: 'ARIA/tabindex',
      [ClickType.frame]: '框架',
      [ClickType.scrollX]: '水平滚动',
      [ClickType.scrollY]: '垂直滚动',
    };
    return typeNames[type] || '未知';
  }

  /**
   * 判断元素的可点击类型并返回详细信息
   */
  function getClickTypeWithReason(element) {
    const tag = element.tagName.toLowerCase();
    let markingReason = '';

    // 直接可点击的元素
    switch (tag) {
      case 'a':
        if (checkAnchorClickable(element)) {
          markingReason = '链接元素(a标签)';
          return { type: ClickType.Default, reason: markingReason };
        }
        return { type: false, reason: '' };
      case 'button':
        if (checkFormElementClickable(element)) {
          markingReason = '按钮元素(button标签)';
          return { type: ClickType.Default, reason: markingReason };
        }
        return { type: false, reason: '' };
      case 'select':
        if (checkFormElementClickable(element)) {
          markingReason = '选择框元素(select标签)';
          return { type: ClickType.Default, reason: markingReason };
        }
        return { type: false, reason: '' };
      case 'input':
        if (checkFormElementClickable(element)) {
          const inputType = element.type ? element.type.toLowerCase() : 'text';
          if (UNEDITABLE_INPUTS[inputType]) {
            markingReason = `输入元素(input type=${inputType})`;
            return { type: ClickType.Default, reason: markingReason };
          } else {
            markingReason = `可编辑输入框(input type=${inputType})`;
            return { type: ClickType.edit, reason: markingReason };
          }
        }
        return { type: false, reason: '' };
      case 'textarea':
        if (checkFormElementClickable(element)) {
          markingReason = '文本区域(textarea标签)';
          return { type: ClickType.edit, reason: markingReason };
        }
        return { type: false, reason: '' };
      case 'details':
        markingReason = '详情元素(details标签)';
        return { type: ClickType.Default, reason: markingReason };
      case 'audio':
        markingReason = '音频元素(audio标签)';
        return { type: ClickType.Default, reason: markingReason };
      case 'video':
        markingReason = '视频元素(video标签)';
        return { type: ClickType.Default, reason: markingReason };
      case 'iframe':
        markingReason = '内联框架(iframe标签)';
        return { type: ClickType.frame, reason: markingReason };
      case 'frame':
        markingReason = '框架(frame标签)';
        return { type: ClickType.frame, reason: markingReason };
      case 'img':
        // 检查图片的 useMap 属性
        if (element.useMap) {
          markingReason = `图片映射元素(useMap)`;
          return { type: ClickType.Default, reason: markingReason };
        }

        // 更严格的图片cursor检测 - 只在非hover模式或非a标签内时检测
        const parentElement = element.parentElement;
        const inAnchor = parentElement && parentElement.tagName.toLowerCase() === 'a';

        // 如果图片在A标签内，让A标签处理，不单独标记图片
        if (inAnchor) {
          return { type: false, reason: '' };
        }

        // 只有具有特殊cursor的图片才标记
        const cursor = element.style.cursor || getComputedStyle(element).cursor;
        if (
          cursor &&
          cursor !== 'default' &&
          (cursor.includes('zoom') || cursor.startsWith('url') || cursor === 'pointer')
        ) {
          markingReason = `可点击图片元素(cursor=${cursor})`;
          return { type: ClickType.Default, reason: markingReason };
        }

        // 默认情况下不标记普通图片
        return { type: false, reason: '' };
    }

    // 检查可编辑内容
    const contentEditable = element.getAttribute('contenteditable');
    if (contentEditable === 'true' || contentEditable === '') {
      markingReason = '内容可编辑(contentEditable)';
      return { type: ClickType.edit, reason: markingReason };
    }

    // 检查事件监听器
    if (hasEventListeners(element)) {
      if (element.onclick || element.onmousedown || element.onmouseup) {
        markingReason = '有内联事件监听器';
      } else if (
        element.getAttribute('onclick') ||
        element.getAttribute('onmousedown') ||
        element.getAttribute('onmouseup')
      ) {
        markingReason = '有onclick/onmousedown/onmouseup属性';
      } else if (element.getAttribute('ng-click')) {
        markingReason = '有Angular ng-click指令';
      } else if (element.getAttribute('v-on:click') || element.getAttribute('@click')) {
        markingReason = '有Vue点击事件监听器';
      } else if (element.getAttribute('jsaction')) {
        markingReason = '有JSAction事件监听器';
      } else {
        markingReason = '有其他事件监听器';
      }
      return { type: ClickType.attrListener, reason: markingReason };
    }

    // 检查代码事件监听器（模拟插件的clickable_检测）
    if (hasCodeEventListeners(element)) {
      markingReason = '检测到代码事件监听器或交互性指示器';
      return { type: ClickType.codeListener, reason: markingReason };
    }

    // 检查ARIA属性
    if (checkAriaClickable(element)) {
      const role = element.getAttribute('role');
      const tabindex = element.getAttribute('tabindex');
      if (role && CLICKABLE_ROLES.test(role)) {
        markingReason = `ARIA角色(role=${role})`;
      } else if (tabindex && parseInt(tabindex, 10) >= 0) {
        markingReason = `可聚焦元素(tabindex=${tabindex})`;
      } else if (element.getAttribute('aria-selected') !== null) {
        markingReason = '有aria-selected属性';
      } else if (element.getAttribute('data-tab') !== null) {
        markingReason = '有data-tab属性';
      } else {
        markingReason = '其他ARIA可点击属性';
      }
      return { type: ClickType.tabindex, reason: markingReason };
    }

    // 检查CSS类名和li元素特殊逻辑（基于插件实现）
    const hasClickableClass = checkClickableClasses(element);
    const isLiElement = tag === 'li';

    if (hasClickableClass || isLiElement) {
      // 基于插件逻辑：检查父元素条件
      const parentElement = element.parentElement;
      const shouldMark = hasClickableClass
        ? !parentElement ||
          (parentElement.tagName.toLowerCase() !== 'button' &&
            parentElement.tagName.toLowerCase() !== 'a')
        : parentElement &&
          parentElement.tagName.toLowerCase() === 'ul' &&
          !element.className.includes('active');

      if (shouldMark) {
        markingReason = hasClickableClass ? '可点击CSS类名' : 'li元素在ul中';
        return { type: ClickType.classname, reason: markingReason };
      }
    }

    // 检查滚动
    const scrollType = checkScrollable(element);
    if (scrollType) {
      if (scrollType === ClickType.scrollY) {
        markingReason = '可垂直滚动';
      } else if (scrollType === ClickType.scrollX) {
        markingReason = '可水平滚动';
      }
      return { type: scrollType, reason: markingReason };
    }

    return { type: false, reason: '' };
  }

  /**
   * 基于插件的去重逻辑（deduplicate）
   */
  function deduplicate(hints) {
    const list = hints.slice(); // 复制数组
    let i = list.length;
    let j = 0;
    let k, s, notRemoveParents;
    let element,
      prect,
      crect,
      splice = 0;

    // 先移除不可滚动的滚动元素
    for (j = 0; j < i; ) {
      k = list[j].type;
      if (k > ClickType.scrollY - 1) {
        // 简化的滚动检查，如果元素不应该被滚动则移除
        if (!shouldScrollElement(list[j].element, k - ClickType.scrollX)) {
          list.splice(j, 1);
          i--;
        } else {
          j++;
        }
      } else {
        j++;
      }
    }

    // 更精确的父子元素去重逻辑
    for (let parentIdx = 0; parentIdx < list.length; parentIdx++) {
      const parentHint = list[parentIdx];
      const parentElement = parentHint.element;
      const parentType = parentHint.type;
      const parentTag = parentElement.tagName.toLowerCase();

      // 移除强元素内的弱子元素，以及同类型父子元素的去重
      if (parentType <= ClickType.MaxNotWeak || parentType === ClickType.codeListener) {
        for (let childIdx = list.length - 1; childIdx > parentIdx; childIdx--) {
          const childHint = list[childIdx];
          const childElement = childHint.element;
          const childType = childHint.type;
          const childTag = childElement.tagName.toLowerCase();

          if (parentElement.contains(childElement)) {
            let shouldRemove = false;

            // 移除A标签内的IMG元素（除非img有特殊点击行为）
            if (parentTag === 'a' && childTag === 'img' && childType !== ClickType.Default) {
              shouldRemove = true;
            }
            // 移除强元素内的弱子元素
            else if (childType > ClickType.MaxNotWeak) {
              shouldRemove = true;
            }
            // 移除可点击元素内的SVG、USE等装饰性元素
            else if (
              (childTag === 'svg' || childTag === 'use' || childTag === 'path') &&
              (parentType <= ClickType.MaxNotWeak || parentType === ClickType.codeListener)
            ) {
              shouldRemove = true;
            }
            // 移除codeListener父元素内的codeListener子元素（去重同类型）
            else if (
              parentType === ClickType.codeListener &&
              childType === ClickType.codeListener
            ) {
              shouldRemove = true;
            }
            // 移除可点击元素内的SPAN、DIV等纯文本容器（扩展条件）
            else if (
              (childTag === 'span' || childTag === 'div') &&
              (parentType <= ClickType.MaxNotWeak || parentType === ClickType.codeListener) &&
              childType === ClickType.codeListener
            ) {
              shouldRemove = true;
            }
            // 移除LI内的A元素（保留LI，去除重复的A）
            else if (
              parentTag === 'li' &&
              childTag === 'a' &&
              parentType === ClickType.classname &&
              childType <= ClickType.MaxNotWeak
            ) {
              shouldRemove = true;
            }
            // 移除布局容器DIV内的实际可点击元素
            else if (
              parentTag === 'div' &&
              parentType === ClickType.classname &&
              childType <= ClickType.MaxNotWeak &&
              (childTag === 'a' || childTag === 'button')
            ) {
              // 如果DIV只是布局容器，移除DIV而保留子元素
              list.splice(parentIdx, 1);
              parentIdx--; // 调整索引
              break;
            }

            if (shouldRemove) {
              list.splice(childIdx, 1);
            }
          }
        }
      }
    }

    // 重新设置i变量为列表长度
    i = list.length;

    // 主要的去重逻辑
    while (0 <= --i) {
      k = list[i].type;
      notRemoveParents = k === ClickType.classname;

      if (k === ClickType.codeListener) {
        s = list[i].element.tagName.toLowerCase();
        if (s === 'i' || s === 'div') {
          if (i > 0 && /^(button|a)$/.test(list[i - 1].element.tagName.toLowerCase())) {
            if (
              (s < 'i' || !list[i].element.firstChild) &&
              isDescendant(list[i].element, list[i - 1].element, +(s < 'i'))
            ) {
              splice = 1;
            }
          } else {
            element = list[i].element.parentElement;
            if (element && element.tagName.toLowerCase() === 'button' && element.disabled) {
              splice = 1;
            }
          }
        }

        if (s[0] === 'h' && /^h\d$/.test(s)) {
          if (
            i > 0 &&
            (k = list[i - 1].type) < ClickType.MinNotWeak + 1 &&
            k !== ClickType.edit &&
            (element = list[i - 1].element).childElementCount === 1 &&
            getComputedStyle(element).display === 'inline' &&
            isDescendant(list[i].element, element, 0)
          ) {
            splice = i;
            i--;
          }
        } else if (s === 'div' && !splice && (j = i + 1) < list.length) {
          s = list[j].element.tagName.toLowerCase();
          if (s === 'div' || s === 'a') {
            prect = list[i].rect;
            crect = list[j].rect;
            if (
              crect.l < prect.l + 19 &&
              crect.t < prect.t + 9 &&
              crect.l > prect.l - 4 &&
              crect.t > prect.t - 4 &&
              crect.b > prect.b - 9 &&
              (s !== 'a' || list[i].element.contains(list[j].element))
            ) {
              splice = 1;
            }
          }
        }
      } else if (
        k === ClickType.tabindex &&
        (element = list[i].element).childElementCount === 1 &&
        i + 1 < list.length
      ) {
        element = element.firstElementChild;
        prect = list[i].rect;
        crect = getVisibleClientRect(element);
        if (crect && isContaining(crect, prect)) {
          if (list[i + 1].element.parentNode !== element) {
            list[i] = {
              element: element,
              rect: crect,
              type: ClickType.tabindex,
              reason: list[i].reason,
            };
          } else if (list[i + 1].type === ClickType.codeListener) {
            splice = 1;
          }
        }
      } else if (notRemoveParents) {
        if (
          i + 1 < list.length &&
          list[(j = i + 1)].type < ClickType.MinWeak &&
          isDescendant((element = list[j].element), list[i].element, 0) &&
          (list[j].type > ClickType.edit - 1 || /^(button|a)$/.test(element.tagName.toLowerCase()))
        ) {
          splice = 1;
        }
      } else {
        notRemoveParents =
          k === ClickType.edit &&
          i > 0 &&
          (element = list[i - 1].element) === list[i].element.parentNode &&
          element.childElementCount < 2 &&
          element.tagName.toLowerCase() === 'a' &&
          !element.innerText;
        if (notRemoveParents) {
          splice = i;
          i--;
        }
      }

      if (splice) {
        list.splice(i, 1);
        splice = 0;
      }

      if (notRemoveParents) {
        continue;
      }

      // 移除其他弱类型的祖先元素
      for (j = i; j > i - 3 && 0 < j; j--) {
        k = list[j - 1].type;
        if (
          k > ClickType.MaxNotWeak &&
          k < ClickType.MinNotWeak &&
          isDescendant(list[j].element, list[j - 1].element, 1)
        ) {
          // 继续循环
        } else {
          break;
        }
      }
      if (j < i) {
        list.splice(j, i - j);
        i = j;
      }
    }

    return list;
  }

  /**
   * 检查元素是否应该滚动
   */
  function shouldScrollElement(element, direction) {
    // 简化的滚动检查逻辑
    if (direction === 0) {
      // scrollY
      return element.scrollHeight > element.clientHeight + 5;
    } else {
      // scrollX
      return element.scrollWidth > element.clientWidth + 5;
    }
  }

  /**
   * 检查一个矩形是否包含另一个矩形
   */
  function isContaining(outer, inner) {
    return outer.l <= inner.l && outer.t <= inner.t && outer.r >= inner.r && outer.b >= inner.b;
  }

  /**
   * 检查是否为后代元素
   */
  function isDescendant(child, parent, shouldBeSingleChild) {
    let i = 3;
    let c = child;

    while (0 < i-- && c !== null && (c = c.parentElement) !== null && c !== parent) {
      // 继续向上查找
    }

    if (
      c !== parent ||
      shouldBeSingleChild === 0 ||
      /^(button|a)$/.test(parent.tagName.toLowerCase())
    ) {
      return c === parent;
    }

    // 检查是否为单子元素
    for (i = 0; c.childElementCount === 1 && i < 3; i++) {
      const firstChild = c.firstChild;
      if (firstChild && firstChild.nodeType === 3 && firstChild.textContent.trim()) {
        break;
      }
      c = c.firstElementChild;
    }

    return i > 2;
  }

  /**
   * 过滤不可达的元素（基于插件的filterOutNonReachable逻辑）
   */
  function filterOutNonReachable(hints) {
    const filteredHints = [];

    for (let i = 0; i < hints.length; i++) {
      const hint = hints[i];
      const element = hint.element;
      const rect = hint.rect;

      // 计算元素中心点
      const centerX = (rect.l + rect.r) / 2;
      const centerY = (rect.t + rect.b) / 2;

      // 使用elementFromPoint检测元素是否可达
      const fromPoint = document.elementFromPoint(centerX, centerY);

      // 基于插件的does_hit逻辑
      const isReachable = !fromPoint || element === fromPoint || element.contains(fromPoint);

      if (isReachable) {
        filteredHints.push(hint);
      }
    }

    return filteredHints;
  }

  /**
   * 遍历DOM树收集可点击元素
   * 使用类似Vimium C插件的方式：querySelectorAll + 逐一检测
   * @param {Document|ShadowRoot} root - 要遍历的根节点
   * @param {number} depth - 当前递归深度，用于防止栈溢出
   */
  function collectClickableElements(root = document, depth = 0) {
    const hints = [];
    const MAX_DEPTH = 10; // 最大递归深度

    // 防止递归过深导致栈溢出
    if (depth > MAX_DEPTH) {
      console.warn(`⚠️ Shadow DOM 递归深度超过限制 (${MAX_DEPTH})，停止遍历`);
      return hints;
    }

    // 使用与插件相同的选择器逻辑：选择除form外的所有元素
    const selector = ':not(form)';
    let elements;

    try {
      elements = root.querySelectorAll(selector);
    } catch (e) {
      // 降级到所有元素
      elements = root.querySelectorAll('*');
    }

    for (const node of elements) {
      // 跳过script、style等元素
      const tag = node.tagName.toLowerCase();
      if (['script', 'style', 'meta', 'title', 'head'].includes(tag)) {
        continue;
      }

      const result = getClickTypeWithReason(node);
      if (result.type !== false) {
        const rect = getVisibleClientRect(node);
        if (rect) {
          // 类似插件，先收集所有可能的元素，后续再过滤
          hints.push({
            element: node,
            rect: rect,
            type: result.type,
            reason: result.reason,
          });
        }
      }
    }

    // 处理Shadow DOM - 从已遍历的元素中查找 shadow hosts
    // 避免重复查询和无限递归
    for (const host of elements) {
      // 跳过脚本自己创建的容器，避免递归到高亮标记中
      if (host.id === CONFIG.SHADOW_ROOT_ID || host.id === CONFIG.CONTAINER_ID) {
        continue;
      }

      if (host.shadowRoot) {
        // 递归处理 Shadow DOM，传入递增的深度参数
        const shadowHints = collectClickableElements(host.shadowRoot, depth + 1);
        hints.push(...shadowHints);
      }
    }

    // 应用插件风格的去重和过滤
    let filteredHints = deduplicate(hints);
    filteredHints = filterOutNonReachable(filteredHints);

    return filteredHints;
  }

  // ==================== 样式和渲染 ====================

  // CSS样式
  const HINT_STYLES = `
    .vimium-hint-container {
      position: fixed !important;
      pointer-events: none !important;
      z-index: 2147483647 !important;
    }
    
    .vimium-hint-overlay {
      position: fixed !important;
      pointer-events: none !important;
      box-sizing: border-box !important;
      z-index: 2147483647 !important;
    }
    
    .vimium-hint-label {
      position: fixed !important;
      font-family: Arial, sans-serif !important;
      font-weight: bold !important;
      text-align: center !important;
      line-height: 1 !important;
      text-shadow: none !important;
      text-decoration: none !important;
      pointer-events: none !important;
      z-index: 2147483648 !important;
      border: none !important;
      outline: none !important;
      display: inline-block !important;
    }
  `;

  // Create and setup shadow DOM for style isolation
  function createShadowContainer() {
    if (shadowRoot) return shadowRoot;

    const container = document.createElement('div');
    container.id = CONFIG.SHADOW_ROOT_ID;
    container.style.cssText = `
      position: fixed !important;
      top: 0 !important;
      left: 0 !important;
      width: 0 !important;
      height: 0 !important;
      z-index: ${CONFIG.HIGHLIGHT_Z_INDEX} !important;
      pointer-events: none !important;
      overflow: visible !important;
    `;

    try {
      shadowRoot = container.attachShadow({ mode: 'closed' });

      // Add CSS styles to shadow DOM
      const style = document.createElement('style');
      style.textContent = HINT_STYLES;
      shadowRoot.appendChild(style);

      document.documentElement.appendChild(container);
      return shadowRoot;
    } catch (e) {
      console.warn('Failed to create shadow DOM, falling back to regular DOM:', e);
      // Fallback to regular DOM
      shadowRoot = container;
      const style = document.createElement('style');
      style.textContent = HINT_STYLES;
      document.head.appendChild(style);
      document.documentElement.appendChild(container);
      return shadowRoot;
    }
  }

  // Generate hint text using incremental numbers
  function generateHintText(index, totalHints) {
    // 使用自增数字标记（从1开始）
    return String(index + 1);
  }

  // Create hint marker with enhanced styling from simple-hint-system
  function createHintMarker(hint, hintText, index) {
    // 创建容器div
    const container = document.createElement('div');
    container.className = 'vimium-hint-container';

    // 定义颜色数组
    const colors = [
      '#FF0000',
      '#00FF00',
      '#0000FF',
      '#FFA500',
      '#800080',
      '#008080',
      '#FF69B4',
      '#4B0082',
      '#FF4500',
      '#2E8B57',
      '#DC143C',
      '#4682B4',
    ];
    const colorIndex = index % colors.length;
    const baseColor = colors[colorIndex];
    const backgroundColor = baseColor + '1A'; // 10% opacity version

    // 创建高亮覆盖层
    const overlay = document.createElement('div');
    overlay.className = 'vimium-hint-overlay';
    Object.assign(overlay.style, {
      position: 'fixed',
      left: hint.rect.l + 'px',
      top: hint.rect.t + 'px',
      width: hint.rect.r - hint.rect.l + 'px',
      height: hint.rect.b - hint.rect.t + 'px',
      border: `2px solid ${baseColor}`,
      backgroundColor: backgroundColor,
      pointerEvents: 'none',
      boxSizing: 'border-box',
      zIndex: '2147483647',
    });

    // 创建标签
    const label = document.createElement('div');
    label.className = 'vimium-hint-label';
    label.textContent = hintText;

    const rect = hint.rect;
    // 标签的宽度计算
    const labelWidth = Math.max(18, hintText.length * 6 + 12);
    const labelHeight = 16;

    // 计算标签位置
    let labelTop = hint.rect.t + 2;
    let labelLeft = hint.rect.l + 2;

    // 如果元素太小，将标签放在外面
    if (rect.r - rect.l < labelWidth + 4 || rect.b - rect.t < labelHeight + 4) {
      labelTop = hint.rect.t - labelHeight - 2;
      labelLeft = hint.rect.l;
    }

    // 确保标签不会超出视窗边界
    if (labelLeft + labelWidth > window.innerWidth) {
      labelLeft = window.innerWidth - labelWidth - 2;
    }
    if (labelTop < 0) {
      labelTop = hint.rect.t + 2;
    }

    Object.assign(label.style, {
      position: 'fixed',
      top: labelTop + 'px',
      left: labelLeft + 'px',
      background: baseColor,
      color: 'white',
      padding: '2px 6px',
      borderRadius: '4px',
      fontSize: Math.min(14, Math.max(10, (rect.b - rect.t) / 2)) + 'px',
      fontFamily: 'Arial, sans-serif',
      fontWeight: 'bold',
      textAlign: 'center',
      lineHeight: '1',
      textShadow: 'none',
      zIndex: '2147483646',
      pointerEvents: 'none',
      minWidth: '18px',
    });

    // 根据类型调整颜色
    if (hint.type === ClickType.edit) {
      overlay.style.borderColor = '#00AA00';
      overlay.style.backgroundColor = '#00AA001A';
      label.style.background = '#00AA00';
    } else if (hint.type === ClickType.frame) {
      overlay.style.borderColor = '#FF6600';
      overlay.style.backgroundColor = '#FF66001A';
      label.style.background = '#FF6600';
    }

    container.appendChild(overlay);
    container.appendChild(label);

    return {
      marker: container,
      element: hint.element,
      text: hintText,
      rect: hint.rect,
    };
  }

  // ==================== 元素数据提取辅助函数 ====================

  /**
   * 提取元素的可序列化属性
   */
  function extractElementAttributes(element) {
    const attrs = {};

    if (element.id) attrs.id = element.id;
    if (element.className) {
      const className =
        typeof element.className === 'string' ? element.className : element.className.baseVal || '';
      if (className) attrs.class = className;
    }
    if (element.href) attrs.href = element.href;
    if (element.type) attrs.type = element.type;
    if (element.name) attrs.name = element.name;
    if (element.placeholder) attrs.placeholder = element.placeholder;

    const ariaLabel = element.getAttribute('aria-label');
    if (ariaLabel) attrs.ariaLabel = ariaLabel;

    return Object.keys(attrs).length > 0 ? attrs : undefined;
  }

  /**
   * 获取元素的文本内容（截取前100字符）
   */
  function getElementText(element) {
    const text = element.innerText || element.textContent || '';
    return text.trim().substring(0, 100);
  }

  /**
   * 生成元素的 CSS 选择器
   */
  function generateElementSelector(element) {
    // 优先使用 ID
    if (element.id) {
      return `#${element.id}`;
    }

    // 构建路径选择器
    const path = [];
    let current = element;

    while (current && current !== document.body && path.length < 5) {
      let selector = current.tagName.toLowerCase();

      // 添加类名（取第一个）
      if (current.className) {
        const className =
          typeof current.className === 'string'
            ? current.className.split(' ')[0]
            : current.className.baseVal?.split(' ')[0];
        if (className) {
          selector += `.${className}`;
        }
      }

      // 添加 nth-child（如果有兄弟节点）
      if (current.parentElement) {
        const siblings = Array.from(current.parentElement.children);
        const index = siblings.indexOf(current) + 1;
        if (siblings.length > 1) {
          selector += `:nth-child(${index})`;
        }
      }

      path.unshift(selector);
      current = current.parentElement;
    }

    return path.join(' > ');
  }

  // Remove all existing highlighting elements
  function removeHighlights() {
    console.log('🧹 Removing browser-use highlighting elements');

    // Remove shadow root container
    const shadowContainer = document.getElementById(CONFIG.SHADOW_ROOT_ID);
    if (shadowContainer) {
      shadowContainer.remove();
    }

    // Cleanup global state
    shadowRoot = null;
    hintsContainer = null;
    currentHints = [];
  }

  // Main highlighting function - 完全基于simple-hint-system的实现
  function highlightElements(selector = null) {
    console.log('=== BROWSER-USE HIGHLIGHTING SYSTEM ===');
    console.log('🚀 基于Simple-Hint-System的完整实现');

    // Remove existing highlights
    removeHighlights();

    try {
      const startTime = performance.now();

      // 收集可点击元素 - 使用simple-hint-system的完整逻辑
      console.log('🔍 开始检测可点击元素...');
      const clickableElements = selector
        ? Array.from(document.querySelectorAll(selector))
            .map((el) => {
              const result = getClickTypeWithReason(el);
              const rect = getVisibleClientRect(el);
              if (result.type !== false && rect) {
                return { element: el, rect, type: result.type, reason: result.reason };
              }
              return null;
            })
            .filter((item) => item !== null)
        : collectClickableElements();

      const endTime = performance.now();
      console.log(`⏱️ 检测耗时 ${(endTime - startTime).toFixed(2)}ms`);

      if (clickableElements.length === 0) {
        console.log('⚠️ 未找到可点击元素');
        return Promise.resolve([]);
      }

      console.log(`🎯 发现 ${clickableElements.length} 个可点击元素`);

      // 显示详细元素信息（参考simple-hint-system）
      if (clickableElements.length > 0) {
        console.log('📝 检测到的元素详情:');
        for (let i = 0; i < Math.min(10, clickableElements.length); i++) {
          const item = clickableElements[i];
          const elem = item.element;
          const typeNames = getClickTypeName(item.type);

          const classStr =
            typeof elem.className === 'string' ? elem.className : elem.className?.baseVal || '';
          const className = classStr ? `.${classStr.split(' ')[0]}` : '';

          console.log(
            `  ${i + 1}. <${elem.tagName.toLowerCase()}> ${className} ${elem.id ? `#${elem.id}` : ''} [${typeNames}]`,
          );
        }
      }

      // Create shadow container
      const shadowContainer = createShadowContainer();

      // Create hints container
      hintsContainer = document.createElement('div');
      hintsContainer.className = 'vimium-hint-container';

      // Generate hints
      currentHints = [];
      for (let i = 0; i < clickableElements.length; i++) {
        const hintText = generateHintText(i, clickableElements.length);
        const hint = createHintMarker(clickableElements[i], hintText, i);

        hintsContainer.appendChild(hint.marker);
        currentHints.push(hint);
      }

      // Add to shadow DOM or fallback container
      if (shadowContainer.shadowRoot) {
        shadowContainer.shadowRoot.appendChild(hintsContainer);
      } else {
        shadowContainer.appendChild(hintsContainer);
      }

      console.log(`✅ 成功创建 ${currentHints.length} 个高亮标记`);

      // Return hint information with detailed element data
      return Promise.resolve(
        currentHints.map((hint, index) => {
          const clickableElement = clickableElements[index];
          const rect = hint.rect;

          return {
            index: generateHintText(index, clickableElements.length),
            tag: hint.element.tagName,
            type: clickableElement.reason || 'Unknown',
            rect: {
              left: rect.l,
              top: rect.t,
              right: rect.r,
              bottom: rect.b,
              width: rect.r - rect.l,
              height: rect.b - rect.t,
            },
            attributes: extractElementAttributes(hint.element),
            text: getElementText(hint.element),
            selector: generateElementSelector(hint.element),
          };
        }),
      );
    } catch (error) {
      console.error('❌ 高亮实现出错:', error);
      return Promise.resolve([]);
    }
  }

  // Check if highlighting is active
  function isHighlighted() {
    return !!document.getElementById(CONFIG.SHADOW_ROOT_ID);
  }

  // Get highlighting statistics
  function getStats() {
    return {
      hintsCount: currentHints.length,
      isActive: isHighlighted(),
      hintChars: hintChars,
      config: CONFIG,
    };
  }

  // Export API to global scope
  window.browserUseHighlighter = {
    highlight: highlightElements,
    remove: removeHighlights,
    isHighlighted: isHighlighted,
    getStats: getStats,
    setHintChars: (chars) => {
      hintChars = chars || CONFIG.HINT_CHARS;
    },
    config: CONFIG,
  };

  // Chrome extension message listener
  if (typeof chrome !== 'undefined' && chrome.runtime && chrome.runtime.onMessage) {
    chrome.runtime.onMessage.addListener((request, _sender, sendResponse) => {
      if (request.action === 'HIGHLIGHT_ELEMENTS') {
        console.log('🎯 Received HIGHLIGHT_ELEMENTS message:', request);

        // Set custom hint characters if provided
        if (request.hintChars) {
          hintChars = request.hintChars;
        }

        highlightElements(request.selector)
          .then((result) => {
            sendResponse({
              success: true,
              highlightedElements: result || [],
              stats: getStats(),
            });
          })
          .catch((error) => {
            console.error('Error highlighting elements:', error);
            sendResponse({
              success: false,
              error: error.message,
            });
          });

        return true; // Indicates we will send a response asynchronously
      }

      if (request.action === 'REMOVE_HIGHLIGHTS') {
        console.log('🧹 Received REMOVE_HIGHLIGHTS message');

        try {
          removeHighlights();
          sendResponse({
            success: true,
            stats: getStats(),
          });
        } catch (error) {
          console.error('Error removing highlights:', error);
          sendResponse({
            success: false,
            error: error.message,
          });
        }

        return true;
      }

      if (request.action === 'GET_STATS') {
        sendResponse({
          success: true,
          stats: getStats(),
        });
        return true;
      }
    });
  }

  // Initialize and log readiness
  console.log('🚀 Browser-Use Highlighter loaded (基于Simple-Hint-System)');
  console.log('📋 Available methods:', Object.keys(window.browserUseHighlighter));

  // Cleanup on page unload
  window.addEventListener('beforeunload', removeHighlights);
})();
