巴哈姆特_新版B頁板務功能Re

巴哈姆特哈拉區新體驗。

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name 巴哈姆特_新版B頁板務功能Re
// @namespace Bee10301
// @version 9.5
// @description 巴哈姆特哈拉區新體驗。
// @author Bee10301
// @match https://removed.www.gamer.com.tw/
// @match https://removed.www.gamer.com.tw/index2.php*
// @match https://forum.gamer.com.tw/B.php?*
// @match https://forum.gamer.com.tw/C.php?*
// @match https://forum.gamer.com.tw/2025/?bsn*
// @homepage https://home.gamer.com.tw/home.php?owner=bee10301
// @icon https://home.gamer.com.tw/favicon.ico
// @connect *
// @grant GM_xmlhttpRequest
// @license GPL
// ==/UserScript==

/**
 * 巴哈姆特插件 - 核心配置與初始化模組
 * 負責插件的基本配置、設定管理和初始化流程
 */
class BahamutePlugin {
  constructor() {
    this.version = "9.0";
    this.isNewVersion = false;
    this.settings = new SettingsManager();
    this.init();
  }

  /**
   * 插件初始化(舊版棄置)
   */
  async init() {
    try {
      this.isNewVersion = await this.detectMode();
      //this.settings.checkFirstRun();
      //await this.addSettingElement(this.isNewVersion);
      //await this.initializeWorkers();
      //this.checkTips(this.isNewVersion);
      //this.reportAlert(this.isNewVersion);
    } catch (error) {
      console.error("[ERROR] Plugin initialization failed:", error);
    }
  }

  /**
   * 檢測頁面模式(新版/舊版)
   * @returns {Promise<boolean>} 是否為新版
   */
  async detectMode() {
    if (document.querySelector(".forum-nav-main") !== null) {
      await this.waitForElement(".forum-list-normal");
      this.setupNewVersionStyles();
      return true;
    }
    return false;
  }

  /**
   * 等待特定元素出現
   * @param {string} selector - CSS選擇器
   */
  waitForElement(selector) {
    return new Promise((resolve) => {
      const observer = new MutationObserver((mutations) => {
        if (document.querySelector(selector)) {
          observer.disconnect();
          resolve();
        }
      });
      observer.observe(document.body, { childList: true, subtree: true });
    });
  }

  /**
   * 設置新版樣式
   */
  setupNewVersionStyles() {
    const styleSheet = document.createElement("style");
    document.head.appendChild(styleSheet);
    const sheet = styleSheet.sheet;

    // C頁管理工具樣式
    sheet.insertRule(
      ".c-section:has(div.c-section__main.managertools) { position: sticky; bottom: 0; right: 0; z-index: 100; transform: translateX(85%); transition: 0.5s cubic-bezier(0,.67,0,1.05); }",
      0
    );
    sheet.insertRule(
      ".c-section:has(div.c-section__main.managertools):hover { transform: translateX(0vw); }",
      0
    );
    // C頁避免誤點上一頁
    sheet.insertRule(".article-back { display: none !important; }", 0);
    // 快速回覆樣式
    sheet.insertRule(
      `.c-section:has(div.c-section__main.c-editor.c-quick-reply) { position: sticky; bottom: 50px; right: 0; z-index: 99; transform: translateX(85%); transition: 0.5s cubic-bezier(0,.67,0,1.05); }`,
      0
    );
    sheet.insertRule(
      ".c-section:has(div.c-section__main.c-editor.c-quick-reply):hover { transform: translateX(0vw); }",
      0
    );

    this.setupPreviewBox();
    this.setupTopBarCover();
  }

  /**
   * 設置預覽框
   */
  setupPreviewBox() {
    const previewBox = document.getElementById("article-content-box");
    if (!previewBox) return;

    previewBox.style.width = "0%";
    previewBox.style.transition = "0.5s cubic-bezier(0,.67,0,1.05)";
    previewBox.style.zIndex = "999";
    previewBox.style.transform =
      this.settings.get("preview_LR") === "true"
        ? "translateX(100%)"
        : "translateX(-150%)";
  }

  /**
   * 設置頂部遮罩
   */
  setupTopBarCover() {
    const topBarCover = document.createElement("div");
    topBarCover.className = "bee-top-bar-cover";

    Object.assign(topBarCover.style, {
      width: "100vw",
      height: "0%",
      backgroundColor: "var(--f1-bg)",
      position: "absolute",
      top: "0",
      left: "0",
      transition: "0.5s cubic-bezier(0,.67,0,1.05)",
      zIndex: "990",
    });

    topBarCover.addEventListener("click", (e) => {
      const previewBox = document.getElementById("article-content-box");
      if (previewBox) {
        previewBox.style.transform =
          this.settings.get("preview_LR") === "true"
            ? "translateX(100%)"
            : "translateX(-150%)";
      }
      // 棄用內建返回按鈕
      // if (
      //   window.getComputedStyle(document.querySelector(".article-back"))
      //     .display !== "none"
      // ) {
      //   document.querySelector(".article-back").click();
      // }

      // 將網址 snA sn cPage 參數移除
      const url = new URL(window.location.href);
      url.searchParams.delete("snA");
      url.searchParams.delete("sn");
      url.searchParams.delete("cPage");
      window.history.replaceState({}, "", url.toString());

      topBarCover.style.height = "0%";
      topBarCover.style.opacity = "1";
      // remove skip floor btn
      document.getElementById("floating-skip-button")?.remove();
      // remove quick replay
      document
        .querySelector(".article-content-box .c-editor.c-quick-reply")
        ?.remove();
      // remove managertools
      document.querySelector(".article-content-box .managertools")?.remove();
      return false;
    });

    const topBar = document.querySelector(".main-nav");
    if (topBar) {
      topBar.parentNode.insertBefore(topBarCover, topBar.nextSibling);
      document.querySelector(".main-nav__row").style.height = "auto";
    }
  }

  /**
   * 初始化工作模組
   */
  async initializeWorkers() {
    const bPageWorker = new BPageWorker(this.isNewVersion, this.settings);
    const cPageWorker = new CPageWorker(this.settings);

    await bPageWorker.init();
    await cPageWorker.init();
  }

  /**
   * 檢查提示
   */
  checkTips(newVer) {
    const tipsManager = new TipsManager(this.settings);
    tipsManager.checkTips(newVer);
  }

  /**
   * 檢查檢舉提醒
   */
  reportAlert(newVer) {
    const reportManager = new ReportManager(this.settings);
    reportManager.checkAlert(newVer);
  }
}

/**
 * 設定管理器
 */
class SettingsManager {
  constructor() {
    this.defaultSettings = this.getDefaultSettings();
  }

  /**
   * 獲取預設設定
   */
  getDefaultSettings() {
    return {
      isFirstRun: "false",
      add_function: "true",
      preview_auto: "true",
      preview_wait_load: "false",
      preview_size: "80%",
      new_design: "true",
      new_design_box: "80%",
      new_design_box_Left: "65%",
      new_design_box_Right: "18%",
      new_design_LRSwitch: "false",
      bee_select_color: "#000000b3",
      addBorderInPicMode: "true",
      showTips: "true",
      preview_LR: "true",
      showAbuse: "true",
      addSummaryBtn: "true",
      oaiBaseUrl: "https://api.openai.com/v1/chat/completions",
      oaiKey: "sk-yourKey",
      oaiModel: "gpt-3.5-turbo",
      oaiPrompt: `## workflow
1. 總結:精確的讀懂和理解文章,然後用一句話脈絡清晰的語句,總結出[文章的主旨]。
2. 提煉重點:根據文章的邏輯和結構,清楚列出文章的主要論點,並按照下方範例的格式輸出。

總結:
- 要點1:
- 要點2:
...(依情況增加或減少要點)

## MUST/IMPORTANT/RULES
- 不能添加其他個人觀點或註釋。
- 使用繁體中文`,
      oaiPromptCmd:
        "以下是一段群組聊天的對話,總結對話中的話題,用條列式列出使用者的想法。\n## workflow \n 1. 整理話題:理解各個使用者討論的話題並以話題為單位整理出整串對話的話題 \n 2. 將相同話題中,對同一件事有相似想法的對話整理在一起(例如 `@user1/@user2:認為太貴了`) ,不同看法則單獨列出。\n 3. 輸出:把冗餘贅字優化,但保留具體描述。(劣例:`@user1/@user2:提及角色在世界觀中的地位和特徵` 在這個例子中沒有具體描述提及了什麼樣的地位或特徵)。使用者以 @id 標記並且不再添加其他md語法。 \n ## MUST/IMPORTANT/RULES \n- 不能添加其他個人觀點或註釋。\n- 使用繁體中文\n",
      oaiPromptChat:
        "根據文章內容,使用繁體中文流暢語言,簡潔的回答使用者的問題。",
      custom_oaiPrompt: "",
      custom_oaiPromptCmd: "",
      custom_oaiPromptChat: "",
      oaiPromptSystemMode: "true",
      oaiPromptDate: "20241101",
      oaiPromptUpdateDate: "20241101",
      oaiPromptUpdateURL: "https://gamercomtwnew.bee.moe/gamer.prompts.json",
      oaiPromptUpdateSleep: "1",
      cleanMode: "false",
      cleanModeSize: "4rem",
      homeStyleSwitch: "true",
      homeTips: "true",
    };
  }

  /**
   * 檢查首次運行
   */
  checkFirstRun(reset = false) {
    console.log("[INFO] Init data");

    Object.entries(this.defaultSettings).forEach(([key, defaultValue]) => {
      if (this.get(key) === "" || this.get(key) === null || reset === true) {
        this.set(key, defaultValue);
      }
    });

    // 特殊處理:更新舊版URL
    if (
      this.get("oaiPromptUpdateURL") ===
      "https://gamercomtwnew.bee.moe/gamer.prompts.js"
    ) {
      this.set(
        "oaiPromptUpdateURL",
        "https://gamercomtwnew.bee.moe/gamer.prompts.json"
      );
    }
  }

  /**
   * 獲取設定值
   */
  get(key) {
    return localStorage.getItem(key);
  }

  /**
   * 設置設定值
   */
  set(key, value) {
    localStorage.setItem(key, value);
  }

  /**
   * 獲取布林值設定
   */
  getBool(key) {
    return this.get(key) === "true";
  }
}
/**
 * B頁面工作模組
 * 負責B頁面的所有功能,包括即時預覽、版面設計、功能按鈕等
 */
class BPageWorker {
  constructor(isNewVersion, settings) {
    this.isNewVersion = isNewVersion;
    this.settings = settings;
    this.previewFrame = null;
  }

  /**
   * 初始化B頁面功能
   */
  async init() {
    if (!this.isBPage()) return;

    await this.initializePreview();
    this.initializeLayout();
    this.initializeInteractions();
    this.initializeMenu();
    this.initializeDesign();
    this.initializeFunctions();
    this.initializeStyles();
  }

  /**
   * 檢查是否為B頁面
   */
  isBPage() {
    return (
      document.querySelector(".forum-list-normal") ||
      document.querySelector(".b-list__head")
    );
  }

  /**
   * 初始化預覽功能
   */
  async initializePreview() {
    await this.setupPreviewAuto();

    if (!this.isNewVersion && this.settings.getBool("preview_auto")) {
      await this.createPreviewFrame();
    }
  }

  /**
   * 設置自動預覽
   */
  async setupPreviewAuto() {
    if (this.isNewVersion) {
      await this.setupNewVersionPreview();
    } else {
      this.setupOldVersionPreview();
    }
  }

  /**
   * 設置新版預覽
   */
  async setupNewVersionPreview() {
    const articleListContainer = document.querySelector("#list");
    if (!articleListContainer) {
      console.warn("⚠️ 文章列表容器未找到!");
      return;
    }
    articleListContainer.addEventListener("click", async (e) => {
      if (e.target.closest(".forum-item-info")) {
        e.preventDefault();
        await this.showNewVersionPreview();
        return false;
      }
    });

    // 如果網址帶有 snA 參數
    if (window.location.href.includes("snA=")) {
      await this.showNewVersionPreview();
    }
  }

  /**
   * 顯示新版預覽
   */
  async showNewVersionPreview() {
    const previewBox = document.getElementById("article-content-box");
    const topBarCover = document.querySelector(".bee-top-bar-cover");

    previewBox.style.transform = "translateX(0%)";
    previewBox.style.width = this.settings.get("preview_size") || "80%";

    topBarCover.style.height = "100vh";
    topBarCover.style.opacity = "0.7";

    // 等待C頁面載入並添加AI功能
    await this.waitForCPageLoad();
  }

