/**
 * 阅读进度跟踪器 - Reading Progress Tracker
 * 一个轻量级的JavaScript库，用于跟踪网页内容的阅读进度
 *
 * @version 1.0.0
 * @author AI Assistant
 */

class ReadingProgressTracker {
  constructor(options = {}) {
    this.options = {
      targetSelector: "#mainContent",
      customEventName: "readingProgressChange",
      wordsPerMinute: 200, // 每分钟阅读字数（中文字符按2个字符算1个字）
      pdf: false, //是否是pdf的环境
      ...options,
    };

    this.currentProgress = 0; // 当前阅读进度
    this.totalLength = 0; // 页面的高度
    this.isTracking = true; //是否开启阅读
    this.lastReportedProgress = 0; // 上次报告的进度
    this.wordCount = 0; // 文章总字数
    this.estimatedReadingTime = 0; // 预计阅读时间（分钟）

    this.lastUpdateTime = 0; // 上次更新时间，防止同一帧内重复调用

    this.init();
  }

  init() {
  
    // 滚动监听事件
    this.bindEvents();

    console.log("✅ 阅读进度跟踪器初始化成功");
  }

  /**
   * 计算总阅读长度
   * 基于目标元素的内容高度和视口高度计算，针对PDF.js进行优化
   */
  calculateTotalLength() {
    console.log(
      "calculateTotalLength calculateTotalLength calculateTotalLength"
    );

    const target = document.querySelector(this.options.targetSelector);
    if (!target) {
      console.warn("⚠️ 未找到目标元素:", this.options.targetSelector);
      this.totalLength = 0;
      return;
    }

    // 获取目标元素的实际内容高度
    const contentHeight = target.scrollHeight || target.offsetHeight;
    console.log("contentHeight=", contentHeight);
    console.log("target=", target);

    // 如果内容高度为0，可能是内容还没有加载完成
    if (contentHeight === 0) {
      this.totalLength = 0;
      return;
    }

    // 获取视口高度
    const viewportHeight = window.innerHeight;

    // 获取目标元素相对于视口的位置
    const targetRect = target.getBoundingClientRect();
    const targetOffsetTop = target.offsetTop;

    // 针对PDF.js环境进行特殊处理
    let calculatedLength;

    if (this.options.pdf) {
      // PDF.js环境：使用更精确的高度计算
      const pdfContainers = [
        "#viewerContainer",
        "#viewer",
        ".pdfViewer",
        "#mainContainer",
      ];
      let maxPdfHeight = 0;

      // 遍历所有可能的PDF容器，找到最大高度
      for (const selector of pdfContainers) {
        const container = document.querySelector(selector);
        if (container) {
          const containerHeight =
            container.scrollHeight || container.offsetHeight;
          if (containerHeight > maxPdfHeight) {
            maxPdfHeight = containerHeight;
          }
        }
      }

      console.log("maxPdfHeight=", maxPdfHeight);

      // 使用PDF容器高度和body高度的较大值，减去视口高度
      calculatedLength = Math.max(maxPdfHeight, contentHeight) - viewportHeight;

      console.log("📄 PDF.js环境高度计算:", {
        maxPdfHeight: maxPdfHeight,
        bodyContentHeight: contentHeight,
        viewportHeight: viewportHeight,
        calculatedLength: calculatedLength,
      });
    } else {
      // 普通网页环境：使用标准计算方式
      // 统一计算基准：使用内容高度减去视口高度，得到可滚动的距离
      calculatedLength = Math.max(contentHeight - viewportHeight, 0);
      
      console.log("📄 普通网页环境高度计算:", {
        contentHeight: contentHeight,
        viewportHeight: viewportHeight,
        calculatedLength: calculatedLength,
        targetOffsetTop: targetOffsetTop,
      });
    }

    // 如果计算结果为负数或0，尝试使用文档总高度
    if (calculatedLength <= 0) {
      const documentHeight = Math.max(
        document.body.scrollHeight,
        document.body.offsetHeight,
        document.documentElement.clientHeight,
        document.documentElement.scrollHeight,
        document.documentElement.offsetHeight
      );
      calculatedLength = Math.max(
        documentHeight - viewportHeight,
        documentHeight
      );
      console.log("📄 使用文档总高度作为备选:", {
        documentHeight: documentHeight,
        calculatedLength: calculatedLength,
      });
    }

    // 确保总长度至少为1，避免除零错误
    this.totalLength = Math.max(calculatedLength, 1);

    console.log("📏 总阅读长度计算完成:", {
      totalLength: this.totalLength,
      contentHeight: contentHeight,
      viewportHeight: viewportHeight,
      targetOffsetTop: targetOffsetTop,
      finalCalculatedLength: calculatedLength,
      isPDFJS:
        typeof PDFViewerApplication !== "undefined" &&
        PDFViewerApplication.initialized,
    });

    // 如果启用了阅读时间计算，则计算字数和预计阅读时间
      this.calculateWordCount();
      this.calculateEstimatedReadingTime();

    // 重置标志
  }

