/* eslint-disable */
/**
 * Scroll helper script for handling scroll operations
 * This script is injected into web pages to perform scroll actions
 */

(() => {
  'use strict';

  // Prevent multiple injections
  if (window.scrollHelperInjected) {
    return;
  }
  window.scrollHelperInjected = true;

  console.log('Scroll helper script injected');

  /**
   * 超时 Promise 辅助函数
   */
  function withTimeout(promise, timeoutMs) {
    return Promise.race([
      promise,
      new Promise((_, reject) => {
        setTimeout(() => {
          reject(new Error(`操作超时 (${timeoutMs}ms)`));
        }, timeoutMs);
      }),
    ]);
  }

  /**
   * 判断一个元素在指定方向上是否可以滚动
   */
  async function isScrollableInDirection(el, direction) {
    if (!el) return false;

    // 根据方向判断需要检查的溢出类型
    const isVertical = direction === 'up' || direction === 'down';
    const isHorizontal = direction === 'left' || direction === 'right';

    // 检查相应方向的内容溢出
    const hasVerticalOverflow = el.scrollHeight > el.clientHeight;
    const hasHorizontalOverflow = el.scrollWidth > el.clientWidth;

    let hasRelevantOverflow = false;
    if (isVertical && hasVerticalOverflow) {
      hasRelevantOverflow = true;
    } else if (isHorizontal && hasHorizontalOverflow) {
      hasRelevantOverflow = true;
    }

    if (!hasRelevantOverflow) {
      console.log(`${direction} 方向没有内容溢出，不可滚动`);
      return false;
    }

    // 检查 CSS overflow 属性
    const style = window.getComputedStyle(el);
    const overflowX = style.overflowX;
    const overflowY = style.overflowY;

    console.log(`${direction} 方向 CSS overflow:`, isVertical ? overflowY : overflowX);

    // 检查相应方向的 CSS 设置
    const relevantOverflow = isVertical ? overflowY : overflowX;

    // 如果明确设置了不可滚动
    if (relevantOverflow === 'hidden' || relevantOverflow === 'visible') {
      console.log(`${direction} 方向 CSS 设置为不可滚动`);
      return false;
    }

    // 如果设置了可滚动样式且有内容溢出，则认为可滚动
    if ((relevantOverflow === 'auto' || relevantOverflow === 'scroll') && hasRelevantOverflow) {
      console.log(`${direction} 方向 CSS 设置为可滚动且有内容溢出，判断为可滚动`);
      return true;
    }

    // 对于其他情况（如inherit等），使用异步实际测试
    return new Promise((resolve) => {
      requestAnimationFrame(() => {
        try {
          console.log(`${direction} 方向使用异步实际滚动测试`);
          const result = performScrollTestInDirection(el, direction);
          console.log(`${direction} 方向异步测试结果:`, result);
          resolve(result);
        } catch (error) {
          console.warn(`${direction} 方向异步滚动检测失败:`, error);
          // 如果测试失败但有内容溢出，谨慎地认为可能可滚动
          resolve(hasRelevantOverflow);
        }
      });
    });
  }

  /**
   * 判断一个元素是否真的可以滚动 (基于CSS和内容的可靠方法)
   * @param {Element} el - 要检查的元素
   * @param {string} direction - 可选的滚动方向 ('up', 'down', 'left', 'right')
   */
  async function isScrollable(el, direction) {
    if (!el) return false;

    // 如果指定了方向，使用方向性检测
    if (direction) {
      return isScrollableInDirection(el, direction);
    }

    // 兼容原有的全方向检测
    if (!el) return false;

    // 检查是否有内容溢出
    const hasVerticalOverflow = el.scrollHeight > el.clientHeight;
    const hasHorizontalOverflow = el.scrollWidth > el.clientWidth;

    if (!hasVerticalOverflow && !hasHorizontalOverflow) {
      console.log('没有内容溢出，不可滚动');
      return false;
    }

    // 检查 CSS overflow 属性
    const style = window.getComputedStyle(el);
    const overflowX = style.overflowX;
    const overflowY = style.overflowY;

    console.log('CSS overflow:', overflowX, overflowY);

    // 如果明确设置了不可滚动
    if (
      (overflowX === 'hidden' && overflowY === 'hidden') ||
      (overflowX === 'visible' && overflowY === 'visible')
    ) {
      console.log('CSS设置为不可滚动');
      return false;
    }

    // 如果设置了可滚动样式且有内容溢出，则认为可滚动
    if (
      (overflowX === 'auto' ||
        overflowX === 'scroll' ||
        overflowY === 'auto' ||
        overflowY === 'scroll') &&
      (hasVerticalOverflow || hasHorizontalOverflow)
    ) {
      console.log('CSS设置为可滚动且有内容溢出，判断为可滚动');
      return true;
    }

    // 对于其他情况（如inherit等），使用异步实际测试
    return new Promise((resolve) => {
      requestAnimationFrame(() => {
        try {
          console.log('使用异步实际滚动测试');
          const result = performScrollTest(el);
          console.log('异步测试结果:', result);
          resolve(result);
        } catch (error) {
          console.warn('异步滚动检测失败:', error);
          // 如果测试失败但有内容溢出，谨慎地认为可能可滚动
          resolve(hasVerticalOverflow || hasHorizontalOverflow);
        }
      });
    });
  }

  /**
   * 执行指定方向的滚动测试
   * 根据滚动方向只测试相关方向的滚动能力
   */
  function performScrollTestInDirection(el, direction) {
    console.log(`开始 ${direction} 方向滚动测试:`, el.tagName, el.className, el.id);

    const isVertical = direction === 'up' || direction === 'down';
    const isHorizontal = direction === 'left' || direction === 'right';

    if (isVertical) {
      // 测试垂直滚动
      const oldTop = el.scrollTop;

      // 根据方向选择测试策略
      if (direction === 'down') {
        // 向下滚动测试
        el.scrollTop += 1;
      } else {
        // 向上滚动测试，如果已经在顶部，先向下滚动一点再测试向上
        if (el.scrollTop === 0) {
          const maxScrollTop = el.scrollHeight - el.clientHeight;
          if (maxScrollTop > 0) {
            el.scrollTop = 1;
            const newTop = el.scrollTop;
            el.scrollTop = 0;
            return newTop > 0; // 如果能滚动到1，说明可以向上滚动
          }
          return false;
        } else {
          el.scrollTop -= 1;
        }
      }

      console.log(`${direction} 垂直滚动测试:`, el.scrollTop, oldTop, el.scrollTop !== oldTop);
      if (el.scrollTop !== oldTop) {
        el.scrollTop = oldTop; // 恢复原位置
        console.log(`${direction} 垂直滚动检测成功`);
        return true;
      }

      // 策略2: 检查滚动到最大值是否有效果
      const maxScrollTop = el.scrollHeight - el.clientHeight;
      if (maxScrollTop > 0) {
        const originalTop = el.scrollTop;
        if (direction === 'down') {
          el.scrollTop = maxScrollTop;
          if (el.scrollTop > originalTop) {
            el.scrollTop = originalTop; // 恢复原位置
            console.log(`${direction} 滚动到底部检测成功`);
            return true;
          }
        } else {
          // direction === 'up'
          if (originalTop > 0) {
            el.scrollTop = 0;
            if (el.scrollTop < originalTop) {
              el.scrollTop = originalTop; // 恢复原位置
              console.log(`${direction} 滚动到顶部检测成功`);
              return true;
            }
          }
        }
      }
    } else if (isHorizontal) {
      // 测试水平滚动
      const oldLeft = el.scrollLeft;

      // 根据方向选择测试策略
      if (direction === 'right') {
        // 向右滚动测试
        el.scrollLeft += 1;
      } else {
        // 向左滚动测试，如果已经在最左边，先向右滚动一点再测试向左
        if (el.scrollLeft === 0) {
          const maxScrollLeft = el.scrollWidth - el.clientWidth;
          if (maxScrollLeft > 0) {
            el.scrollLeft = 1;
            const newLeft = el.scrollLeft;
            el.scrollLeft = 0;
            return newLeft > 0; // 如果能滚动到1，说明可以向左滚动
          }
          return false;
        } else {
          el.scrollLeft -= 1;
        }
      }

      console.log(`${direction} 水平滚动测试:`, el.scrollLeft, oldLeft, el.scrollLeft !== oldLeft);
      if (el.scrollLeft !== oldLeft) {
        el.scrollLeft = oldLeft; // 恢复原位置
        console.log(`${direction} 水平滚动检测成功`);
        return true;
      }

      // 策略2: 检查滚动到最大值是否有效果
      const maxScrollLeft = el.scrollWidth - el.clientWidth;
      if (maxScrollLeft > 0) {
        const originalLeft = el.scrollLeft;
        if (direction === 'right') {
          el.scrollLeft = maxScrollLeft;
          if (el.scrollLeft > originalLeft) {
            el.scrollLeft = originalLeft; // 恢复原位置
            console.log(`${direction} 滚动到右边检测成功`);
            return true;
          }
        } else {
          // direction === 'left'
          if (originalLeft > 0) {
            el.scrollLeft = 0;
            if (el.scrollLeft < originalLeft) {
              el.scrollLeft = originalLeft; // 恢复原位置
              console.log(`${direction} 滚动到左边检测成功`);
              return true;
            }
          }
        }
      }
    }

    console.log(`${direction} 方向滚动测试失败`);
    return false;
  }

  /**
   * 执行实际的滚动测试
   * 使用多种策略检测元素是否可滚动
   */
  function performScrollTest(el) {
    // 策略1: 尝试微小滚动检测（原方法）
    console.log('开始滚动测试:', el.tagName, el.className, el.id);

    // 测试垂直滚动
    const oldTop = el.scrollTop;
    el.scrollTop += 1;
    console.log('垂直滚动测试:', el.scrollTop, oldTop, el.scrollTop !== oldTop);
    if (el.scrollTop !== oldTop) {
      el.scrollTop = oldTop; // 恢复原位置
      console.log('垂直滚动检测成功');
      return true;
    }

    // 测试水平滚动
    const oldLeft = el.scrollLeft;
    el.scrollLeft += 1;
    console.log('水平滚动测试:', el.scrollLeft, oldLeft, el.scrollLeft !== oldLeft);
    if (el.scrollLeft !== oldLeft) {
      el.scrollLeft = oldLeft; // 恢复原位置
      console.log('水平滚动检测成功');
      return true;
    }

    // 策略2: 检查滚动到最大值是否有效果
    const maxScrollTop = el.scrollHeight - el.clientHeight;
    const maxScrollLeft = el.scrollWidth - el.clientWidth;

    if (maxScrollTop > 0) {
      const originalTop = el.scrollTop;
      el.scrollTop = maxScrollTop;
      if (el.scrollTop > originalTop) {
        el.scrollTop = originalTop; // 恢复原位置
        console.log('滚动到底部检测成功');
        return true;
      }
    }

    if (maxScrollLeft > 0) {
      const originalLeft = el.scrollLeft;
      el.scrollLeft = maxScrollLeft;
      if (el.scrollLeft > originalLeft) {
        el.scrollLeft = originalLeft; // 恢复原位置
        console.log('滚动到右边检测成功');
        return true;
      }
    }

    console.log('所有滚动测试均失败');
    return false;
  }

  /**
   * 获取元素的实际滚动容器 (异步版本)
   * - 如果没有找到，返回 window
   * @param {Element} el - 起始元素
   * @param {string} direction - 可选的滚动方向，用于精确检测该方向的滚动能力
   */
  async function getScrollParent(el, direction) {
    let parent = el;

    while (parent && parent !== document.body) {
      if (await isScrollable(parent, direction)) {
        return parent;
      }
      parent = parent.parentElement;
    }

    return window;
  }

  /**
   * Calculate scroll distance based on direction
   */
  function calculateScrollOffset(direction, distance) {
    switch (direction) {
      case 'up':
        return { x: 0, y: -distance };
      case 'down':
        return { x: 0, y: distance };
      case 'left':
        return { x: -distance, y: 0 };
      case 'right':
        return { x: distance, y: 0 };
      default:
        return { x: 0, y: distance };
    }
  }

  /**
   * Get element by selector or coordinates (异步版本)
   * @param {string} selector - 元素选择器
   * @param {Object} coordinates - 坐标位置
   * @param {string} direction - 可选的滚动方向，用于精确检测该方向的滚动能力
   */
  async function getTargetElement(selector, coordinates, direction) {
    if (selector) {
      const element = document.querySelector(selector);
      if (!element) {
        throw new Error(`Element not found for selector: ${selector}`);
      }
      return element;
    }

    if (coordinates) {
      // Get element at coordinates
      const elements = document.elementsFromPoint(coordinates.x, coordinates.y);
      const elementAtPoint = elements.filter(
        (el) => el.id !== 'mcp-page-protection-shadow-root',
      )[0];

      console.log('Element at coordinates:', elementAtPoint);

      if (elementAtPoint) {
        // Start from element at coordinates and traverse up to find scrollable parent
        let currentElement = elementAtPoint;

        while (currentElement) {
          console.log('Current element:', currentElement);
          if (await isScrollable(currentElement, direction)) {
            console.log('Scrollable parent found:', currentElement);
            return currentElement;
          }
          currentElement = currentElement.parentElement;
        }

        // If no scrollable parent found, fall back to window scrolling
        console.log('No scrollable parent found, falling back to window scrolling');
        return null;
      }

      throw new Error(`No element found at coordinates: ${coordinates.x}, ${coordinates.y}`);
    }

    // Default to window/document
    return null;
  }

  /**
   * Check if element is scrollable
   */
  // function isScrollable(element) {
  //   if (!element) {
  //     return false;
  //   }

  //   // body and documentElement are always considered scrollable for window scrolling
  //   if (element === document.body || element === document.documentElement) {
  //     return true;
  //   }

  //   const style = window.getComputedStyle(element);
  //   const overflowX = style.overflowX;
  //   const overflowY = style.overflowY;

  //   // Check if overflow allows scrolling
  //   const hasScrollableOverflow =
  //     overflowX === 'scroll' ||
  //     overflowX === 'auto' ||
  //     overflowY === 'scroll' ||
  //     overflowY === 'auto';

  //   if (hasScrollableOverflow) {
  //     return true;
  //   }

  //   // Check if element actually has scrollable content
  //   const hasScrollableContent =
  //     element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;

  //   return hasScrollableContent;
  // }

  // /**
  //  * Find scrollable parent element
  //  */
  // function findScrollableParent(element) {
  //   if (!element) return null;

  //   let parent = element.parentElement;
  //   while (parent && parent !== document.body) {
  //     if (isScrollable(parent)) {
  //       return parent;
  //     }
  //     parent = parent.parentElement;
  //   }

  //   return null;
  // }

  /**
   * Perform scroll operation (异步版本)
   */
  async function performScroll(params) {
    const { direction, distance, coordinates, selector, smooth = true } = params;

    try {
      const offset = calculateScrollOffset(direction, distance);
      let targetElement = await getTargetElement(selector, coordinates, direction);

      // Note: getTargetElement already handles finding scrollable elements for coordinates
      // Only need additional check for selector-based targeting
      const _isScrollable = await isScrollable(targetElement, direction);
      if (selector && targetElement && !_isScrollable) {
        const scrollableParent = await getScrollParent(targetElement, direction);
        if (scrollableParent) {
          targetElement = scrollableParent;
        } else {
          targetElement = null; // Fall back to window scroll
        }
      }

      let scrollResult;

      if (
        targetElement &&
        targetElement !== document.body &&
        targetElement !== document.documentElement
      ) {
        // Scroll specific element
        const initialScrollLeft = targetElement.scrollLeft;
        const initialScrollTop = targetElement.scrollTop;

        targetElement.scrollBy({
          left: offset.x,
          top: offset.y,
          behavior: smooth ? 'smooth' : 'instant',
        });

        scrollResult = {
          scrollPosition: {
            x: targetElement.scrollLeft,
            y: targetElement.scrollTop,
          },
          elementInfo: {
            tagName: targetElement.tagName,
            id: targetElement.id,
            className: targetElement.className,
            scrollWidth: targetElement.scrollWidth,
            scrollHeight: targetElement.scrollHeight,
            clientWidth: targetElement.clientWidth,
            clientHeight: targetElement.clientHeight,
          },
          scrollOffset: {
            x: targetElement.scrollLeft - initialScrollLeft,
            y: targetElement.scrollTop - initialScrollTop,
          },
        };
      } else {
        // Scroll window/document
        const initialScrollX = window.scrollX;
        const initialScrollY = window.scrollY;

        window.scrollBy({
          left: offset.x,
          top: offset.y,
          behavior: smooth ? 'smooth' : 'instant',
        });

        scrollResult = {
          scrollPosition: {
            x: window.scrollX,
            y: window.scrollY,
          },
          elementInfo: {
            tagName: 'WINDOW',
            scrollWidth: document.documentElement.scrollWidth,
            scrollHeight: document.documentElement.scrollHeight,
            clientWidth: window.innerWidth,
            clientHeight: window.innerHeight,
          },
          scrollOffset: {
            x: window.scrollX - initialScrollX,
            y: window.scrollY - initialScrollY,
          },
        };
      }

      return {
        success: true,
        message: `Scrolled ${direction} by ${distance}px`,
        targetElementInfo: {
          isWindow:
            !targetElement ||
            targetElement === document.body ||
            targetElement === document.documentElement,
          element: targetElement
            ? {
                tagName: targetElement.tagName,
                id: targetElement.id,
                className: targetElement.className,
                rect: targetElement.getBoundingClientRect
                  ? {
                      left: targetElement.getBoundingClientRect().left,
                      top: targetElement.getBoundingClientRect().top,
                      width: targetElement.getBoundingClientRect().width,
                      height: targetElement.getBoundingClientRect().height,
                    }
                  : null,
              }
            : { tagName: 'WINDOW' },
        },
        ...scrollResult,
      };
    } catch (error) {
      console.error('Scroll operation failed:', error);
      return {
        success: false,
        error: error.message,
      };
    }
  }

  /**
   * Handle messages from background script
   */
  chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
    if (message.action === 'scrollPageElement') {
      // 异步处理滚动操作，添加超时保护（最多等待3秒）
      withTimeout(performScroll(message), 3000)
        .then((result) => {
          sendResponse(result);
        })
        .catch((error) => {
          console.error('Error handling scroll message:', error);
          sendResponse({
            success: false,
            error: error.message,
          });
        });

      // 返回 true 表示会异步调用 sendResponse
      return true;
    }

    // Handle ping messages for helper detection
    if (message.action === 'scroll_helper_ping') {
      sendResponse({ success: true, message: 'Scroll helper is active' });
    }
  });

  console.log('Scroll helper ready');
})();