  /**
   * 等待C頁面載入
   */
  async waitForCPageLoad() {
    return new Promise((resolve) => {
      const observer = new MutationObserver(async (mutations) => {
        if (document.querySelectorAll(".c-section__main.c-post").length > 0) {
          observer.disconnect();
          // 移動快速回覆、板務工具
          let managertools = document.querySelector(".managertools");
          if (managertools) {
            managertools = document
              .querySelector(".article-content-box")
              .appendChild(managertools.parentElement);
          }
          const quickReply = document.querySelector(".c-editor.c-quick-reply");
          if (quickReply) {
            document
              .querySelector(".article-content-box")
              .appendChild(quickReply.parentElement);
          }
          // 添加額外功能
          if (this.settings.getBool("addSummaryBtn")) {
            const cPageWorker = new CPageWorker(this.settings);
            await cPageWorker.addPostButtons(this.isNewVersion);
            cPageWorker.addSkipFloorButton();
          }
          resolve();
        }
      });
      observer.observe(document.body, { childList: true, subtree: true });
    });
  }

  /**
   * 設置舊版預覽
   */
  setupOldVersionPreview() {
    this.handlePicModeAdjustment();
    this.setupOldVersionClickHandlers();
  }

  /**
   * 處理圖片模式調整
   */
  handlePicModeAdjustment() {
    const picMode = document.querySelectorAll(".imglist-text").length !== 0;

    if (picMode) {
      const switchTopics = document.querySelectorAll(".b-list__main");
      switchTopics.forEach((topic) => {
        const topicTexts = topic.childNodes[1].childNodes[3];
        if (topicTexts && topicTexts.className === "imglist-text") {
          topic.childNodes[1].removeChild(topicTexts);
          topic.insertAdjacentHTML("beforeend", topicTexts.outerHTML);
        }
      });
    }
  }

  /**
   * 設置舊版點擊處理器
   */
  setupOldVersionClickHandlers() {
    const picMode = document.querySelectorAll(".imglist-text").length !== 0;

    // 標題點擊
    const titleLinks = document.querySelectorAll(".b-list__main__title");
    titleLinks.forEach((link) => {
      link.addEventListener("click", (e) => {
        e.preventDefault();
        const href = link.getAttribute("href");
        this.openInFrame(`https://forum.gamer.com.tw/${href}`);
        return false;
      });
    });

    // 頁面點擊
    const pageSelector = picMode
      ? "#BH-master > form > div > table > tbody > tr > td.b-list__main > div > div > span > span"
      : "#BH-master > form > div > table > tbody > tr > td.b-list__main > span > a";

    const pageLinks = document.querySelectorAll(pageSelector);
    pageLinks.forEach((link) => {
      link.addEventListener("click", (e) => {
        e.preventDefault();
        const href = link.getAttribute(picMode ? "data-page" : "href");
        this.openInFrame(`https://forum.gamer.com.tw/${href}`);
        return false;
      });
    });
  }

  /**
   * 創建預覽框架
   */
  async createPreviewFrame() {
    const previewContainer = this.createPreviewContainer();
    const iframe = this.createIframe();

    previewContainer.appendChild(iframe);
    document.body.appendChild(previewContainer);

    this.previewFrame = iframe;
    await this.initializePreviewContainer(previewContainer);
    this.setupPreviewCloseHandler();
  }

  /**
   * 創建預覽容器
   */
  createPreviewContainer() {
    const container = document.createElement("div");
    container.className = "bee_preview_wd";

    Object.assign(container.style, {
      height: "100%",
      width: this.settings.get("preview_size"),
      transform: "scaleX(0)",
      zIndex: "100",
      position: "fixed",
      top: "0px",
      [this.settings.getBool("preview_LR") ? "right" : "left"]: "1%",
    });

    return container;
  }

  /**
   * 創建iframe
   */
  createIframe() {
    const iframe = document.createElement("iframe");
    iframe.id = "bee_frame";
    iframe.title = "bee_frame";
    iframe.src = "";

    Object.assign(iframe.style, {
      border: "0em solid rgb(170, 50, 220, 0)",
      width: "100%",
      height: "100%",
    });

    return iframe;
  }

  /**
   * 初始化預覽容器
   */
  async initializePreviewContainer(container) {
    const animationDirection = this.settings.getBool("preview_LR")
      ? "rl"
      : "lr";
    await this.popElementInit(container, false, animationDirection, false);
  }

  /**
   * 設置預覽關閉處理器
   */
  setupPreviewCloseHandler() {
    const menuPath = document.querySelector("#BH-menu-path");
    if (!menuPath) return;

    Object.assign(menuPath.style, {
      transition: "all 0.5s cubic-bezier(0.21, 0.3, 0.18, 1.37) 0s",
      height: "40px",
      opacity: "1",
    });

    menuPath.addEventListener("click", () => {
      const container = document.querySelector(".bee_preview_wd");
      const direction = this.settings.getBool("preview_LR") ? "rl" : "lr";
      this.popElement(container, "false", direction);
      menuPath.style.height = "40px";
      menuPath.style.opacity = "1";
    });
  }

  /**
   * 在框架中打開URL
   */
  openInFrame(url) {
    if (!this.previewFrame) return;

    this.previewFrame.src = url;
    const menuPath = document.querySelector("#BH-menu-path");

    if (menuPath) {
      menuPath.style.height = "100%";
      menuPath.style.opacity = "0.6";
    }

    setTimeout(() => {
      const container = document.querySelector(".bee_preview_wd");
      const direction = this.settings.getBool("preview_LR") ? "rl" : "lr";
      this.popElement(container, "true", direction);
    }, 1000);

    // 設置iframe內的樣式
    setTimeout(() => {
      this.setupIframeStyles();
    }, 1000);
  }

  /**
   * 設置iframe內的樣式
   */
  setupIframeStyles() {
    try {
      const iframeDoc =
        this.previewFrame.contentDocument ||
        this.previewFrame.contentWindow.document;
      const styleSheet = iframeDoc.createElement("style");
      iframeDoc.head.appendChild(styleSheet);

      const sheet = styleSheet.sheet;
      sheet.insertRule(
        ".managertools { position: fixed; bottom: 0; right: 0; z-index: 100; }",
        0
      );
    } catch (error) {
      console.warn("無法設置iframe樣式:", error);
    }
  }

  /**
   * 初始化版面佈局
   */
  initializeLayout() {
    if (this.isNewVersion) {
      this.setupNewVersionLayout();
    } else {
      this.setupOldVersionLayout();
    }
  }

  /**
   * 設置新版版面
   */
  setupNewVersionLayout() {
    if (this.settings.getBool("cleanMode")) {
      this.enableCleanMode();
    }

    this.setupSlaveDisplay();
    this.setupOrderSwitching();
  }

  /**
   * 啟用清爽模式
   */
  enableCleanMode() {
    if (document.getElementById("cleanModeStyles")) {
      return;
    }
    const style = document.createElement("style");
    style.id = "cleanModeStyles";
    style.textContent = `
    /* 移除描述和縮圖 */
    .forum-item-desc,
    .forum-item-thumbnail {
      display: none !important;
    }
 
    /* 調整列表項目樣式 */
    .forum-list-item {
      padding: 0 !important;
      min-height: ${this.settings.get("cleanModeSize")} !important; 
    }
  `;
    document.head.appendChild(style);
  }

  /**
   * 設置從屬顯示
   */
  setupSlaveDisplay() {
    if (document.getElementById("showSlave")) {
      return;
    }
    const style = document.createElement("style");
    style.id = "showSlave";
    style.textContent = `
    #BH-slave {
      display: block !important;
    }
  `;
    document.head.appendChild(style);
  }

  /**
   * 設置順序切換
   */
  setupOrderSwitching() {
    if (document.getElementById("orderSwitching")) {
      return;
    }
    const style = document.createElement("style");
    style.id = "orderSwitching";
    style.textContent = `
    #BH-master {
      order: 2 !important;
    }
    #BH-slave {
      order: 1 !important;
      margin-left: 0 !important;
      margin-right: 12px !important;
    }
  `;
    document.head.appendChild(style);
  }

  /**
   * 設置舊版版面
   */
  setupOldVersionLayout() {
    if (this.settings.getBool("new_design_LRSwitch")) {
      const master = document.getElementById("BH-master");
      const slave = document.getElementById("BH-slave");

      if (master && slave) {
        master.style.float = "right";
        slave.style.float = "left";
      }
    }
  }

  /**
   * 初始化交互功能
   */
  initializeInteractions() {
    this.setupCheckboxSystem();
    this.setupBorderInPicMode();
  }

  /**
   * 設置複選框系統
   */
  setupCheckboxSystem() {
    const titleElements = this.getTitleElements();
    const checkboxes = this.getCheckboxElements();

    titleElements.forEach((title, index) => {
      this.setupTitleClickHandler(title, checkboxes, index);
    });
  }

  /**
   * 獲取標題元素
   */
  getTitleElements() {
    const hasImgList = document.querySelectorAll(".imglist-text").length > 0;
    return hasImgList
      ? document.getElementsByClassName("b-list__main")
      : document.getElementsByClassName("b-list__main");
  }

  /**
   * 獲取複選框元素
   */
  getCheckboxElements() {
    try {
      return document.getElementsByName("jsn[]");
    } catch (error) {
      return [];
    }
  }

  /**
   * 設置標題點擊處理器
   */
  setupTitleClickHandler(title, checkboxes, index) {
    // 防止子元素觸發
    const children = title.querySelectorAll("*");
    children.forEach((child) => {
      child.addEventListener("click", (event) => {
        event.stopPropagation();
      });
    });

    // 重置複選框
    if (checkboxes[index]) {
      checkboxes[index].checked = false;
    }

    title.onclick = (e) => {
      this.handleTitleClick(title, checkboxes, e);
    };
  }

  /**
   * 處理標題點擊
   */
  handleTitleClick(title, checkboxes, event) {
    const hasValidContent =
      title.querySelector(".b-list__main__title") ||
      title.querySelector(".imglist-text");

    if (!hasValidContent) return;

    // 隱藏管理器
    const manager = document.querySelector(".bee_manager");
    if (manager) {
      manager.style.display = "none";
    }

    // 處理複選框邏輯
    const snA = this.extractSnA(title.innerHTML);
    if (!snA) return;

    let hasCheckedBox = false;
    checkboxes.forEach((checkbox) => {
      if (checkbox.value === snA) {
        checkbox.checked = !checkbox.checked;
        title.style.backgroundColor = checkbox.checked
          ? this.settings.get("bee_select_color")
          : "";

        if (checkbox.checked) {
          hasCheckedBox = true;
        }
      }
    });

    // 顯示管理器
    if (hasCheckedBox && manager) {
      this.showManagerAtCursor(manager, event);
    }
  }

  /**
   * 提取snA值
   */
  extractSnA(innerHTML) {
    const match = innerHTML.match(/snA=(\d*)/);
    return match ? match[1] : null;
  }

  /**
   * 在游標位置顯示管理器
   */
  showManagerAtCursor(manager, event) {
    manager.style.left = `${event.clientX + 50}px`;
    manager.style.top = `${event.clientY - 170}px`;
    manager.style.display = "block";
  }

  /**
   * 設置圖片模式邊框
   */
  setupBorderInPicMode() {
    if (!this.settings.getBool("addBorderInPicMode")) return;

    const picModeBlocks = document.querySelectorAll(
      "#BH-master > form > div > table > tbody > tr > td.b-list__main > div > p"
    );

    picModeBlocks.forEach((block) => {
      block.style.borderTop = "dashed";
    });
  }

  /**
   * 初始化選單
   */
  initializeMenu() {
    if (this.isNewVersion) return;

    this.createManagerMenu();
    this.setupLinkClickPrevention();
  }

  /**
   * 創建管理器選單
   */
  createManagerMenu() {
    try {
      const managertools = document.querySelector(".managertools");
      if (!managertools) return;

      const bManagerDiv = this.createManagerContainer();
      const buttonGroups = this.createButtonGroups(managertools);

      bManagerDiv.appendChild(this.createCheckboxContainer());
      buttonGroups.forEach((group) => bManagerDiv.appendChild(group));

      managertools.parentElement.appendChild(bManagerDiv);
    } catch (error) {
      console.warn("創建管理器選單失敗:", error);
    }
  }

  /**
   * 創建管理器容器
   */
  createManagerContainer() {
    const container = document.createElement("div");
    container.className = "b-manager managertools bee_manager";

    Object.assign(container.style, {
      zIndex: "100",
      position: "fixed",
      width: "auto",
    });

    return container;
  }

  /**
   * 創建複選框容器
   */
  createCheckboxContainer() {
    const checkboxDiv = document.createElement("div");
    checkboxDiv.className = "checkbox";

    const label = document.createElement("label");
    label.setAttribute("for", "check");

    checkboxDiv.appendChild(label);
    return checkboxDiv;
  }