  /**
   * 计算文章字数
   * 统计目标元素内的文本字符数
   */
  calculateWordCount() {
    const target = document.querySelector(this.options.targetSelector);
    if (!target) {
      console.warn(
        "⚠️ 未找到目标元素，无法计算字数:",
        this.options.targetSelector
      );
      this.wordCount = 0;
      return;
    }

    // 获取纯文本内容
    const textContent = target.innerText || target.textContent || "";

    // 移除多余的空白字符
    const cleanText = textContent.replace(/\s+/g, " ").trim();

    // 分别统计中文字符和英文单词
    const chineseChars = (cleanText.match(/[\u4e00-\u9fff]/g) || []).length;
    const englishWords = (cleanText.match(/[a-zA-Z]+/g) || []).length;
    const otherChars = cleanText
      .replace(/[\u4e00-\u9fff]/g, "")
      .replace(/[a-zA-Z]+/g, "")
      .replace(/\s/g, "").length;

    // 中文字符数 + 英文单词数 + 其他字符数的一半
    this.wordCount = chineseChars + englishWords + Math.ceil(otherChars / 2);

    console.log("📝 文章字数统计完成:", {
      totalWords: this.wordCount,
      chineseChars: chineseChars,
      englishWords: englishWords,
      otherChars: otherChars,
      textLength: cleanText.length,
    });

    // 重置标志
  }

  /**
   * 计算预计阅读时间
   * 基于字数和阅读速度计算
   */
  calculateEstimatedReadingTime() {
    if (this.wordCount > 0 && this.options.wordsPerMinute > 0) {
      // 计算预计阅读时间（分钟）
      this.estimatedReadingTime = Math.ceil(
        this.wordCount / this.options.wordsPerMinute
      );
    } else {
      this.estimatedReadingTime = 0;
    }

    console.log("⏱️ 预计阅读时间计算完成:", {
      wordCount: this.wordCount,
      wordsPerMinute: this.options.wordsPerMinute,
      estimatedMinutes: this.estimatedReadingTime,
    });
  }

  /**
   * 绑定滚动事件
   */
  bindEvents() {
    // 监听 '#mainContent' 的滚动
    if (this.options.pdf) {
      document.querySelector(this.options.targetSelector).addEventListener(
        "scroll",
        () => {
          if (this.isTracking) {
            this.updateProgress();
          }
        },
        { passive: true }
      );
    } else {
      window.addEventListener(
        "scroll",
        () => {
          if (this.isTracking) {
            this.updateProgress();
          }
        },
        { passive: true }
      );
      
    }
    // 监听窗口大小变化，重新计算总长度
    window.addEventListener(
        "resize",
        () => {
          this.calculateTotalLength();
        },
        { passive: true }
      );

      // 监听内容变化（如果有MutationObserver支持）
      if (typeof MutationObserver !== "undefined") {
        this.observeContentChanges();
      }
  }