  /**
   * 創建按鈕組
   */
  createButtonGroups(managertools) {
    const buttonIndexes = [
      [0, 3, 7],
      [2, 4],
      [1, 8],
      [5, 6],
    ];

    return buttonIndexes.map((indexes) => {
      const beeDiv = document.createElement("div");
      beeDiv.className = "bee";
      beeDiv.style.padding = "5px";

      indexes.forEach((index) => {
        const buttons = managertools.querySelectorAll("button");
        if (buttons[index]) {
          const button = buttons[index].cloneNode(true);
          beeDiv.appendChild(button);
        }
      });

      return beeDiv;
    });
  }

  /**
   * 設置連結點擊防止
   */
  setupLinkClickPrevention() {
    const selectors = [
      "#BH-master > form > div > table > tbody > tr > td.b-list__main > a",
      "#BH-master > form > div > table > tbody > tr > td.b-list__main",
    ];

    selectors.forEach((selector) => {
      const elements = document.querySelectorAll(selector);
      elements.forEach((element) => {
        element.addEventListener("click", (event) => {
          event.stopPropagation();
        });
      });
    });
  }

  /**
   * 初始化設計
   */
  initializeDesign() {
    if (!this.settings.getBool("new_design")) return;

    this.applyNewDesign();
  }

  /**
   * 應用新設計
   */
  applyNewDesign() {
    if (document.getElementById("newDesignStyles")) {
      return;
    }
    const style = document.createElement("style");
    style.id = "newDesignStyles";
    style.textContent = `
    #BH-slave {
      width: ${this.settings.get("new_design_box_Right")} !important;
      max-width: 100vw !important;
    }
    #BH-master {
      width: ${this.settings.get("new_design_box_Left")} !important;
    }
  `;
    document.head.appendChild(style);

    if (this.isNewVersion) {
      this.applyNewVersionDesign();
    } else {
      this.applyOldVersionDesign();
    }
  }

  /**
   * 應用新版設計
   */
  applyNewVersionDesign() {
    if (document.getElementById("newVersionStyles")) {
      return;
    }
    const style = document.createElement("style");
    style.id = "newVersionStyles";
    const slaveStyleCss = this.settings.getBool("new_design_LRSwitch")
      ? "left: 0% !important;"
      : "right: 0% !important;";
    const adPositionCss = this.settings.getBool("new_design_LRSwitch")
      ? "right: 0;"
      : "left: 0;";
    const showFixedRightAtLeft = this.settings.getBool("new_design_LRSwitch")
      ? ""
      : "left: 300px !important; right: unset !important;";
    style.textContent = `
    #forum-list-box {
      left: 50% !important;
      transform: translateX(-50%) !important;
    }
    .forum-box.split .forum-list-box {
      width: ${this.settings.get("new_design_box")} !important;
    }
    #BH-slave {
      position: fixed !important;
      bottom: 0% !important;
      z-index: 100 !important;
      ${slaveStyleCss}
    }
    #buildingAdB {
      position: absolute !important;
      bottom: 0 !important;
      ${adPositionCss}
    }
    .fixed-right {
      ${showFixedRightAtLeft}
    }
  `;
    document.head.appendChild(style);

    const changeAdPosition = document.getElementById("buildingAdB");
    const mainBox = document.querySelector(".forum-main");
    mainBox.prepend(changeAdPosition);
  }

  /**
   * 應用舊版設計
   */
  applyOldVersionDesign() {
    const wrapper = document.getElementById("BH-wrapper");
    if (wrapper) {
      wrapper.style.width = this.settings.get("new_design_box");
    }
  }

  /**
   * 初始化功能
   */
  initializeFunctions() {
    if (!this.settings.getBool("add_function") || this.isNewVersion) return;

    this.addFunctionButtons();
  }

  /**
   * 添加功能按鈕
   */
  addFunctionButtons() {
    const titleElements = document.getElementsByClassName("b-list__main");
    const titleLinks = document.getElementsByClassName("b-list__main__title");

    // 創建新的td元素
    const newTd = document.createElement("td");
    const filterElement = document.querySelector(".b-list__filter");
    if (filterElement) {
      filterElement.insertAdjacentElement("afterend", newTd);
    }

    // 為每個標題添加功能按鈕
    Array.from(titleElements).forEach((title, index) => {
      if (titleLinks[index]) {
        const buttonContainer = this.createFunctionButtonContainer(
          titleLinks[index]
        );
        title.insertAdjacentElement("afterend", buttonContainer);
      }
    });

    this.setupFunctionButtonHover();
  }

  /**
   * 創建功能按鈕容器
   */
  createFunctionButtonContainer(titleLink) {
    const td = document.createElement("td");
    td.style.width = "auto";

    const hrefValue = titleLink.getAttribute("href");
    const isDarkTheme = this.checkDarkTheme();

    const buttons = this.createFunctionButtons(hrefValue, isDarkTheme);
    buttons.forEach((button) => td.appendChild(button));

    return td;
  }

  /**
   * 檢查是否為暗色主題
   */
  checkDarkTheme() {
    const menuPath = document.getElementById("BH-menu-path");
    if (!menuPath) return false;

    const bgColor = window.getComputedStyle(menuPath).backgroundColor;
    return bgColor === "rgb(28, 28, 28)";
  }

  /**
   * 創建功能按鈕
   */
  createFunctionButtons(hrefValue, isDarkTheme) {
    const buttonConfigs = [
      {
        title: "快速瀏覽",
        class: "bee_preview",
        icon: "fullscreen",
        onclick: () =>
          this.openInFrame("https://forum.gamer.com.tw/" + hrefValue),
      },
      {
        title: "開新視窗",
        class: "bee_open_new_wd",
        icon: "open_in_new",
        onclick: () => window.open(hrefValue),
      },
      {
        title: "複製連結",
        class: "bee_link",
        icon: "link",
        onclick: () =>
          navigator.clipboard.writeText(
            "https://forum.gamer.com.tw/" + hrefValue
          ),
      },
    ];

    return buttonConfigs.map((config) => {
      const button = document.createElement("a");
      button.title = config.title;
      button.className = `btn-icon btn-icon--inverse ${config.class}`;
      button.style.display = "none";
      button.onclick = config.onclick;

      const icon = document.createElement("i");
      icon.className = `material-icons ${config.class}`;
      icon.textContent = config.icon;

      if (!isDarkTheme) {
        icon.style.color = "rgba(0, 0, 0, 0.4)";
      }

      button.appendChild(icon);
      return button;
    });
  }

  /**
   * 設置功能按鈕懸停效果
   */
  setupFunctionButtonHover() {
    const rows = document.querySelectorAll(".b-list__row");

    rows.forEach((row) => {
      row.addEventListener("mouseover", () => {
        this.toggleFunctionButtons(row, true);
      });

      row.addEventListener("mouseout", () => {
        this.toggleFunctionButtons(row, false);
      });
    });
  }

  /**
   * 切換功能按鈕顯示
   */
  toggleFunctionButtons(row, show) {
    const buttonClasses = [".bee_preview", ".bee_open_new_wd", ".bee_link"];

    buttonClasses.forEach((className) => {
      const button = row.querySelector(className);
      if (button) {
        button.style.display = show ? "" : "none";
      }
    });
  }

  /**
   * 初始化樣式
   */
  initializeStyles() {
    // 樣式相關的初始化可以在這裡添加
  }

  /**
   * 彈出元素初始化
   */
  async popElementInit(element, show = true, anime = "ud", waitAppend = true) {
    if (waitAppend) {
      requestAnimationFrame(() => {
        this.setElementDimensions(element);
      });
    } else {
      this.setElementDimensions(element);
    }

    this.setupElementTransition(element, show, anime);
  }

  /**
   * 設置元素尺寸
   */
  setElementDimensions(element) {
    element.style.readHeight =
      element.scrollHeight === 0 ? "999px" : `${element.scrollHeight}px`;
    element.style.readWidth =
      element.scrollWidth === 0 ? "999px" : `${element.scrollWidth}px`;
  }

  /**
   * 設置元素過渡
   */
  setupElementTransition(element, show, anime) {
    Object.assign(element.style, {
      transition: "",
      overflow: "hidden auto",
      opacity: "0",
    });

    this.popElement(element, "false", anime);
    element.style.transition =
      "all 0.5s cubic-bezier(0.21, 0.3, 0.18, 1.37) 0s";

    if (!show) {
      element.style.beeShow = "false";
      return;
    }

    element.style.beeShow = "true";
    element.style.opacity = "1";

    requestAnimationFrame(() => {
      element.style.maxHeight = element.style.readHeight;
    });
  }

  /**
   * 彈出元素控制
   */
  popElement(element, show = "true", anime = "ud") {
    const doShow =
      show === "toggle" ? !(element.style.beeShow === "true") : show === "true";

    if (doShow) {
      this.showElement(element);
    } else {
      this.hideElement(element, anime);
    }
  }

  /**
   * 顯示元素
   */
  showElement(element) {
    Object.assign(element.style, {
      opacity: "1",
      maxHeight: element.style.readHeight,
      maxWidth: element.style.readWidth,
      transform: "translateX(0px) translateY(0px)",
      beeShow: "true",
    });
  }

  /**
   * 隱藏元素
   */
  hideElement(element, anime) {
    element.style.beeShow = "false";
    element.style.opacity = "0";

    if (anime.includes("u")) {
      element.style.maxHeight = "0px";
      if (anime.startsWith("d")) {
        element.style.transform = `translateX(0px) translateY(${element.style.readWidth}px)`;
      }
    }

    if (anime.includes("l")) {
      element.style.maxWidth = "0px";
      if (anime.startsWith("r")) {
        element.style.transform = `translateX(${element.style.readHeight}) translateY(0px)`;
      }
    }
  }
}
/**
 * C頁面工作模組
 * 負責C頁面的AI功能,包括懶人包、留言統整、問問功能等
 */
class CPageWorker {
  constructor(settings) {
    this.settings = settings;
    this.gptRequestQueue = [];
    this.isProcessingQueue = false;
  }

  /**
   * 初始化C頁面功能
   */
  async init() {
    if (!this.isCPage()) return;

    this.setupCPageStyles();

    if (this.settings.getBool("addSummaryBtn")) {
      await this.addPostButtons();
    }
  }

  /**
   * 檢查是否為C頁面
   */
  isCPage() {
    return window.location.href.includes("forum.gamer.com.tw/C.php");
  }

  /**
   * 設置C頁面樣式
   */
  setupCPageStyles() {
    const styleSheet = document.createElement("style");
    document.head.appendChild(styleSheet);
    const sheet = styleSheet.sheet;

    sheet.insertRule(
      ".managertools { position: fixed; bottom: 0; right: 0; z-index: 100; }",
      0
    );
  }

  /**
   * 添加文章按鈕
   */
  async addPostButtons(isNewVersion = false) {
    await this.updatePrompts();

    const postSections = this.getPostSections();
    postSections.forEach((postSection) => {
      if (this.hasEditPermission(postSection)) return;
      this.addAskButton(postSection);
      const summaryButton = this.addSummaryButton(postSection);
      this.addCommentSummaryButton(postSection);

      // 可選功能(目前註解)
      // this.addSkipFloorButton(postSections, postSection);
      // this.addSummaryButtonLeft(postSection, summaryButton);
    });
  }

  /**
   * 獲取文章區塊
   */
  getPostSections() {
    return Array.from(document.querySelectorAll(".c-section")).filter(
      (section) => section.querySelector(".c-post__body")
    );
  }

  /**
   * 檢查是否已經新增按鈕
   */
  hasEditPermission(postSection) {
    const editIcon = postSection.querySelectorAll(".lazyBtn");
    return editIcon !== null && editIcon.length > 0;
  }

  /**
   * 添加懶人包按鈕
   */
  addSummaryButton(postSection) {
    const postBody = postSection.querySelector(".c-post__body");
    const footerRight = postBody.querySelector(".article-footer_right");

    const summaryButton = this.createButton({
      text: "懶人包",
      icon: "description",
      id: `lazy-summary-${postBody.querySelector(".c-article").id}`,
      insertPosition: "first",
    });

    footerRight.insertBefore(summaryButton, footerRight.firstChild);

    summaryButton.addEventListener("click", async () => {
      await this.handleSummaryClick(summaryButton, postBody);
    });

    return summaryButton;
  }
  /**
   * 添加跳過樓層 - 按需檢測版本
   */
  addSkipFloorButton() {
    //檢查按鈕是否已經存在
    if (document.getElementById("floating-skip-button")) {
      // remove
      document.getElementById("floating-skip-button").remove();
    }
    // 創建右側浮動的跳過按鈕
    const floatingSkipButton = this.createFloatingSkipButton();
    document.body.appendChild(floatingSkipButton);

    // 點擊事件處理 - 只在點擊時檢查當前樓層
    floatingSkipButton.addEventListener("click", () => {
      const cPageWorker = new CPageWorker(this.settings);
      const postSections = cPageWorker.getPostSections();
      const currentSection = this.findCurrentVisibleSection(postSections);

      if (currentSection) {
        const currentIndex = Array.from(postSections).indexOf(currentSection);
        const nextSection = postSections[currentIndex + 1];

        if (nextSection) {
          // 暫時禁止點擊
          floatingSkipButton.disabled = true;
          this.scrollToElement(nextSection, 2);
          // 700毫秒後恢復
          setTimeout(() => {
            floatingSkipButton.disabled = false;
          }, 700);
          this.animateButtonClick(floatingSkipButton);
        } else {
          // 已到最後一樓
          this.handleLastFloor(currentSection, floatingSkipButton);
        }
      }
    });
  }
  /**
   * 創建浮動跳過按鈕
   */
  createFloatingSkipButton() {
    const button = document.createElement("button");
    button.id = "floating-skip-button";
    button.innerHTML = `
      <i class="fa fa-arrow-down"></i>
      <span>跳過此樓</span>
    `;
    // 添加CSS動畫到頁面
    if (!document.getElementById("arrow-bounce-style")) {
      const style = document.createElement("style");
      style.id = "arrow-bounce-style";
      style.textContent = `
        @keyframes arrowBounce {
          0%, 100% { transform: translateY(0); }
          25% { transform: translateY(-3px); }
          50% { transform: translateY(2px); }
          75% { transform: translateY(-1px); }
        }
      `;
      document.head.appendChild(style);
    }

    // 設置按鈕樣式
    Object.assign(button.style, {
      position: "fixed",
      right: "20px",
      bottom: "300px",
      transform: "translateY(-50%)",
      zIndex: "9999",
      backgroundColor: "var(--primary)",
      color: "var(--primary-text)",
      border: "none",
      borderRadius: "50px",
      padding: "12px 16px",
      cursor: "pointer",
      boxShadow: "0 4px 12px rgba(0,0,0,0.3)",
      display: "flex",
      alignItems: "center",
      gap: "8px",
      fontSize: "14px",
      fontWeight: "500",
      transition: "all 0.3s ease",
      opacity: "0.8",
    });

    // 懸停效果 - 帶箭頭跳動動畫
    button.addEventListener("mouseenter", () => {
      // 為箭頭添加跳動動畫
      const arrow = button.querySelector("i");
      if (arrow) {
        arrow.style.animation = "arrowBounce 0.6s ease-in-out";
      }
    });

    button.addEventListener("mouseleave", () => {
      // 移除箭頭動畫
      const arrow = button.querySelector("i");
      if (arrow) {
        arrow.style.animation = "";
      }
    });

    return button;
  }
  /**
   * 找出當前在視野中的樓層
   */
  findCurrentVisibleSection(postSections) {
    // 使用你現有的 isElementInViewport 函式
    for (let i = 0; i < postSections.length; i++) {
      const section = postSections[i];
      if (UtilityFunctions.isInViewport(section)) {
        return section;
      }
    }

    // 如果沒有找到完全可見的,找最接近視窗頂部的
    return this.findClosestSection(postSections);
  }

  /**
   * 找出最接近視窗頂部的樓層(備用方案)
   */
  findClosestSection(postSections) {
    let closestSection = null;
    let minDistance = Infinity;

    postSections.forEach((section) => {
      const rect = section.getBoundingClientRect();
      const distance = Math.abs(rect.top);

      if (distance < minDistance) {
        minDistance = distance;
        closestSection = section;
      }
    });

    return closestSection;
  }
  /**
   * 按鈕點擊動畫效果
   */
  animateButtonClick(button) {
    button.style.transform = "translateY(-50%) scale(0.95)";
    setTimeout(() => {
      button.style.transform = "translateY(-50%) scale(1)";
    }, 150);
  }
  /**
   * 處理到達最後一樓的情況
   */
  handleLastFloor(lastSection, button) {
    const footer = lastSection.querySelector(".c-post__footer");

    if (footer) {
      // 滾動到 footer 元素
      this.scrollToElement(footer);
      this.animateButtonClick(button);

      // 更新按鈕狀態
      button.style.opacity = "0.6";
      button.innerHTML = `
      <i class="fa fa-anchor"></i>
      <span>已到樓底</span>
    `;

      // 3秒後恢復按鈕狀態
      setTimeout(() => {
        button.style.opacity = "0.8";
        button.innerHTML = `
        <i class="fa fa-arrow-down"></i>
        <span>跳過此樓</span>
      `;
      }, 3000);
    } else {
      // 如果找不到 footer,就滾動到樓層底部
      this.handleLastFloorFallback(lastSection, button);
    }
  }
  /**
   * 處理找不到 footer 的備用方案
   */
  handleLastFloorFallback(lastSection, button) {
    // 滾動到樓層元素的底部
    const elementBottom = lastSection.offsetTop + lastSection.offsetHeight;
    window.scrollTo({
      top: elementBottom - window.innerHeight + 100, // 留一點邊距
      behavior: "smooth",
    });

    this.animateButtonClick(button);

    // 更新按鈕狀態
    button.style.opacity = "0.5";
    button.innerHTML = `
      <i class="fa fa-check"></i>
      <span>已到底部</span>
    `;

    // 3秒後恢復按鈕狀態
    setTimeout(() => {
      button.style.opacity = "0.8";
      button.innerHTML = `
        <i class="fa fa-arrow-down"></i>
        <span>跳過此樓</span>
      `;
    }, 3000);
  }

  /**
   * 處理懶人包按鈕點擊
   */
  async handleSummaryClick(button, postBody) {
    this.scrollToElement(button);

    if (button.querySelector("p").textContent === "產生中...") return;

    if (!this.validateApiKey()) return;

    const articleId = postBody.querySelector(".c-article").id;
    const cleanId = `${articleId}-clean`;

    // 處理展開/摺疊邏輯
    if (this.handleToggleLogic(button, cleanId)) return;

    // 生成懶人包
    await this.generateSummary(button, postBody, articleId);
  }

  /**
   * 生成懶人包
   */
  async generateSummary(button, postBody, articleId) {
    button.querySelector("p").textContent = "產生中...";

    const articleContent = this.extractArticleContent(postBody);
    const customPrompt = this.settings.get("custom_oaiPrompt");
    const prompt = customPrompt || this.settings.get("oaiPrompt");

    const { response, data } = await this.sendGptRequest(
      prompt,
      `文章內容:\`\`\`${articleContent}\`\`\``
    );

    if (!response) {
      button.querySelector("p").textContent = "懶人包";
      return;
    }

    const summaryArticle = this.createSummaryArticle(
      `${articleId}-clean`,
      data.choices[0].message.content
    );

    button.querySelector("p").textContent = "摺疊 ▲";
    postBody.appendChild(summaryArticle);

    await this.animateElement(summaryArticle, true);
  }

  /**
   * 添加留言統整按鈕
   */
  addCommentSummaryButton(postSection) {
    const postBody = postSection.querySelector(".c-post__body");
    const replyHead = postSection.querySelector(".c-reply__head");

    if (!replyHead) return;

    const commentButton = this.createButton({
      text: "留言統整",
      icon: "forum",
      id: `lazy-summaryCmd-${postBody.querySelector(".c-article").id}`,
      className: "article-footer_right-btn",
      style: { margin: "0.3rem 0.5rem 0rem 0rem" },
    });

    replyHead.appendChild(commentButton);

    commentButton.addEventListener("click", async () => {
      await this.handleCommentSummaryClick(
        commentButton,
        postBody,
        postSection
      );
    });
  }

  /**
   * 處理留言統整按鈕點擊
   */
  async handleCommentSummaryClick(button, postBody, postSection) {
    this.scrollToElement(button);

    if (button.querySelector("p").textContent === "產生中...") return;

    if (!this.validateApiKey()) return;

    const postId = postBody.querySelector(".c-article").id.replace("cf", "");
    const cleanCmdId = `${postId}-cleanCmd`;

    // 處理展開/摺疊邏輯
    if (this.handleToggleLogic(button, cleanCmdId, "留言統整")) return;

    // 生成留言統整
    await this.generateCommentSummary(button, postId, postSection);
  }

  /**
   * 生成留言統整
   */
  async generateCommentSummary(button, postId, postSection) {
    button.querySelector("p").textContent = "產生中...";

    const commentData = await this.getCommentData(postId);
    const customPrompt = this.settings.get("custom_oaiPromptCmd");
    const prompt = customPrompt || this.settings.get("oaiPromptCmd");

    const { response, data } = await this.sendGptRequest(
      prompt,
      `對話內容:\n \`\`\`${commentData.textContent}\n\`\`\``
    );

    if (!response) {
      button.querySelector("p").textContent = "留言統整";
      return;
    }

    const processedContent = this.restoreOriginalFormat(
      data.choices[0].message.content,
      commentData.textContentOrigin
    );

    const summaryArticle = this.createCommentSummaryArticle(
      `${postId}-cleanCmd`,
      processedContent
    );

    button.querySelector("p").textContent = "摺疊 ▲";

    const insertBefore = document.getElementById(`Commendlist_${postId}`);
    postSection
      .querySelector(".c-post__footer")
      .insertBefore(summaryArticle, insertBefore);

    await this.animateElement(summaryArticle, true);
  }

  /**
   * 添加問問按鈕
   */
  addAskButton(postSection) {
    const postBody = postSection.querySelector(".c-post__body");
    const footerRight = postBody.querySelector(".article-footer_right");

    // 創建對話輸入區
    const { askInput, chatArea, askTextarea } =
      this.createChatInterface(postBody);

    // 創建問問按鈕
    const askButton = this.createButton({
      text: "問問 ▼",
      icon: "chat",
      id: `ask-${postBody.querySelector(".c-article").id}`,
      insertPosition: "first",
    });

    footerRight.insertBefore(askButton, footerRight.firstChild);

    // 設置事件監聽器
    this.setupAskButtonEvents(
      askButton,
      askInput,
      chatArea,
      askTextarea,
      postBody
    );
  }

  /**
   * 創建聊天介面
   */
  createChatInterface(postBody) {
    // 創建輸入區
    const askInput = document.createElement("div");
    askInput.classList.add("c-reply__editor");

    const replyInput = document.createElement("div");
    replyInput.classList.add("reply-input");

    const askTextarea = document.createElement("textarea");
    askTextarea.classList.add("content-edit");
    askTextarea.placeholder = "詢問⋯";

    replyInput.appendChild(askTextarea);
    askInput.appendChild(replyInput);
    postBody.appendChild(askInput);

    this.animateElement(askInput, false);

    // 創建聊天區域
    const chatArea = document.createElement("div");
    chatArea.classList.add("chatArea");
    chatArea.style.overflow = "hidden";

    postBody.insertBefore(chatArea, askInput);
    this.animateElement(chatArea, false);

    return { askInput, chatArea, askTextarea };
  }

  /**
   * 設置問問按鈕事件
   */
  setupAskButtonEvents(askButton, askInput, chatArea, askTextarea, postBody) {
    // 按鈕點擊事件
    askButton.addEventListener("click", async () => {
      this.scrollToElement(askButton);

      if (!this.validateApiKey()) return;

      const isExpanded = askButton.querySelector("p").textContent === "問問 ▲";

      this.toggleElement(askInput);
      this.toggleElement(chatArea);

      askButton.querySelector("p").textContent = isExpanded
        ? "問問 ▼"
        : "問問 ▲";

      if (!isExpanded) {
        askTextarea.focus();
      }
    });

    // 輸入框按鍵事件
    askTextarea.addEventListener("keydown", async (e) => {
      if (e.key === "Enter" && !e.shiftKey) {
        e.preventDefault();
        await this.handleAskQuestion(askTextarea, chatArea, postBody);
      }
    });
  }

  /**
   * 處理問問功能
   */
  async handleAskQuestion(askTextarea, chatArea, postBody) {
    if (!this.validateApiKey()) return;
    if (askTextarea.placeholder !== "詢問⋯") return;

    const userInput = askTextarea.value;
    if (!userInput.trim()) return;

    askTextarea.placeholder = "載入中⋯";
    askTextarea.value = "";

    const gptArray = this.buildChatGptArray(postBody, chatArea, userInput);

    const { response, data } = await this.sendGptArrayRequest(gptArray);

    if (!response) {
      askTextarea.placeholder = "詢問⋯";
      askTextarea.value = userInput;
      return;
    }

    // 添加用戶問題
    this.addChatMessage(chatArea, userInput, "user-ask");

    // 添加AI回答
    this.addChatMessage(chatArea, data.choices[0].message.content, "gpt-reply");

    // 更新聊天區域高度
    this.updateChatAreaHeight(chatArea);

    askTextarea.placeholder = "詢問⋯";
    askTextarea.focus();
  }