  /**
   * 监听内容变化
   */
  observeContentChanges() {
      const target = document.querySelector(this.options.targetSelector);
      if (!target) return;

      // 添加防止递归调用的标志
      let isCalculating = false;

      const observer = new MutationObserver((mutations) => {
          // 避免递归调用
          if (isCalculating) return;

          // 检查是否是实际的内容变化（忽略属性变化和文本节点的样式变化）
          const hasRealContentChange = mutations.some(mutation => {
              return mutation.type === 'childList' &&
                     (mutation.addedNodes.length > 0 || mutation.removedNodes.length > 0);
          });

          if (hasRealContentChange) {
              isCalculating = true;
              // 延迟执行，避免在DOM操作过程中计算
              setTimeout(() => {
                  this.calculateTotalLength();
                  isCalculating = false;
              }, 100);
          }
      });

      observer.observe(target, {
          childList: true,
          subtree: true,
          attributes: false,        // 不监听属性变化
          characterData: false,     // 不监听文本内容变化
          attributeOldValue: false,
          characterDataOldValue: false
      });

      // 保存observer引用，以便销毁时清理
      this.contentObserver = observer;
  }

  /**
   * 处理滚动事件
   */
  // handleScroll方法已废弃

  /**
   * 更新阅读进度
   * 针对PDF.js环境进行优化，提供更精确的进度计算
   */
  updateProgress() {
    // 简化的防重复调用：仅在同一帧内防止重复
    const now = Date.now();
    if (this.lastUpdateTime && now - this.lastUpdateTime < 16) {
      // 16ms = 约60fps，避免同一帧内重复计算
      return;
    }
    this.lastUpdateTime = now;

    const target = document.querySelector(this.options.targetSelector);
    if (!target) {
      console.warn("⚠️ 未找到目标元素:", this.options.targetSelector);
      return;
    }


    // 获取当前滚动位置 - 针对PDF.js进行优化
    let scrollTop, targetOffsetTop, relativeScrollTop;

    if (this.options.pdf) {
      const container = document.querySelector("#viewerContainer");
      if (container && container.scrollHeight > container.clientHeight) {
        scrollTop = container.scrollTop;
        targetOffsetTop = container.offsetTop;
        relativeScrollTop = Math.max(0, scrollTop - targetOffsetTop);

        console.log(`📄 使用PDF容器 计算滚动:`, {
          scrollTop: scrollTop,
          targetOffsetTop: targetOffsetTop,
          relativeScrollTop: relativeScrollTop,
          totalLength: this.totalLength,
        });
      }
    } else {
      // 普通网页环境：使用标准滚动计算
      scrollTop = window.pageYOffset || document.documentElement.scrollTop;
      console.log("scrollTop=", scrollTop);
      targetOffsetTop = target.offsetTop;
      console.log("targetOffsetTop=", targetOffsetTop);
      
      // 修复：统一计算基准，与totalLength保持一致
      // 计算当前滚动位置相对于目标元素起始位置的距离
      relativeScrollTop = Math.max(0, scrollTop - targetOffsetTop);
      
      // 确保relativeScrollTop不超过可滚动的最大距离
      const maxScrollable = Math.max(0, target.scrollHeight - window.innerHeight);
      relativeScrollTop = Math.min(relativeScrollTop, maxScrollable);
      
      console.log("relativeScrollTop=", relativeScrollTop);
      console.log("this.totalLength=", this.totalLength);
      console.log("maxScrollable=", maxScrollable);
    }

    // 计算实际滚动进度百分比
    let actualProgress = 0;
    let rawProgress = 0;

    if (this.totalLength > 0) {
      // 使用更精确的进度计算公式
      rawProgress = Math.min(
        100,
        Math.max(0, (relativeScrollTop / this.totalLength) * 100)
      );
      console.log("rawProgress=", rawProgress);
      
      // 直接使用原始进度，不再进行加速计算
      actualProgress = rawProgress;
    }
    console.log("rawProgress=", rawProgress);

    // 修复：检测是否滚动到底部，如果是则强制进度为100%
    if (!this.pdf) {
      const documentHeight = Math.max(
        document.body.scrollHeight,
        document.body.offsetHeight,
        document.documentElement.clientHeight,
        document.documentElement.scrollHeight,
        document.documentElement.offsetHeight
      );
    }
    // 更新阅读进度
    this.currentProgress = rawProgress;
    console.log("newProgress this.currentProgress =", this.currentProgress);
    console.log("newProgress=", rawProgress);
    this.reportProgress(rawProgress);
  }