  /**
   * 構建聊天GPT陣列
   */
  buildChatGptArray(postBody, chatArea, userInput) {
    const gptArray = [];
    const customPrompt = this.settings.get("custom_oaiPromptChat");
    const prompt = customPrompt || this.settings.get("oaiPromptChat");
    const useSystemMode = this.settings.getBool("oaiPromptSystemMode");

    // 添加系統提示
    gptArray.push({
      role: useSystemMode ? "system" : "user",
      content: prompt,
    });

    if (!useSystemMode) {
      gptArray.push({
        role: "assistant",
        content: "好的,請提供文章。",
      });
    }

    // 添加文章內容
    const articleContent = this.extractArticleContent(postBody);
    gptArray.push({
      role: "user",
      content: `文章內容:\n\`\`\`\n${articleContent}\n\`\`\``,
    });

    // 添加聊天歷史
    const chatHistory = chatArea.querySelectorAll(".chatHistory");
    chatHistory.forEach((chat) => {
      const role = chat.classList.contains("user-ask") ? "user" : "assistant";
      const content = chat.querySelector(".c-article__content").textContent;
      gptArray.push({ role, content });
    });

    // 添加當前問題
    gptArray.push({
      role: "user",
      content: userInput,
    });

    return gptArray;
  }

  /**
   * 添加聊天訊息
   */
  addChatMessage(chatArea, content, type) {
    const messageArticle = document.createElement("article");
    messageArticle.classList.add("c-article", "FM-P2", "chatHistory", type);
    messageArticle.id = `chat-${Date.now()}-${Math.random()
      .toString(36)
      .substr(2, 9)}`;

    Object.assign(messageArticle.style, {
      display: "block",
      minHeight: "0px",
      marginBottom: type === "user-ask" ? "0.8rem" : "1.6rem",
      borderBottom: `1px solid ${
        type === "user-ask" ? "var(--primary-text)" : "var(--primary)"
      }`,
    });

    const messageContent = document.createElement("div");
    messageContent.classList.add("c-article__content");
    messageContent.style.whiteSpace = "pre-wrap";
    messageContent.innerHTML = content;

    messageArticle.appendChild(messageContent);
    chatArea.appendChild(messageArticle);
  }

  /**
   * 更新聊天區域高度
   */
  updateChatAreaHeight(chatArea) {
    requestAnimationFrame(() => {
      chatArea.style.readHeight = `${chatArea.scrollHeight}px`;
      chatArea.style.maxHeight = `${chatArea.scrollHeight}px`;
    });
  }

  /**
   * 獲取留言資料
   */
  async getCommentData(postId) {
    let commentElements = document
      .getElementById(`Commendlist_${postId}`)
      .querySelectorAll(".c-reply__item");

    // 展開留言
    const showButton = document.getElementById(`showoldCommend_${postId}`);
    if (
      showButton &&
      (showButton.style.display === "block" || showButton.style.display === "")
    ) {
      const initialCount = commentElements.length;
      showButton.click();

      await new Promise((resolve) => {
        const observer = new MutationObserver(() => {
          const currentElements = document
            .getElementById(`Commendlist_${postId}`)
            .querySelectorAll(".c-reply__item");

          if (currentElements.length >= initialCount) {
            commentElements = currentElements;
            document.getElementById(`closeCommend_${postId}`).click();
            observer.disconnect();
            resolve();
          }
        });

        observer.observe(document.getElementById(`Commendlist_${postId}`), {
          childList: true,
          subtree: true,
          characterData: true,
        });
      });

      document.getElementById(`closeCommend_${postId}`).click();
    }

    // 處理留言內容
    let textContent = "";
    const textContentOrigin = Array.from(commentElements)
      .map((node) => node.innerHTML)
      .join("");

    commentElements.forEach((node) => {
      const user = node.querySelector(".reply-content__user").innerHTML;
      const comment = node.querySelector(".comment_content").innerHTML;
      textContent += `@${user}:${comment}\n`;
    });

    // 清理格式
    textContent = textContent.replace(/\n+/g, "\n");
    textContent = this.processCommentReferences(textContent);

    return { textContent, textContentOrigin };
  }

  /**
   * 處理留言引用格式
   */
  processCommentReferences(textContent) {
    const patterns = [
      {
        regex: /([^<]+)\((.*?)\)<\/a>/g,
        replacement: (match, prefix, name) => `回應@${name} => `,
      },
      {
        regex: /([^<]+)<\/a>/g,
        replacement: (match, name) => `回應@${name},`,
      },
    ];

    patterns.forEach(({ regex, replacement }) => {
      textContent = textContent.replace(regex, replacement);
    });

    return textContent;
  }

  /**
   * 還原原始格式
   */
  restoreOriginalFormat(textContent, originalContent) {
    const nameToHtmlMap = new Map();
    const htmlPattern = /([^<]+)<\/a>/g;
    let match;

    while ((match = htmlPattern.exec(originalContent)) !== null) {
      nameToHtmlMap.set(match[1], match[0]);
    }

    let processedText = textContent;
    nameToHtmlMap.forEach((html, name) => {
      const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
      const atPattern = new RegExp(`@${escapedName}`, "g");
      processedText = processedText.replace(atPattern, html);
    });

    return processedText;
  }

  /**
   * 更新提示詞
   */
  async updatePrompts() {
    const today = new Date();
    const lastUpdate = this.settings.get("oaiPromptUpdateDate");
    const sleepDays = parseInt(this.settings.get("oaiPromptUpdateSleep"));

    const daysDiff = Math.floor(
      (today -
        new Date(lastUpdate.replace(/(\d{4})(\d{2})(\d{2})/, "$1-$2-$3"))) /
        (1000 * 60 * 60 * 24)
    );

    if (daysDiff < sleepDays) return;

    try {
      const response = await fetch(this.settings.get("oaiPromptUpdateURL"));
      if (!response.ok) {
        console.error("[ERROR] fetching prompt:", response.status);
        return;
      }

      const data = await response.json();
      const todayString = today.toISOString().slice(0, 10).replace(/-/g, "");

      this.settings.set("oaiPromptUpdateDate", todayString);

      if (this.settings.get("oaiPromptDate") >= data.oaiPromptDate) return;

      // 更新提示詞
      this.settings.set("oaiPromptDate", data.oaiPromptDate);
      this.settings.set("oaiPrompt", data.oaiPrompt);
      this.settings.set("oaiPromptUpdateSleep", data.oaiPromptUpdateSleep);
      this.settings.set("oaiPromptCmd", data.oaiPromptCmd);
    } catch (error) {
      console.error("[ERROR] fetching prompt:", error);
    }
  }

  /**
   * 發送GPT請求
   */
  async sendGptRequest(systemPrompt, userPrompt) {
    const useSystemMode = this.settings.getBool("oaiPromptSystemMode");
    const messages = [
      {
        role: useSystemMode ? "system" : "user",
        content: systemPrompt,
      },
      {
        role: "user",
        content: userPrompt,
      },
    ];

    return this.makeGptRequest(messages);
  }

  /**
   * 發送GPT陣列請求
   */
  async sendGptArrayRequest(messages) {
    return this.makeGptRequest(messages);
  }

  /**
   * 執行GPT請求
   */
  async makeGptRequest(messages) {
    return new Promise((resolve) => {
      const apiKey = this.settings.get("oaiKey");

      GM_xmlhttpRequest({
        method: "POST",
        url: this.settings.get("oaiBaseUrl"),
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${apiKey}`,
        },
        data: JSON.stringify({
          messages,
          max_tokens: 4090,
          model: this.settings.get("oaiModel"),
          stream: false,
          temperature: 0.7,
          presence_penalty: 0,
          frequency_penalty: 0,
        }),
        timeout: 30000,
        onload: (response) => {
          try {
            if (response.status !== 200) {
              console.error(`伺服器回應錯誤: ${response.status}`);
              alert("取得 GPT 回覆時發生錯誤,請稍後再試。");
              resolve({ response: false, data: null });
              return;
            }

            const data = JSON.parse(response.responseText);
            if (data?.choices?.[0]?.message?.content) {
              resolve({ response: true, data });
            } else {
              console.error("API 返回的數據格式不正確");
              alert("取得 GPT 回覆時發生錯誤,請稍後再試。");
              resolve({ response: false, data: null });
            }
          } catch (error) {
            console.error("取得 GPT 回覆時發生錯誤:", error);
            alert("取得 GPT 回覆時發生錯誤,請稍後再試。");
            resolve({ response: false, data: null });
          }
        },
        onerror: (error) => {
          console.error("取得 GPT 回覆時發生錯誤:", error);
          alert("取得 GPT 回覆時發生錯誤,請稍後再試。");
          resolve({ response: false, data: null });
        },
        ontimeout: () => {
          console.error("取得 GPT 回覆超時");
          alert("取得 GPT 回覆時發生錯誤,請稍後再試。");
          resolve({ response: false, data: null });
        },
      });
    });
  }

  /**
   * 工具方法:創建按鈕
   */
  createButton({
    text,
    icon,
    id,
    className = "article-footer_right-btn",
    style = {},
    insertPosition = null,
  }) {
    const button = document.createElement("a");
    button.classList.add(className);
    button.innerHTML = `<i class="material-icons lazyBtn">${icon}</i><p>${text}</p>`;
    button.id = id;

    Object.assign(button.style, {
      display: "flex",
      alignItems: "center",
      ...style,
    });

    return button;
  }

  /**
   * 工具方法:創建摘要文章
   */
  createSummaryArticle(id, content) {
    const article = document.createElement("article");
    article.classList.add("c-article", "FM-P2");
    article.id = id;

    Object.assign(article.style, {
      display: "block",
      overflow: "hidden",
      maxHeight: "auto",
      minHeight: "0px",
    });

    const articleContent = document.createElement("div");
    articleContent.classList.add("c-article__content");
    articleContent.style.whiteSpace = "pre-wrap";
    articleContent.innerHTML = content;

    article.appendChild(articleContent);
    return article;
  }

  /**
   * 工具方法:創建留言摘要文章
   */
  createCommentSummaryArticle(id, content) {
    const article = document.createElement("article");
    article.classList.add("c-reply__item", "c-article", "FM-P2");
    article.id = id;

    Object.assign(article.style, {
      display: "block",
      overflow: "hidden",
      maxHeight: "auto",
      minHeight: "0px",
    });

    const articleContent = document.createElement("div");
    articleContent.classList.add("c-article__content");
    articleContent.style.whiteSpace = "pre-wrap";
    articleContent.innerHTML = content;

    article.appendChild(articleContent);
    return article;
  }

  /**
   * 工具方法:提取文章內容
   */
  extractArticleContent(postBody) {
    const articleContent = postBody.querySelector(".c-article__content");
    let textContent = "";

    articleContent.childNodes.forEach((node) => {
      textContent += node.textContent.trim() + "\n";
    });

    return textContent.replace(/\n+/g, "\n");
  }

  /**
   * 工具方法:驗證API密鑰
   */
  validateApiKey() {
    const apiKey = this.settings.get("oaiKey");
    if (apiKey === "sk-yourKey" || apiKey === "") {
      alert("請先設定 API Key 才能使用 AI 功能");
      return false;
    }
    return true;
  }

  /**
   * 工具方法:處理切換邏輯
   */
  handleToggleLogic(button, elementId, defaultText = null) {
    const element = document.getElementById(elementId);
    const buttonText = button.querySelector("p").textContent;

    if (element && buttonText === "摺疊 ▲") {
      this.toggleElement(element);
      button.querySelector("p").textContent = "展開 ▼";
      return true;
    }

    if (element && buttonText === "展開 ▼") {
      this.toggleElement(element);
      button.querySelector("p").textContent = "摺疊 ▲";
      return true;
    }

    if (element && buttonText !== (defaultText || "懶人包")) {
      return true;
    }

    return false;
  }

  /**
   * 工具方法:滾動到元素
   */
  scrollToElement(element, marginOffset = 7) {
    const originalMargin = element.style.marginTop || "0px";
    element.style.marginTop = `-${marginOffset}rem`;
    element.scrollIntoView({ behavior: "smooth" });
    element.style.marginTop = originalMargin;
    // 檢查是否在視窗內,如果不是則重新滾動
    setTimeout(() => {
      if (!UtilityFunctions.isInViewport(element)) {
        this.scrollToElement(element, marginOffset);
      }
    }, 700);
  }

  /**
   * 工具方法:動畫元素
   */
  async animateElement(
    element,
    show = true,
    animation = "ud",
    waitForAppend = true
  ) {
    if (waitForAppend) {
      requestAnimationFrame(() => {
        this.setElementDimensions(element);
      });
    } else {
      this.setElementDimensions(element);
    }

    this.setupElementAnimation(element, show, animation);
  }

  /**
   * 工具方法:設置元素尺寸
   */
  setElementDimensions(element) {
    element.style.readHeight =
      element.scrollHeight === 0 ? "999px" : `${element.scrollHeight}px`;
    element.style.readWidth =
      element.scrollWidth === 0 ? "999px" : `${element.scrollWidth}px`;
  }

  /**
   * 工具方法:設置元素動畫
   */
  setupElementAnimation(element, show, animation) {
    Object.assign(element.style, {
      transition: "",
      overflow: "hidden auto",
      opacity: "0",
    });

    this.toggleElement(element, false, animation);
    element.style.transition =
      "all 0.5s cubic-bezier(0.21, 0.3, 0.18, 1.37) 0s";

    if (!show) {
      element.style.beeShow = "false";
      return;
    }

    element.style.beeShow = "true";
    element.style.opacity = "1";

    requestAnimationFrame(() => {
      element.style.maxHeight = element.style.readHeight;
    });
  }

  /**
   * 工具方法:切換元素顯示
   */
  toggleElement(element, show = null, animation = "ud") {
    const shouldShow =
      show === null ? !(element.style.beeShow === "true") : show;

    if (shouldShow) {
      Object.assign(element.style, {
        opacity: "1",
        maxHeight: element.style.readHeight,
        maxWidth: element.style.readWidth,
        transform: "translateX(0px) translateY(0px)",
        beeShow: "true",
      });
    } else {
      element.style.beeShow = "false";
      element.style.opacity = "0";

      if (animation.includes("u")) {
        element.style.maxHeight = "0px";
        if (animation.startsWith("d")) {
          element.style.transform = `translateX(0px) translateY(${element.style.readWidth}px)`;
        }
      }

      if (animation.includes("l")) {
        element.style.maxWidth = "0px";
        if (animation.startsWith("r")) {
          element.style.transform = `translateX(${element.style.readHeight}) translateY(0px)`;
        }
      }
    }
  }
}
/**
 * 設定管理與UI模組
 * 負責插件設定介面、提示系統、檢舉提醒等功能
 */
class SettingsUIManager {
  constructor(settings) {
    this.settings = settings;
  }

  /**
   * 添加設定元素到頁面
   */
  async addSettingElement(isNewVersion) {
    const uiElements = this.createUIElements(isNewVersion);
    if (!uiElements) return;

    const { navAdd, settingsContainer } = uiElements;

    this.setupEventListeners(navAdd, settingsContainer, isNewVersion);
    this.createSettingsContent(settingsContainer, isNewVersion);

    await this.initializeSettingsContainer(settingsContainer);
  }

  /**
   * 創建UI元素
   */
  createUIElements(isNewVersion) {
    if (isNewVersion) {
      return this.createNewVersionUI();
    } else if (document.querySelector(".b-list") !== null) {
      return this.createOldVersionUI();
    }
    return null;
  }

  /**
   * 創建新版UI
   */
  createNewVersionUI() {
    const navAddTag = document.querySelector(".forum-nav-main");
    const settingsWarp = document.querySelector(".forum-header");

    if (!navAddTag || !settingsWarp) return null;

    // 創建設定按鈕
    const navAdd = document.createElement("li");
    navAdd.className = "forum-nav-link forum-nav-rules beeSettingTag";
    navAdd.innerHTML = "插件設定";
    navAdd.style.cursor = "pointer";
    navAddTag.appendChild(navAdd);

    // 創建設定容器
    const settingsContainer = this.createSettingsContainer(
      "forum-filter-box beeSettingWarp"
    );
    settingsWarp.appendChild(settingsContainer);

    // 添加提示標題
    const sectionTitle = document.createElement("h3");
    sectionTitle.className = "section-title";
    sectionTitle.textContent = "滾動下拉還有哦!";
    sectionTitle.style.margin = "0.6rem 0 0.7rem 0.7rem";
    settingsContainer.appendChild(sectionTitle);

    return { navAdd, settingsContainer };
  }

  /**
   * 創建舊版UI
   */
  createOldVersionUI() {
    const navAddTag = document.querySelector(".BH-menuE");
    const settingsWarp = document.querySelector(".b-list-wrap");

    if (!navAddTag || !settingsWarp) return null;

    // 創建設定按鈕
    const navAdd = document.createElement("li");
    navAdd.className = "beeSettingTag";
    navAdd.innerHTML = "插件設定";
    navAdd.style.cursor = "pointer";
    navAddTag.appendChild(navAdd);

    // 創建設定容器
    const settingsContainer = this.createSettingsContainer(
      "forum-filter-box beeSettingWarp"
    );
    settingsWarp.insertBefore(settingsContainer, settingsWarp.firstChild);

    // 添加提示標題
    const sectionTitle = document.createElement("h3");
    sectionTitle.className = "section-title";
    sectionTitle.textContent =
      "插件設定(再點一次上方的【插件設定】即可返回【文章列表】)";
    sectionTitle.style.margin = "0.6rem 0 0.7rem 0.7rem";
    settingsContainer.appendChild(sectionTitle);

    return { navAdd, settingsContainer };
  }

  /**
   * 創建設定容器
   */
  createSettingsContainer(className) {
    const container = document.createElement("div");
    container.className = className;

    Object.assign(container.style, {
      maxHeight: "0px",
      overflow: "hidden auto",
    });

    return container;
  }

  /**
   * 設置事件監聽器
   */
  setupEventListeners(navAdd, settingsContainer, isNewVersion) {
    navAdd.addEventListener("click", () => {
      if (isNewVersion) {
        this.toggleNewVersionSettings(settingsContainer);
      } else {
        this.toggleOldVersionSettings(settingsContainer);
      }
    });
  }

  /**
   * 切換新版設定顯示
   */
  toggleNewVersionSettings(container) {
    if (container.style.maxHeight === "0px") {
      container.style.maxHeight = "60vh";
      container.style.opacity = "1";
    } else {
      container.style.maxHeight = "0px";
      container.style.opacity = "0";
    }
  }

  /**
   * 切換舊版設定顯示
   */
  toggleOldVersionSettings(container) {
    const animationManager = new AnimationManager();
    animationManager.popElement(container, "toggle", "ud");

    const scrollTarget =
      document.getElementById("BH-master") ||
      document.querySelector(".b-list-wrap");
    if (scrollTarget) {
      this.scrollToElement(scrollTarget, 7);
    }
  }

  /**
   * 創建設定內容
   */
  createSettingsContent(container, isNewVersion) {
    this.addBasicSettings(container, isNewVersion);
    this.addLayoutSettings(container);
    this.addAISettings(container);
    this.addMiscSettings(container, isNewVersion);
    this.addReloadButton(container, isNewVersion);
  }

  /**
   * 添加基本設定
   */
  addBasicSettings(container, isNewVersion) {
    if (!isNewVersion) {
      container.appendChild(
        this.createItemCard("add_function", "標題後方插入功能按鈕")
      );
      container.appendChild(
        this.createItemCard("preview_auto", "點擊文章時使用即時瀏覽")
      );
      container.appendChild(
        this.createItemCard(null, null, {
          inputId: "preview_size",
          labelText: " └ 即時瀏覽視窗的大小",
        })
      );
    } else {
      container.appendChild(
        this.createItemCard("cleanMode", "清爽模式(隱藏文章描述和縮圖)")
      );
      container.appendChild(
        this.createItemCard(null, null, {
          inputId: "cleanModeSize",
          labelText: " └ 清爽模式文章清單大小",
        })
      );
      container.appendChild(
        this.createItemCard(null, null, {
          inputId: "preview_size",
          labelText: "即時瀏覽視窗的大小",
        })
      );
    }

    container.appendChild(
      this.createItemCard("preview_LR", "即時瀏覽從右方彈出(取消則從左)")
    );
  }

  /**
   * 添加版面設定
   */
  addLayoutSettings(container) {
    container.appendChild(
      this.createItemCard("new_design", "自訂板面大小(附加浮動型聊天室)")
    );

    const layoutSettings = [
      {
        inputId: "new_design_box",
        labelText: " └ 整體顯示區域佔比(文章+聊天室佔整個畫面的比例,< 100%)",
      },
      {
        inputId: "new_design_box_Left",
        labelText: " ├ 文章佔比(與聊天室佔比總和 <= 100%)",
      },
      {
        inputId: "new_design_box_Right",
        labelText: " └ 聊天室佔比",
      },
    ];

    layoutSettings.forEach((setting) => {
      container.appendChild(this.createItemCard(null, null, setting));
    });

    container.appendChild(
      this.createItemCard("new_design_LRSwitch", "聊天室在左方")
    );
  }

  /**
   * 添加AI設定
   */
  addAISettings(container) {
    container.appendChild(
      this.createItemCard(
        "addSummaryBtn",
        "跳過樓層按鈕/AI總結(AI功能需自備KEY填入下方)"
      )
    );

    const aiSettings = [
      { inputId: "oaiBaseUrl", labelText: " ├ oai URL" },
      { inputId: "oaiModel", labelText: " ├ oai model" },
      { inputId: "oaiKey", labelText: " ├ oai key" },
      {
        inputId: "custom_oaiPrompt",
        labelText: " ├ 「懶人包」提示詞(留空=預設)",
      },
      {
        inputId: "custom_oaiPromptCmd",
        labelText: " ├ 「留言統整」自訂提示詞(留空=預設)",
      },
      {
        inputId: "custom_oaiPromptChat",
        labelText: " ├ 「問問」自訂提示詞(留空=預設)",
      },
    ];

    aiSettings.forEach((setting) => {
      container.appendChild(this.createItemCard(null, null, setting));
    });

    container.appendChild(
      this.createItemCard("oaiPromptSystemMode", "├ 自訂提示詞使用 system 模式")
    );

    container.appendChild(
      this.createItemCard(null, null, {
        inputId: "oaiPromptUpdateURL",
        labelText: " └ oai prompt settings URL",
      })
    );
  }

  /**
   * 添加雜項設定
   */
  addMiscSettings(container, isNewVersion) {
    if (!isNewVersion) {
      container.appendChild(
        this.createItemCard("addBorderInPicMode", "縮圖列表模式中,加上分隔線")
      );
      container.appendChild(
        this.createItemCard("showAbuse", "有檢舉時,自動以即時瀏覽開啟")
      );
    }

    container.appendChild(this.createItemCard("showTips", "重新觀看TIPs"));
  }

  /**
   * 添加重載按鈕
   */
  addReloadButton(container, isNewVersion) {
    const reloadBtn = document.createElement("button");
    reloadBtn.textContent = "重整頁面以生效";

    if (!isNewVersion) {
      reloadBtn.style.margin = "0.5rem 0 0.7rem 0.7rem";
      reloadBtn.style.color = "white";
    }

    reloadBtn.addEventListener("click", () => {
      location.reload();
    });

    const reloadBtnDiv = document.createElement("div");
    reloadBtnDiv.className = isNewVersion
      ? "btn btn-primary"
      : "BH-rbox BH-qabox1";
    reloadBtnDiv.appendChild(reloadBtn);
    container.appendChild(reloadBtnDiv);
  }

  /**
   * 創建設定項目卡片
   */
  createItemCard(inputId, labelText, additionalContent = null) {
    const itemCard = document.createElement("div");
    itemCard.className =
      "item-card management_guild-check single-choice forum-filter-group";

    const checkGroup = document.createElement("div");
    checkGroup.className = "check-group";
    checkGroup.style.margin = "0rem 0 0.1rem 0.7rem";

    if (inputId) {
      this.createCheckboxInput(checkGroup, inputId, labelText);
    }

    if (additionalContent) {
      this.createTextInput(checkGroup, additionalContent);
    }

    itemCard.appendChild(checkGroup);
    return itemCard;
  }

  /**
   * 創建複選框輸入
   */
  createCheckboxInput(container, inputId, labelText) {
    const input = document.createElement("input");
    input.id = inputId;
    input.type = "checkbox";
    input.checked = this.settings.getBool(inputId);

    const label = document.createElement("label");
    label.htmlFor = inputId;
    label.className = "is-active";

    const labelIcon = document.createElement("div");
    labelIcon.className = "label-icon";

    const icon = document.createElement("i");
    icon.className = "fa fa-check";
    labelIcon.appendChild(icon);

    const h6 = document.createElement("h6");
    h6.textContent = labelText;

    Object.assign(h6.style, {
      display: "inline-block",
      color: "var(--primary-text)",
      fontSize: "100%",
    });

    label.appendChild(labelIcon);
    label.appendChild(h6);
    container.appendChild(input);
    container.appendChild(label);

    // 添加事件監聽器
    input.addEventListener("input", () => {
      this.settings.set(inputId, input.checked.toString());
    });
  }

  /**
   * 創建文字輸入
   */
  createTextInput(container, config) {
    const h6 = document.createElement("h6");
    h6.textContent = config.labelText;
    h6.style.display = "inline-block";
    container.appendChild(h6);

    const input = document.createElement("input");
    input.className = "form-control";
    input.id = config.inputId;
    input.type = "text";
    input.size = 25;

    Object.assign(input.style, {
      margin: "0px",
      width: config.inputId.startsWith("custom_") ? "auto" : "70px",
    });

    input.value = this.settings.get(config.inputId) || "";
    container.appendChild(input);

    // 添加事件監聽器
    input.addEventListener("input", () => {
      this.settings.set(config.inputId, input.value);
    });
  }

  /**
   * 初始化設定容器
   */
  async initializeSettingsContainer(container) {
    const animationManager = new AnimationManager();
    await animationManager.popElementInit(container, false, "ud");
  }

  /**
   * 滾動到元素
   */
  scrollToElement(element, marginOffset = 7) {
    const originalMargin = element.style.marginTop || "0px";
    element.style.marginTop = `-${marginOffset}rem`;
    element.scrollIntoView({ behavior: "smooth" });
    element.style.marginTop = originalMargin;

    setTimeout(() => {
      if (!UtilityFunctions.isInViewport(element)) {
        this.scrollToElement(element, marginOffset);
      }
    }, 300);
  }
}

/**
 * 提示系統管理器
 */
class TipsManager {
  constructor(settings) {
    this.settings = settings;
  }

  /**
   * 檢查並載入提示
   */
  checkTips(isNewVersion) {
    if (this.shouldShowBPageTips()) {
      this.loadBPageTips();
      this.settings.set("showTips", "false");
    }

    if (this.shouldShowHomeTips()) {
      this.loadHomeTips();
      this.settings.set("homeTips", "false");
    }
  }

  /**
   * 檢查是否應顯示B頁提示
   */
  shouldShowBPageTips() {
    return (
      window.location.href.includes("forum.gamer.com.tw/B.php") &&
      this.settings.getBool("showTips")
    );
  }

  /**
   * 檢查是否應顯示首頁提示
   */
  shouldShowHomeTips() {
    return (
      window.location.href.includes("www.gamer.com.tw") &&
      this.settings.getBool("homeTips")
    );
  }

  /**
   * 載入B頁提示
   */
  loadBPageTips() {
    this.loadDriverJS(() => {
      this.createBPageTour();
    });
  }

  /**
   * 載入首頁提示
   */
  loadHomeTips() {
    this.loadDriverJS(() => {
      this.createHomeTour();
    });
  }

  /**
   * 載入Driver.js庫
   */
  loadDriverJS(callback) {
    // 載入CSS
    const link = document.createElement("link");
    link.rel = "stylesheet";
    link.href = "https://cdn.jsdelivr.net/npm/[email protected]/dist/driver.css";
    document.head.appendChild(link);

    // 載入JS
    const script = document.createElement("script");
    script.src =
      "https://cdn.jsdelivr.net/npm/[email protected]/dist/driver.js.iife.js";
    script.onload = callback;
    document.head.appendChild(script);
  }

  /**
   * 創建B頁導覽
   */
  createBPageTour() {
    const picMode = document.querySelectorAll(".imglist-text").length !== 0;
    const driver = window.driver.js.driver;

    const driverObj = driver({
      showButtons: ["next", "previous"],
      allowClose: false,
      nextBtnText: "▶",
      prevBtnText: "◀",
      doneBtnText: "好耶",
      showProgress: true,
      steps: this.getBPageTourSteps(picMode),
    });

    driverObj.drive();
  }

  /**
   * 獲取B頁導覽步驟
   */
  getBPageTourSteps(picMode) {
    return [
      {
        element: ".beeSettingTag",
        popover: {
          title: "客製化設定",
          description:
            "在這裡可以進行詳細的個人設定,設定變更後需要【重新整理】頁面才會生效。",
        },
      },
      {
        element: picMode
          ? "#BH-master > form > div > table > tbody > tr > td.b-list__main > div > div > p"
          : "#BH-master > form > div > table > tbody > tr > td.b-list__main > a",
        popover: {
          title: "即時瀏覽",
          description:
            "如果開啟「點擊時使用即時預覽」,文章標題的跳轉會以即時預覽的方式啟動。",
          side: "bottom",
        },
      },
      {
        element:
          "#BH-master > form > div > table > tbody > tr > td.b-list__main",
        popover: {
          title: "快速選取",
          description:
            "除了文章標題、縮圖模式的預覽圖,其他區域可以觸發快速選取。功能等同左方的勾選方塊。",
          side: "bottom",
          onNextClick: () => {
            this.showFunctionButtons();
            driverObj.moveNext();
          },
        },
      },
      {
        element: picMode
          ? "#BH-master > form > div > table > tbody > tr:nth-child(2) > td:nth-child(3)"
          : "#BH-master > form > div > table > tbody > tr:nth-child(2) > td:nth-child(3)",
        popover: {
          title: "功能按鈕",
          description:
            "如果開啟「插入功能按鈕」,指標指向的文章後方會出現三個功能按鈕,分別是「即時預覽」「新分頁開啟」「複製連結」。",
          side: "bottom",
          onNextClick: () => {
            this.hideFunctionButtons();
            this.clickPreviewButton(picMode);
            driverObj.moveNext();
          },
        },
      },
      {
        element: "#BH-master > form > section:last-child > div",
        popover: {
          title: "功能選單",
          description: "快速預覽視窗中,功能選單會漂浮在下方,方便使用!",
          side: "bottom",
          onPrevClick: () => {
            this.closePreviewer();
            this.showFunctionButtons();
            driverObj.movePrevious();
          },
          onNextClick: () => {
            this.closePreviewer();
            driverObj.moveNext();
          },
        },
      },
    ];
  }

  /**
   * 顯示功能按鈕
   */
  showFunctionButtons() {
    const buttons = [".bee_preview", ".bee_open_new_wd", ".bee_link"];

    buttons.forEach((selector) => {
      const button = document.querySelector(
        `#BH-master > form > div > table > tbody > tr:nth-child(2) > td:nth-child(3) > a.btn-icon.btn-icon--inverse${selector}`
      );
      if (button) {
        button.style.display = "inline-block";
      }
    });
  }

  /**
   * 隱藏功能按鈕
   */
  hideFunctionButtons() {
    const buttons = [".bee_preview", ".bee_open_new_wd", ".bee_link"];

    buttons.forEach((selector) => {
      const button = document.querySelector(
        `#BH-master > form > div > table > tbody > tr:nth-child(2) > td:nth-child(3) > a.btn-icon.btn-icon--inverse${selector}`
      );
      if (button) {
        button.style.display = "none";
      }
    });
  }

  /**
   * 點擊預覽按鈕
   */
  clickPreviewButton(picMode) {
    const selector = picMode
      ? "#BH-master > form > div > table > tbody > tr:nth-child(2) > td.b-list__main > div > a"
      : "#BH-master > form > div > table > tbody > tr:nth-child(2) > td.b-list__main > a";

    const button = document.querySelector(selector);
    if (button) {
      button.click();
    }
  }

  /**
   * 關閉預覽器
   */
  closePreviewer() {
    const closeButton = document.querySelector("#BH-menu-path");
    if (closeButton) {
      closeButton.click();
    }
  }

  /**
   * 創建首頁導覽
   */
  createHomeTour() {
    const driver = window.driver.js.driver;

    const driverObj = driver({
      showButtons: ["next", "previous"],
      allowClose: false,
      nextBtnText: "▶",
      prevBtnText: "◀",
      doneBtnText: "好耶",
      showProgress: true,
      steps: [
        {
          element: "#homeStyleSwitch",
          popover: {
            title: "滿版首頁",
            description: "點此可以切換首頁排版。",
          },
        },
      ],
    });

    driverObj.drive();
  }
}

/**
 * 檢舉提醒管理器
 */
class ReportManager {
  constructor(settings) {
    this.settings = settings;
  }