  /**
   * 报告阅读进度
   */
  reportProgress(newProgress) {
    // 创建自定义事件数据
    const eventDetail = {
      progress: newProgress,
      totalLength: this.totalLength,
      timestamp: Date.now(),
    };

    // 如果启用了阅读时间计算，添加相关信息
      eventDetail.wordCount = this.wordCount;
      eventDetail.estimatedReadingTime = this.estimatedReadingTime;
      eventDetail.remainingReadingTime = this.getRemainingReadingTime();
      eventDetail.wordsPerMinute = this.options.wordsPerMinute;

    // 创建自定义事件
    const event = new CustomEvent(this.options.customEventName, {
      detail: eventDetail,
    });

    // 触发事件
    window.dispatchEvent(event);

    console.log("📊 阅读进度更新:", this.currentProgress + "%");
  }


  /**
   * 滚动到指定进度位置
   * @param {number} progress - 进度百分比（0-100）
   */
  scrollToProgress(progress) {
    const target = document.querySelector(this.options.targetSelector);
    if (!target) {
      console.warn("⚠️ 未找到目标元素:", this.options.targetSelector);
      return;
    }

    // 确保进度在有效范围内
    progress = Math.max(0, Math.min(100, progress));

    // 计算目标滚动位置
    const targetOffsetTop = target.offsetTop;
    const scrollPosition =
      targetOffsetTop + (this.totalLength * progress) / 100;

    // 平滑滚动到目标位置
    window.scrollTo({
      top: scrollPosition,
      behavior: "smooth",
    });

    console.log("🎯 滚动到阅读进度:", progress + "%");
  }

  /**
   * 获取总阅读长度
   * @returns {number} 总阅读长度（像素）
   */
  getTotalLength() {
    return this.totalLength;
  }

  /**
   * 获取当前阅读进度
   * @returns {number} 当前阅读进度（0-100的整数）
   */
  getCurrentProgress() {
    // 实时计算当前进度
    this.updateProgress();
    return this.currentProgress;
  }

  /**
   * 获取详细的进度信息
   * @returns {object} 包含进度、总长度、时间戳等信息的对象
   */
  getProgressInfo() {
    this.updateProgress();
    const progressInfo = {
      progress: this.currentProgress,
      totalLength: this.totalLength,
      timestamp: Date.now(),
      isTracking: this.isTracking,
    };

    // 如果启用了阅读时间计算，添加相关信息
   
      progressInfo.wordCount = this.wordCount;
      progressInfo.estimatedReadingTime = this.estimatedReadingTime;
      progressInfo.wordsPerMinute = this.options.wordsPerMinute;

      // 计算剩余阅读时间
      const remainingProgress = Math.max(0, 100 - this.currentProgress);
      progressInfo.remainingReadingTime = Math.ceil(
        (this.estimatedReadingTime * remainingProgress) / 100
      );
    

    return progressInfo;
  }

  /**
   * 开始跟踪阅读进度
   */
  startTracking() {
    this.isTracking = true;
    this.calculateTotalLength();
    console.log("▶️ 开始跟踪阅读进度");
  }

  /**
   * 停止跟踪阅读进度
   */
  stopTracking() {
    this.isTracking = false;
    console.log("⏸️ 停止跟踪阅读进度");
  }

  /**
   * 重置进度跟踪器
   */
  reset() {
    this.currentProgress = 0;
    this.lastReportedProgress = 0;
    this.lastUpdateTime = 0;
    this.calculateTotalLength();
    console.log("�� 阅读进度跟踪器已重置");
  }

  /**
   * 设置自定义事件名称
   * @param {string} eventName - 自定义事件名称
   */
  setCustomEventName(eventName) {
    this.options.customEventName = eventName;
    console.log("🎯 自定义事件名称已设置为:", eventName);
  }

  /**
   * 设置防抖延迟时间
   * @param {number} delay - 延迟时间（毫秒）
   */
  setThrottleDelay(delay) {
    // 移除此方法，因为不再使用防抖
    console.warn("setThrottleDelay 方法已废弃，不再支持防抖延迟。");
  }