  /**
   * 檢查檢舉提醒
   */
  checkAlert(isNewVersion) {
    if (!this.shouldCheckReport()) return;

    const isReported = this.detectReport();
    if (!isReported) return;

    const bsn = this.extractBsn();
    if (!bsn) {
      console.log("[WARN] 有檢舉但抓取連結失敗");
      return;
    }

    this.openReportPage(bsn);
  }

  /**
   * 檢查是否應該檢查檢舉
   */
  shouldCheckReport() {
    return (
      window.location.href.includes("forum.gamer.com.tw/B.php") &&
      this.settings.getBool("showAbuse")
    );
  }

  /**
   * 檢測是否有檢舉
   */
  detectReport() {
    const reportElement = document.querySelector(
      "#BH-slave > div.BH-rbox.FM-rbox14 > div.FM-master-btn > a > span"
    );
    return reportElement !== null;
  }

  /**
   * 提取BSN參數
   */
  extractBsn() {
    const urlParams = new URLSearchParams(window.location.search);
    return urlParams.get("bsn");
  }

  /**
   * 開啟檢舉頁面
   */
  openReportPage(bsn) {
    // 這裡需要使用全域的openInFrame函數
    if (typeof openInFrame === "function") {
      openInFrame(`https://forum.gamer.com.tw/gemadmin/accuse.php?bsn=${bsn}`);
    }
  }
}

/**
 * 動畫管理器
 */
class AnimationManager {
  /**
   * 彈出元素初始化
   */
  async popElementInit(element, show = true, anime = "ud", waitAppend = true) {
    if (waitAppend) {
      requestAnimationFrame(() => {
        this.setElementDimensions(element);
      });
    } else {
      this.setElementDimensions(element);
    }

    this.setupElementTransition(element, show, anime);
  }

  /**
   * 設置元素尺寸
   */
  setElementDimensions(element) {
    element.style.readHeight =
      element.scrollHeight === 0 ? "999px" : `${element.scrollHeight}px`;
    element.style.readWidth =
      element.scrollWidth === 0 ? "999px" : `${element.scrollWidth}px`;
  }

  /**
   * 設置元素過渡
   */
  setupElementTransition(element, show, anime) {
    Object.assign(element.style, {
      transition: "",
      overflow: "hidden auto",
      opacity: "0",
    });

    this.popElement(element, "false", anime);
    element.style.transition =
      "all 0.5s cubic-bezier(0.21, 0.3, 0.18, 1.37) 0s";

    if (!show) {
      element.style.beeShow = "false";
      return;
    }

    element.style.beeShow = "true";
    element.style.opacity = "1";

    requestAnimationFrame(() => {
      element.style.maxHeight = element.style.readHeight;
    });
  }

  /**
   * 彈出元素控制
   */
  popElement(element, show = "true", anime = "ud") {
    const doShow =
      show === "toggle" ? !(element.style.beeShow === "true") : show === "true";

    if (doShow) {
      this.showElement(element);
    } else {
      this.hideElement(element, anime);
    }
  }

  /**
   * 顯示元素
   */
  showElement(element) {
    Object.assign(element.style, {
      opacity: "1",
      maxHeight: element.style.readHeight,
      maxWidth: element.style.readWidth,
      transform: "translateX(0px) translateY(0px)",
      beeShow: "true",
    });
  }

  /**
   * 隱藏元素
   */
  hideElement(element, anime) {
    element.style.beeShow = "false";
    element.style.opacity = "0";

    if (anime.includes("u")) {
      element.style.maxHeight = "0px";
      if (anime.startsWith("d")) {
        element.style.transform = `translateX(0px) translateY(${element.style.readWidth}px)`;
      }
    }

    if (anime.includes("l")) {
      element.style.maxWidth = "0px";
      if (anime.startsWith("r")) {
        element.style.transform = `translateX(${element.style.readHeight}) translateY(0px)`;
      }
    }
  }
}
/**
 * 首頁功能模組
 * 負責首頁的版面切換和樣式調整功能
 */
class HomePageWorker {
  constructor(settings) {
    this.settings = settings;
  }

  /**
   * 初始化首頁功能
   */
  init() {
    if (!this.isHomePage()) return;

    this.addStyleSwitchButton();
    this.applyHomeStyles();
  }

  /**
   * 檢查是否為首頁
   */
  isHomePage() {
    return (
      window.location.href.includes("www.gamer.com.tw") &&
      document.querySelectorAll("div.BA-lbox.BA-lbox3").length > 0
    );
  }

  /**
   * 添加樣式切換按鈕
   */
  addStyleSwitchButton() {
    const baServeElement = document.querySelector(".BA-serve");
    if (!baServeElement) return;

    const switchButton = document.createElement("li");
    switchButton.id = "homeStyleSwitch";
    switchButton.innerHTML = "首頁滿版切換";
    baServeElement.appendChild(switchButton);

    switchButton.addEventListener("click", () => {
      this.toggleHomeStyle();
    });
  }

  /**
   * 切換首頁樣式
   */
  toggleHomeStyle() {
    const currentValue = this.settings.getBool("homeStyleSwitch");
    this.settings.set("homeStyleSwitch", (!currentValue).toString());
    location.reload();
  }

  /**
   * 應用首頁樣式
   */
  applyHomeStyles() {
    if (!this.settings.getBool("homeStyleSwitch")) return;

    this.reorganizeContainers();
    this.createSecondLeftNav();
    this.addCustomStyles();
  }

  /**
   * 重新組織容器
   */
  reorganizeContainers() {
    const hotboardContainer = document.getElementById("hotboardContainer");
    const guildContainer = document.getElementById("guildContainer");
    const hothalaContainer = document.getElementById("hothalaContainer");

    if (hotboardContainer && guildContainer && hothalaContainer) {
      hothalaContainer.appendChild(hotboardContainer);
      hothalaContainer.appendChild(guildContainer);
    }
  }

  /**
   * 創建第二個左側導航
   */
  createSecondLeftNav() {
    const bahaStoreContainer = document.querySelectorAll(
      "div.BA-lbox.BA-lbox3"
    )[0];
    const bahaAnimeContainer = document.querySelectorAll(
      "div.BA-lbox.BA-lbox3"
    )[1];
    const titles = document.querySelectorAll("h1.BA-ltitle");
    const wrapper = document.querySelectorAll("div.BA-wrapper.BA-main")[0];
    const center = document.querySelectorAll("div.BA-center")[0];

    if (!bahaStoreContainer || !bahaAnimeContainer || !wrapper || !center)
      return;

    const secondDivLeft = document.createElement("div");
    secondDivLeft.className = "BA-left";

    Object.assign(secondDivLeft.style, {
      flex: "0 0 11em",
      margin: "0 0 0 1em",
    });

    // 添加標題和容器
    if (titles[1]) secondDivLeft.appendChild(titles[1]);
    secondDivLeft.appendChild(bahaAnimeContainer);
    if (titles[0]) secondDivLeft.appendChild(titles[0]);
    secondDivLeft.appendChild(bahaStoreContainer);

    wrapper.insertBefore(secondDivLeft, center);
  }

  /**
   * 添加自定義樣式
   */
  addCustomStyles() {
    const styleElement = document.createElement("style");
    styleElement.textContent = this.getCustomCSS();
    document.head.appendChild(styleElement);
  }

  /**
   * 獲取自定義CSS
   */
  getCustomCSS() {
    return `
            /* 父容器設置 */
            .BA-wrapper.BA-main {
                display: flex;
                flex-wrap: wrap;
                width: auto;
            }

            /* 第一層左側固定寬度 */
            .BA-left {
                flex: 0 0 11em;
            }

            /* 第一層右側容器 */
            .BA-center {
                flex: 1;
                display: flex;
                flex-wrap: wrap;
            }

            #gnnContainer {
                flex: 0 0 45%;
                margin: 0 1% 2% 1%;
                order: 1;
            }

            #hothalaContainer {
                flex: 45%;
                margin: 0 1% 2% 1%;
                order: 2;
            }

            #homeContainer {
                flex: 45%;
                margin: 0 1% 2% 1%;
                order: 3;
            }

            #buyContainer {
                flex: 0 0 45%;
                margin: 0 1% 2% 1%;
                order: 4;
            }

            #liveContainer {
                flex: 45%;
                margin: 0 1% 2% 1%;
                order: 5;
            }

            #gamecrazyContainer {
                flex: 0 0 45%;
                margin: 0 1% 2% 1%;
                order: 6;
            }

            .BA-cbox7 p {
                text-align: left !important;
            }
        `;
  }
}

/**
 * 工具函數模組
 * 提供全域使用的工具函數
 */
class UtilityFunctions {
  /**
   * 在框架中打開URL(全域函數)
   */
  static openInFrame(url) {
    const iframe = document.getElementById("bee_frame");
    if (!iframe) return;

    iframe.src = url;

    const menuPath = document.querySelector("#BH-menu-path");
    if (menuPath) {
      menuPath.style.height = "100%";
      menuPath.style.opacity = "0.6";
    }

    setTimeout(() => {
      const container = document.querySelector(".bee_preview_wd");
      if (container) {
        const animationManager = new AnimationManager();
        const direction =
          localStorage.getItem("preview_LR") === "true" ? "rl" : "lr";
        animationManager.popElement(container, "true", direction);
      }
    }, 1000);

    // 設置iframe樣式
    setTimeout(() => {
      UtilityFunctions.setupIframeStyles(iframe);
    }, 1000);
  }

  /**
   * 設置iframe樣式
   */
  static setupIframeStyles(iframe) {
    try {
      const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
      const styleSheet = iframeDoc.createElement("style");
      iframeDoc.head.appendChild(styleSheet);

      const sheet = styleSheet.sheet;
      sheet.insertRule(
        ".managertools { position: fixed; bottom: 0; right: 0; z-index: 100; }",
        0
      );
    } catch (error) {
      console.warn("無法設置iframe樣式:", error);
    }
  }

  /**
   * 滾動到指定元素
   */
  static scrollIntoBee(element, marginOffset = 7) {
    const originalMargin = element.style.marginTop || "0px";
    element.style.marginTop = `-${marginOffset}rem`;
    element.scrollIntoView({ behavior: "smooth" });
    element.style.marginTop = originalMargin;

    setTimeout(() => {
      if (!UtilityFunctions.isInViewport(element)) {
        UtilityFunctions.scrollIntoBee(element, marginOffset);
      }
    }, 300);
  }

  /**
   * 檢查元素是否在視窗內
   */
  static isInViewport(element) {
    const rect = element.getBoundingClientRect();
    return (
      rect.top >= 0 &&
      rect.top <= (window.innerHeight || document.documentElement.clientHeight)
    );
  }

  /**
   * 還原原始格式(用於留言處理)
   */
  static restoreOriginalFormat(textContent, cmdContents) {
    const nameToHtmlMap = new Map();
    const htmlPattern = /([^<]+)<\/a>/g;
    let match;

    while ((match = htmlPattern.exec(cmdContents)) !== null) {
      nameToHtmlMap.set(match[1], match[0]);
    }

    let processedText = textContent;
    nameToHtmlMap.forEach((html, name) => {
      const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
      const atPattern = new RegExp(`@${escapedName}`, "g");
      processedText = processedText.replace(atPattern, html);
    });

    return processedText;
  }

  /**
   * 格式化日期
   */
  static formatDate(date) {
    return date.toISOString().slice(0, 10).replace(/-/g, "");
  }

  /**
   * 安全獲取元素
   */
  static safeQuerySelector(selector) {
    try {
      return document.querySelector(selector);
    } catch (error) {
      console.warn(`無法找到元素: ${selector}`, error);
      return null;
    }
  }

  /**
   * 安全獲取多個元素
   */
  static safeQuerySelectorAll(selector) {
    try {
      return document.querySelectorAll(selector);
    } catch (error) {
      console.warn(`無法找到元素: ${selector}`, error);
      return [];
    }
  }

  /**
   * 防抖函數
   */
  static debounce(func, wait) {
    let timeout;
    return function executedFunction(...args) {
      const later = () => {
        clearTimeout(timeout);
        func(...args);
      };
      clearTimeout(timeout);
      timeout = setTimeout(later, wait);
    };
  }

  /**
   * 節流函數
   */
  static throttle(func, limit) {
    let inThrottle;
    return function (...args) {
      if (!inThrottle) {
        func.apply(this, args);
        inThrottle = true;
        setTimeout(() => (inThrottle = false), limit);
      }
    };
  }

  /**
   * 深拷貝對象
   */
  static deepClone(obj) {
    if (obj === null || typeof obj !== "object") return obj;
    if (obj instanceof Date) return new Date(obj.getTime());
    if (obj instanceof Array)
      return obj.map((item) => UtilityFunctions.deepClone(item));
    if (typeof obj === "object") {
      const clonedObj = {};
      for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
          clonedObj[key] = UtilityFunctions.deepClone(obj[key]);
        }
      }
      return clonedObj;
    }
  }

  /**
   * 生成唯一ID
   */
  static generateUniqueId(prefix = "id") {
    return `${prefix}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
  }

  /**
   * 等待指定時間
   */
  static sleep(ms) {
    return new Promise((resolve) => setTimeout(resolve, ms));
  }

  /**
   * 重試函數
   */
  static async retry(fn, maxRetries = 3, delay = 1000) {
    for (let i = 0; i < maxRetries; i++) {
      try {
        return await fn();
      } catch (error) {
        if (i === maxRetries - 1) throw error;
        await UtilityFunctions.sleep(delay);
      }
    }
  }

  /**
   * 檢查是否為移動設備
   */
  static isMobileDevice() {
    return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
      navigator.userAgent
    );
  }

  /**
   * 獲取瀏覽器信息
   */
  static getBrowserInfo() {
    const ua = navigator.userAgent;
    let browser = "Unknown";

    if (ua.includes("Chrome")) browser = "Chrome";
    else if (ua.includes("Firefox")) browser = "Firefox";
    else if (ua.includes("Safari")) browser = "Safari";
    else if (ua.includes("Edge")) browser = "Edge";

    return {
      browser,
      userAgent: ua,
      isMobile: UtilityFunctions.isMobileDevice(),
    };
  }
}

/**
 * 主插件類別 - Re版本
 * 整合所有模組並提供統一的初始化入口
 */
class BahamutePluginMain extends BahamutePlugin {
  constructor() {
    super();
    //this.homePageWorker = new HomePageWorker(this.settings);
    this.settingsUIManager = new SettingsUIManager(this.settings);
    //this.tipsManager = new TipsManager(this.settings);
    this.reportManager = new ReportManager(this.settings);
  }

  /**
   * 重寫初始化方法
   */
  async init() {
    try {
      console.log("[INFO] 巴哈姆特插件開始初始化...");

      // 基礎初始化
      this.isNewVersion = await this.detectMode();
      this.settings.checkFirstRun();

      // UI初始化
      await this.settingsUIManager.addSettingElement(this.isNewVersion);

      // 功能模組初始化
      await this.initializeWorkers();
      //this.homePageWorker.init();

      // 輔助功能初始化
      //this.tipsManager.checkTips(this.isNewVersion);
      this.reportManager.checkAlert(this.isNewVersion);

      console.log("[INFO] 巴哈姆特插件初始化完成!");
    } catch (error) {
      console.error("[ERROR] 插件初始化失敗:", error);
    }
  }

  /**
   * 獲取插件版本信息
   */
  getVersionInfo() {
    return {
      version: this.version,
      isNewVersion: this.isNewVersion,
      browserInfo: UtilityFunctions.getBrowserInfo(),
      initTime: new Date().toISOString(),
    };
  }

  /**
   * 重置插件設定
   */
  resetSettings() {
    if (confirm("確定要重置所有設定嗎?這將會清除所有自定義配置。")) {
      this.settings.checkFirstRun(true);
      alert("設定已重置,請重新整理頁面。");
      location.reload();
    }
  }

  /**
   * 導出設定
   */
  exportSettings() {
    const settings = {};
    Object.keys(this.settings.defaultSettings).forEach((key) => {
      settings[key] = this.settings.get(key);
    });

    const dataStr = JSON.stringify(settings, null, 2);
    const dataBlob = new Blob([dataStr], { type: "application/json" });
    const url = URL.createObjectURL(dataBlob);

    const link = document.createElement("a");
    link.href = url;
    link.download = "bahamute-plugin-settings.json";
    link.click();

    URL.revokeObjectURL(url);
  }

  /**
   * 導入設定
   */
  importSettings(file) {
    const reader = new FileReader();
    reader.onload = (e) => {
      try {
        const settings = JSON.parse(e.target.result);
        Object.keys(settings).forEach((key) => {
          this.settings.set(key, settings[key]);
        });
        alert("設定導入成功,請重新整理頁面。");
        location.reload();
      } catch (error) {
        alert("設定文件格式錯誤,請檢查文件內容。");
      }
    };
    reader.readAsText(file);
  }
}

// 將工具函數設為全域可用
window.openInFrame = UtilityFunctions.openInFrame;
window.scrollIntoBee = UtilityFunctions.scrollIntoBee;
window.isInViewport = UtilityFunctions.isInViewport;
window.restoreOriginalFormat = UtilityFunctions.restoreOriginalFormat;

// 初始化插件(替換原本的立即執行函數)
(async function () {
  "use strict";

  // 等待DOM載入完成
  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", () => {
      new BahamutePluginMain();
    });
  } else {
    new BahamutePluginMain();
  }
})();

// 開發者工具(僅在開發模式下可用)
if (typeof GM_info !== "undefined" && GM_info.script.name.includes("dev")) {
  window.BahamutePluginDev = {
    getPlugin: () => window.bahamutePluginInstance,
    resetSettings: () => window.bahamutePluginInstance?.resetSettings(),
    exportSettings: () => window.bahamutePluginInstance?.exportSettings(),
    getVersionInfo: () => window.bahamutePluginInstance?.getVersionInfo(),
    utils: UtilityFunctions,
  };
}