  /**
   * 获取文章字数
   * @returns {number} 文章总字数
   */
  getWordCount() {
    return this.wordCount;
  }

  /**
   * 获取预计阅读时间
   * @returns {number} 预计阅读时间（分钟）
   */
  getEstimatedReadingTime() {
    return this.estimatedReadingTime;
  }

  /**
   * 获取剩余阅读时间
   * @returns {number} 剩余阅读时间（分钟）
   */
  getRemainingReadingTime() {
    const remainingProgress = Math.max(0, 100 - this.currentProgress);
    return Math.ceil((this.estimatedReadingTime * remainingProgress) / 100);
  }

  /**
   * 设置阅读速度
   * @param {number} wordsPerMinute - 每分钟阅读字数
   */
  setWordsPerMinute(wordsPerMinute) {
    if (wordsPerMinute > 0) {
      this.options.wordsPerMinute = wordsPerMinute;
      // 重新计算预计阅读时间
      this.calculateEstimatedReadingTime();
      console.log("📖 阅读速度已更新为:", wordsPerMinute, "字/分钟");
    } else {
      console.warn("⚠️ 阅读速度必须大于0");
    }
  }

  /**
   * 格式化阅读时间显示
   * @param {number} minutes - 分钟数
   * @returns {string} 格式化的时间字符串
   */
  formatReadingTime(minutes) {
    if (minutes <= 0) {
      return "0分钟";
    } else if (minutes < 60) {
      return `${minutes}分钟`;
    } else {
      const hours = Math.floor(minutes / 60);
      const remainingMinutes = minutes % 60;
      if (remainingMinutes === 0) {
        return `${hours}小时`;
      } else {
        return `${hours}小时${remainingMinutes}分钟`;
      }
    }
  }

  /**
   * 销毁跟踪器
   */
  destroy() {
    this.stopTracking();

    // 移除事件监听器（注意：这里需要移除实际绑定的事件监听器）
    // 由于我们使用的是箭头函数，无法直接移除，但这不是问题
    // 因为当对象被销毁时，这些监听器会自动被垃圾回收

   

    console.log("🗑️ 阅读进度跟踪器已销毁");
  }

  /**
   * 获取精确的滚动信息
   * 针对PDF.js环境进行优化
   */
  getScrollInfo() {
    const scrollInfo = {
      windowScroll: {
        pageYOffset: window.pageYOffset,
        documentElementScrollTop: document.documentElement.scrollTop,
        bodyScrollTop: document.body.scrollTop,
      },
      viewport: {
        innerHeight: window.innerHeight,
        clientHeight: document.documentElement.clientHeight,
      },
      document: {
        scrollHeight: Math.max(
          document.body.scrollHeight,
          document.body.offsetHeight,
          document.documentElement.clientHeight,
          document.documentElement.scrollHeight,
          document.documentElement.offsetHeight
        ),
      },
    };

    // 检查PDF.js环境
    if (
      typeof PDFViewerApplication !== "undefined" &&
      PDFViewerApplication.initialized
    ) {
      const pdfContainers = [
        "#viewerContainer",
        "#viewer",
        ".pdfViewer",
        "#mainContainer",
      ];
      scrollInfo.pdfContainers = {};

      pdfContainers.forEach((selector) => {
        const container = document.querySelector(selector);
        if (container) {
          scrollInfo.pdfContainers[selector] = {
            scrollTop: container.scrollTop,
            scrollHeight: container.scrollHeight,
            clientHeight: container.clientHeight,
            offsetTop: container.offsetTop,
            offsetHeight: container.offsetHeight,
          };
        }
      });
    }

    return scrollInfo;
  }

  /**
   * 智能计算滚动进度
   * 结合多种计算方法，提供最准确的进度值
   */
  calculateSmartProgress() {
    const scrollInfo = this.getScrollInfo();
    let bestProgress = 0;
    let calculationMethod = "unknown";

    if (
      typeof PDFViewerApplication !== "undefined" &&
      PDFViewerApplication.initialized
    ) {
      // PDF.js环境：使用PDF容器的滚动信息
      const pdfContainers = [
        "#viewerContainer",
        "#viewer",
        ".pdfViewer",
        "#mainContainer",
      ];

      for (const selector of pdfContainers) {
        const containerInfo = scrollInfo.pdfContainers[selector];
        if (
          containerInfo &&
          containerInfo.scrollHeight > containerInfo.clientHeight
        ) {
          const progress =
            (containerInfo.scrollTop /
              (containerInfo.scrollHeight - containerInfo.clientHeight)) *
            100;
          if (progress > bestProgress) {
            bestProgress = progress;
            calculationMethod = `pdf-${selector}`;
          }
        }
      }
    }

    // 如果PDF容器计算失败，使用页面滚动
    if (bestProgress === 0) {
      const pageScrollTop =
        scrollInfo.windowScroll.pageYOffset ||
        scrollInfo.windowScroll.documentElementScrollTop;
      const documentHeight = scrollInfo.document.scrollHeight;
      const viewportHeight = scrollInfo.viewport.innerHeight;

      if (documentHeight > viewportHeight) {
        bestProgress =
          (pageScrollTop / (documentHeight - viewportHeight)) * 100;
        calculationMethod = "page-scroll";
      }
    }

    // 确保进度在有效范围内
    bestProgress = Math.max(0, Math.min(100, bestProgress));

    console.log("🧠 智能进度计算:", {
      method: calculationMethod,
      progress: bestProgress.toFixed(2) + "%",
      scrollInfo: scrollInfo,
    });

    return {
      progress: bestProgress,
      method: calculationMethod,
      scrollInfo: scrollInfo,
    };
  }

  /**
   * 强制重新计算进度
   * 用于手动触发进度更新
   */
  forceUpdateProgress() {
    console.log("🔄 强制更新进度...");

    // 重新计算总长度
    this.calculateTotalLength();

    // 使用智能进度计算
    const smartProgress = this.calculateSmartProgress();

    // 更新当前进度
    if (smartProgress.progress !== this.currentProgress) {
      this.currentProgress = Math.round(smartProgress.progress);
      this.lastReportedProgress = this.currentProgress;
      this.reportProgress();
    }

    return smartProgress;
  }

  /**
   * 调试方法：验证计算一致性
   * 用于排查滚动进度计算问题
   */
  debugCalculationConsistency() {
    const target = document.querySelector(this.options.targetSelector);
    if (!target) {
      console.warn("⚠️ 未找到目标元素:", this.options.targetSelector);
      return null;
    }

    const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
    const targetOffsetTop = target.offsetTop;
    const contentHeight = target.scrollHeight || target.offsetHeight;
    const viewportHeight = window.innerHeight;
    
    // 计算可滚动的最大距离
    const maxScrollable = Math.max(0, contentHeight - viewportHeight);
    
    // 计算当前滚动位置相对于目标元素起始位置的距离
    const relativeScrollTop = Math.max(0, scrollTop - targetOffsetTop);
    
    // 计算进度
    const calculatedProgress = maxScrollable > 0 ? (relativeScrollTop / maxScrollable) * 100 : 0;
    
    const debugInfo = {
      scrollTop: scrollTop,
      targetOffsetTop: targetOffsetTop,
      contentHeight: contentHeight,
      viewportHeight: viewportHeight,
      maxScrollable: maxScrollable,
      relativeScrollTop: relativeScrollTop,
      calculatedProgress: calculatedProgress.toFixed(2) + "%",
      totalLength: this.totalLength,
      currentProgress: this.currentProgress,
      isConsistent: Math.abs(maxScrollable - this.totalLength) < 5, // 允许5px的误差
    };

    console.log("🔍 计算一致性调试信息:", debugInfo);
    
    if (!debugInfo.isConsistent) {
      console.warn("⚠️ 计算不一致！建议重新计算totalLength");
      console.warn("maxScrollable:", maxScrollable, "vs totalLength:", this.totalLength);
    }
    
    return debugInfo;
  }
}

// 导出到全局作用域
window.ReadingProgressTracker = ReadingProgressTracker;
