---
import { getCollection, render } from "astro:content";
import { getSpecialPath } from "@/content.config";
import Layout from "@/components/Layout.astro";
import Breadcrumb from "@/components/Breadcrumb.astro";
import { ARTICLE_EXPIRY_CONFIG } from "@/consts";
import "@/styles/articles.css";

// 定义文章类型
interface ArticleEntry {
  id: string;
  data: {
    title: string;
    date: Date;
    tags?: string[];
    summary?: string;
  };
}

// 定义标题类型
interface Heading {
  depth: number;
  slug: string;
  text: string;
}

export async function getStaticPaths() {
  const articles = await getCollection("articles");

  // 为每篇文章生成路由参数
  const paths = [];
  for (const article of articles) {
    // 获取所有可能的路径形式
    const possiblePaths = new Set([
      article.id, // 只保留原始路径
    ]);

    // 如果是多级目录，检查是否需要特殊处理
    if (article.id.includes("/")) {
      const parts = article.id.split("/");
      const fileName = parts[parts.length - 1];
      const dirName = parts[parts.length - 2];

      // 只有当文件名与其父目录名相同时才添加特殊路径
      if (fileName === dirName) {
        possiblePaths.add(getSpecialPath(article.id));
      }
    }

    // 为每个可能的路径生成路由
    for (const path of possiblePaths) {
      paths.push({
        params: { id: path },
        props: {
          article,
          section: article.id.includes("/")
            ? article.id.split("/").slice(0, -1).join("/")
            : "",
          originalId: path !== article.id ? article.id : undefined,
        },
      });
    }
  }

  return paths;
}

// 获取文章内容
const { article, section, originalId } = Astro.props;

// 获取搜索参数
const searchParams = new URLSearchParams(Astro.url.search);

// 如果有原始ID，使用它来渲染内容
const articleToRender = originalId ? { ...article, id: originalId } : article;

// 渲染文章内容
const { Content, headings } = await render(articleToRender);

// 获取面包屑路径段
const pathSegments = section ? section.split("/") : [];

// 获取相关文章
const allArticles = await getCollection("articles");

// 1. 尝试通过标签匹配相关文章
let relatedArticles = allArticles
  .filter((a: ArticleEntry) => {
    const hasCommonTags =
      a.id !== article.id &&
      a.data.tags &&
      article.data.tags &&
      a.data.tags.length > 0 &&
      article.data.tags.length > 0 &&
      a.data.tags.some((tag: string) => article.data.tags?.includes(tag));

    return hasCommonTags;
  })
  .sort((a: ArticleEntry, b: ArticleEntry) => b.data.date.getTime() - a.data.date.getTime())
  .slice(0, 3);

// 跟踪相关文章的匹配方式: "tag", "directory", "latest"
let relatedArticlesMatchType = relatedArticles.length > 0 ? "tag" : "";

// 2. 如果标签匹配没有找到足够的相关文章，尝试根据目录结构匹配
if (relatedArticles.length < 3) {
  // 获取当前文章的目录路径
  const currentPath = article.id.includes("/")
    ? article.id.substring(0, article.id.lastIndexOf("/"))
    : "";

  // 如果有目录路径，查找同目录的其他文章
  if (currentPath) {
    // 收集同目录下的文章，但排除已经通过标签匹配的和当前文章
    const dirRelatedArticles = allArticles
      .filter(
        (a: ArticleEntry) =>
          a.id !== article.id &&
          a.id.startsWith(currentPath + "/") &&
          !relatedArticles.some((r: ArticleEntry) => r.id === a.id),
      )
      .sort((a: ArticleEntry, b: ArticleEntry) => b.data.date.getTime() - a.data.date.getTime())
      .slice(0, 3 - relatedArticles.length);

    if (dirRelatedArticles.length > 0) {
      relatedArticles = [...relatedArticles, ...dirRelatedArticles];
      relatedArticlesMatchType =
        relatedArticles.length > 0 && !relatedArticlesMatchType
          ? "directory"
          : relatedArticlesMatchType;
    }
  }
}

// 3. 如果仍然没有找到足够的相关文章，则选择最新的文章（排除当前文章和已选择的文章）
if (relatedArticles.length < 3) {
  const latestArticles = allArticles
    .filter(
      (a: ArticleEntry) => a.id !== article.id && !relatedArticles.some((r: ArticleEntry) => r.id === a.id),
    )
    .sort((a: ArticleEntry, b: ArticleEntry) => b.data.date.getTime() - a.data.date.getTime())
    .slice(0, 3 - relatedArticles.length);

  if (latestArticles.length > 0) {
    relatedArticles = [...relatedArticles, ...latestArticles];
    relatedArticlesMatchType =
      relatedArticles.length > 0 && !relatedArticlesMatchType
        ? "latest"
        : relatedArticlesMatchType;
  }
}

// 准备文章描述
const description =
  article.data.summary ||
  `${article.data.title} - 发布于 ${article.data.date.toLocaleDateString("zh-CN")}`;

// 处理特殊ID的函数
function getArticleUrl(articleId: string) {
  return `/articles/${getSpecialPath(articleId)}${searchParams.toString() ? `?${searchParams.toString()}` : ""}`;
}

// 预先生成目录结构
function generateTableOfContents(headings: Heading[]) {
  if (!headings || headings.length === 0) {
    return '<p class="text-secondary-500 dark:text-secondary-400 italic">此文章没有目录</p>';
  }
  
  // 查找最低级别的标题（数值最小）
  const minDepth = Math.min(...headings.map(h => h.depth));
  
  let tocHtml = '<ul class="space-y-2">';
  
  headings.forEach((heading) => {
    // 计算相对缩进，以最小深度为基准
    const relativeDepth = heading.depth - minDepth;
    const indent = relativeDepth * 0.75;
    
    // 基于相对深度而非绝对深度决定样式
    const isHigherLevel = relativeDepth <= 1; // 仅最高级和次高级标题使用较重的样式
    
    tocHtml += `<li>
      <a href="#${heading.slug}" 
         class="block hover:text-primary-600 dark:hover:text-primary-400 duration-50 ${
           isHigherLevel
             ? "text-secondary-800 dark:text-secondary-200 font-medium"
             : "text-secondary-600 dark:text-secondary-400"
         }"
         style="padding-left: ${indent}rem;">
        ${heading.text}
      </a>
    </li>`;
  });
  
  tocHtml += '</ul>';
  return tocHtml;
}

// 生成目录HTML
const tableOfContents = generateTableOfContents(headings);
---

<Layout
  title={article.data.title}
  description={description}
  date={article.data.date}
  tags={article.data.tags}
  skipSrTitle={false}
  pageType="article"
>
  <div class="max-w-5xl py-8">
    <!-- 阅读进度条 -->
    <div
      class="fixed top-0 left-0 w-full h-1 bg-transparent z-50"
      id="progress-container"
    >
      <div
        class="h-full w-0 bg-primary-500 transition-width duration-100"
        id="progress-bar"
      >
      </div>
    </div>

    <!-- 文章头部 -->
    <header class="mb-8">
      <!-- 导航区域 -->
      <div
        class="bg-white dark:bg-gray-800 rounded-xl p-4 mb-6 shadow-lg border border-gray-200 dark:border-gray-700 relative z-10"
      >
        <div
          class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3"
        >
          <div class="w-full overflow-hidden">
            <Breadcrumb
              pageType="article"
              pathSegments={pathSegments}
              searchParams={searchParams}
              articleTitle={article.data.title}
              path={section}
            />
          </div>
        </div>
      </div>

      <!-- 文章过期提醒 -->
      {
        (() => {
          const publishDate = article.data.date;
          const currentDate = new Date();
          const daysDiff = Math.floor(
            (currentDate.getTime() - publishDate.getTime()) /
              (1000 * 60 * 60 * 24),
          );

          if (
            ARTICLE_EXPIRY_CONFIG.enabled &&
            daysDiff > ARTICLE_EXPIRY_CONFIG.expiryDays
          ) {
            return (
              <div class="bg-yellow-50 border-l-4 border-yellow-400 p-4 mb-4">
                <div class="flex">
                  <div class="flex-shrink-0">
                    <svg
                      class="h-5 w-5 text-yellow-400"
                      viewBox="0 0 20 20"
                      fill="currentColor"
                    >
                      <path
                        fill-rule="evenodd"
                        d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z"
                        clip-rule="evenodd"
                      />
                    </svg>
                  </div>
                  <div class="ml-3">
                    <p class="text-sm text-yellow-700">
                      {ARTICLE_EXPIRY_CONFIG.warningMessage}
                    </p>
                  </div>
                </div>
              </div>
            );
          }
          return null;
        })()
      }

      <h1 class="text-3xl font-bold mb-4 text-gray-900 dark:text-gray-100">
        {article.data.title}
      </h1>

      <div
        class="flex flex-wrap items-center gap-4 text-sm text-secondary-600 dark:text-secondary-400 mb-4"
      >
        <time
          datetime={article.data.date.toISOString()}
          class="flex items-center"
        >
          <svg
            xmlns="http://www.w3.org/2000/svg"
            class="h-4 w-4 mr-1"
            fill="none"
            viewBox="0 0 24 24"
            stroke="currentColor"
          >
            <path
              stroke-linecap="round"
              stroke-linejoin="round"
              stroke-width="2"
              d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
            ></path>
          </svg>
          {article.data.date.toLocaleDateString("zh-CN")}
        </time>

        {
          section && (
            <span class="flex items-center">
              <svg
                xmlns="http://www.w3.org/2000/svg"
                class="h-4 w-4 mr-1 shrink-0"
                fill="none"
                viewBox="0 0 24 24"
                stroke="currentColor"
              >
                <path
                  stroke-linecap="round"
                  stroke-linejoin="round"
                  stroke-width="2"
                  d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z"
                />
              </svg>
              <a
                href={`/articles/${section}/`}
                class="hover:text-indigo-600 break-all"
              >
                {section}
              </a>
            </span>
          )
        }
      </div>

      {
        article.data.tags && article.data.tags.length > 0 && (
          <div class="flex flex-wrap gap-2 mb-6">
            {article.data.tags.map((tag: string) => (
              <a
                href={`/articles?tags=${tag}`}
                class="text-xs bg-primary-50 dark:bg-primary-900/30 text-primary-600 dark:text-primary-400 py-1 px-2 rounded hover:bg-primary-100 dark:hover:bg-primary-800/30"
                data-astro-prefetch="hover"
              >
                #{tag}
              </a>
            ))}
          </div>
        )
      }
    </header>

    <!-- 文章内容 -->
    <article
      class="prose prose-lg dark:prose-invert prose-primary prose-table:rounded-lg prose-table:border-separate prose-table:border-2 prose-thead:bg-primary-50 dark:prose-thead:bg-gray-800 prose-ul:list-disc prose-ol:list-decimal prose-li:my-1 prose-blockquote:border-l-4 prose-blockquote:border-primary-500 prose-blockquote:bg-gray-100 prose-blockquote:dark:bg-gray-800 prose-a:text-primary-600 prose-a:dark:text-primary-400 prose-a:no-underline prose-a:border-b prose-a:border-primary-300 prose-a:hover:border-primary-600 max-w-none mb-12"
    >
      <Content />
    </article>
    
    <!-- 目录 -->
    <section
      class="hidden 2xl:block fixed right-[calc(50%-44rem)] top-20 w-64 z-30"
      id="toc-panel"
    >
      <div
        class="bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 flex flex-col backdrop-blur-sm bg-opacity-95 dark:bg-opacity-95"
      >
        <div
          class="border-b border-secondary-100 dark:border-gray-700 p-4 pb-3 sticky top-0 bg-white dark:bg-gray-800 bg-opacity-95 dark:bg-opacity-95 backdrop-filter backdrop-blur-sm z-10 rounded-t-xl"
        >
          <h3 class="font-bold text-primary-700 dark:text-primary-400 flex items-center gap-2">
            <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h7" />
            </svg>
            文章目录
          </h3>
        </div>
        <div
          id="toc-content"
          class="text-sm p-4 pt-2 overflow-y-auto max-h-[calc(100vh-8rem-42px)] scrollbar-thin scrollbar-thumb-primary-200 dark:scrollbar-thumb-primary-800 scrollbar-track-transparent"
          set:html={tableOfContents}
        >
          <!-- 目录内容在服务端生成 -->
        </div>
      </div>
    </section>

    <!-- 相关文章 -->
    {
      relatedArticles.length > 0 && (
        <aside class="mt-12 pt-8 border-t border-secondary-200 dark:border-gray-700">
          <h2 class="text-2xl font-bold mb-6 text-primary-900 dark:text-primary-100">
            {relatedArticlesMatchType === "tag"
              ? "相关文章"
              : relatedArticlesMatchType === "directory"
                ? "同类文章"
                : "推荐阅读"}
          </h2>
          <div class="grid grid-cols-1 md:grid-cols-3 gap-6">
            {relatedArticles.map((relatedArticle: ArticleEntry) => (
              <a
                href={getArticleUrl(relatedArticle.id)}
                class="article-card"
                data-astro-prefetch="viewport"
              >
                <div class="article-card-content">
                  <div class="article-card-icon">
                    <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 20H5a2 2 0 01-2-2V6a2 2 0 012-2h10a2 2 0 012 2v1m2 13a2 2 0 01-2-2V7m2 13a2 2 0 002-2V9a2 2 0 00-2-2h-2m-4-3H9M7 16h6M7 8h6v4H7V8z"></path>
                    </svg>
                  </div>
                  <div class="article-card-body">
                    <h3 class="article-card-title">
                      {relatedArticle.data.title}
                    </h3>
                    <p class="article-card-date">
                      {relatedArticle.data.date.toLocaleDateString("zh-CN")}
                    </p>
                    {relatedArticle.data.summary && (
                      <p class="article-card-summary">
                        {relatedArticle.data.summary}
                      </p>
                    )}
                    <div class="article-card-footer">
                      <time datetime={relatedArticle.data.date.toISOString()} class="article-card-date">
                        {relatedArticle.data.date.toLocaleDateString("zh-CN", {
                          year: 'numeric',
                          month: 'long',
                          day: 'numeric'
                        })}
                      </time>
                      <span class="article-card-read-more">阅读全文</span>
                    </div>
                  </div>
                </div>
              </a>
            ))}
          </div>
        </aside>
      )
    }

    <!-- 返回顶部按钮 -->
    <button
      id="back-to-top"
      class="fixed bottom-8 right-8 w-12 h-12 rounded-full bg-primary-500 dark:bg-primary-600 text-white shadow-md flex items-center justify-center opacity-0 invisible translate-y-5 hover:bg-primary-600 dark:hover:bg-primary-700"
    >
      <svg
        xmlns="http://www.w3.org/2000/svg"
        class="h-6 w-6"
        fill="none"
        viewBox="0 0 24 24"
        stroke="currentColor"
      >
        <path
          stroke-linecap="round"
          stroke-linejoin="round"
          stroke-width="2"
          d="M5 10l7-7m0 0l7 7m-7-7v18"
        ></path>
      </svg>
    </button>
  </div>
</Layout>

<!-- 文章页面脚本 -->
<script is:inline>
  // 文章页面交互脚本 - 自销毁模式
  (function() {
    // 如果不是文章页面，立即退出，不执行任何代码
    if (!document.querySelector("article")) {
      return;
    }
    
    const scriptInstanceId = Date.now();
    console.log(`[文章脚本:${scriptInstanceId}] 检测到文章页面，开始初始化`);
    
    // 集中管理所有事件监听器
    const allListeners = [];
    
    // 为特殊清理任务准备的数组
    const customCleanupTasks = [];
    
    // 单独保存清理事件的监听器引用
    const cleanupListeners = [];
    
    // 添加事件监听器并记录，方便后续统一清理
    function addListener(element, eventType, handler, options) {
      if (!element) {
        console.warn(`[文章脚本:${scriptInstanceId}] 尝试为不存在的元素添加事件:`, eventType);
        return null;
      }

      console.log(`[文章脚本:${scriptInstanceId}] 添加事件监听器: ${eventType} 到`, element.tagName || "Window/Document");
      element.addEventListener(eventType, handler, options);
      allListeners.push({ element, eventType, handler, options });
      return handler;
    }

    // 统一的清理函数，执行完整清理并自销毁
    function selfDestruct() {
      console.log(`[文章脚本:${scriptInstanceId}] 执行自销毁流程`);
      
      // 1. 先移除普通事件监听器
      console.log(`[文章脚本:${scriptInstanceId}] 移除常规监听器，数量:`, allListeners.length);
      allListeners.forEach(({ element, eventType, handler, options }) => {
        try {
          console.log(`[文章脚本:${scriptInstanceId}] 移除事件监听器: ${eventType} 从`, element.tagName || "Window/Document");
          element.removeEventListener(eventType, handler, options);
        } catch (err) {
          console.error(`[文章脚本:${scriptInstanceId}] 移除事件监听器出错:`, err);
        }
      });
      
      // 清空监听器数组
      allListeners.length = 0;
      
      // 2. 执行特殊清理任务
      console.log(`[文章脚本:${scriptInstanceId}] 执行特殊清理任务，数量:`, customCleanupTasks.length);
      customCleanupTasks.forEach(task => {
        try {
          task();
        } catch (err) {
          console.error(`[文章脚本:${scriptInstanceId}] 执行特殊清理任务出错:`, err);
        }
      });
      
      // 清空特殊任务数组
      customCleanupTasks.length = 0;
      
      // 3. 最后移除清理事件监听器自身
      console.log(`[文章脚本:${scriptInstanceId}] 移除清理监听器，数量:`, cleanupListeners.length);
      cleanupListeners.forEach(({ element, eventType, handler, options }) => {
        try {
          console.log(`[文章脚本:${scriptInstanceId}] 移除清理监听器: ${eventType} 从`, element.tagName || "Window/Document");
          element.removeEventListener(eventType, handler, options);
        } catch (err) {
          console.error(`[文章脚本:${scriptInstanceId}] 移除清理监听器出错:`, err);
        }
      });
      
      console.log(`[文章脚本:${scriptInstanceId}] 完全销毁完成`);
    }
    
    // 注册清理事件，并保存引用
    function registerCleanupEvents() {
      console.log(`[文章脚本:${scriptInstanceId}] 注册清理事件`);
      
      // 创建一次性事件处理函数
      const beforeSwapHandler = () => {
        console.log(`[文章脚本:${scriptInstanceId}] astro:before-swap 触发，执行自销毁`);
        selfDestruct();
      };
      
      const beforeUnloadHandler = () => {
        console.log(`[文章脚本:${scriptInstanceId}] beforeunload 触发，执行自销毁`);
        selfDestruct();
      };
      
      // 添加清理事件监听器并保存引用
      document.addEventListener("astro:before-swap", beforeSwapHandler, { once: true });
      window.addEventListener("beforeunload", beforeUnloadHandler, { once: true });
      
      // 保存清理事件引用，用于完全销毁
      cleanupListeners.push(
        { element: document, eventType: "astro:before-swap", handler: beforeSwapHandler, options: { once: true } },
        { element: window, eventType: "beforeunload", handler: beforeUnloadHandler, options: { once: true } }
      );
    }
    
    // 初始化所有功能
    function initializeFeatures() {
      console.log(`[文章脚本:${scriptInstanceId}] 开始初始化各功能`);
      
      // 1. 代码块复制功能
      function setupCodeCopy() {
        console.log(`[文章脚本:${scriptInstanceId}] 初始化代码复制功能`);
        const copyButtons = document.querySelectorAll('.code-block-copy');
        if (copyButtons.length === 0) {
          console.log(`[文章脚本:${scriptInstanceId}] 未找到代码复制按钮`);
          return;
        }
        
        console.log(`[文章脚本:${scriptInstanceId}] 找到代码复制按钮数量:`, copyButtons.length);
        copyButtons.forEach(button => {
          addListener(button, 'click', async () => {
            try {
              const encodedCode = button.getAttribute('data-code');
              if (!encodedCode) return;
              
              const code = atob(encodedCode);
              await navigator.clipboard.writeText(code);
              
              const originalHTML = button.innerHTML;
              button.classList.add('copied');
              button.innerHTML = `
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4">
                  <path d="M20 6L9 17l-5-5"></path>
                </svg>
                已复制
              `;
              
              setTimeout(() => {
                button.classList.remove('copied');
                button.innerHTML = originalHTML;
              }, 2000);
            } catch (err) {
              console.error(`[文章脚本:${scriptInstanceId}] 复制失败:`, err);
              button.innerHTML = `
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4">
                  <circle cx="12" cy="12" r="10"></circle>
                  <line x1="12" y1="8" x2="12" y2="12"></line>
                  <line x1="12" y1="16" x2="12.01" y2="16"></line>
                </svg>
                失败
              `;
              setTimeout(() => {
                button.innerHTML = `
                  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4">
                    <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
                    <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
                  </svg>
                  复制
                `;
              }, 2000);
            }
          });
        });
      }

      // 2. 阅读进度条
      function setupProgressBar() {
        console.log(`[文章脚本:${scriptInstanceId}] 初始化阅读进度条`);
        const progressBar = document.getElementById("progress-bar");
        const backToTopButton = document.getElementById("back-to-top");

        if (!progressBar) {
          console.warn(`[文章脚本:${scriptInstanceId}] 未找到进度条元素`);
          return;
        }

        function updateReadingProgress() {
          const scrollTop = window.scrollY || document.documentElement.scrollTop;
          const scrollHeight = document.documentElement.scrollHeight - document.documentElement.clientHeight;
          const progress = (scrollTop / scrollHeight) * 100;

          progressBar.style.width = `${progress}%`;

          if (backToTopButton) {
            if (scrollTop > 300) {
              backToTopButton.classList.add(
                "opacity-100",
                "visible",
                "translate-y-0"
              );
              backToTopButton.classList.remove(
                "opacity-0",
                "invisible",
                "translate-y-5"
              );
            } else {
              backToTopButton.classList.add(
                "opacity-0",
                "invisible",
                "translate-y-5"
              );
              backToTopButton.classList.remove(
                "opacity-100",
                "visible",
                "translate-y-0"
              );
            }
          }
        }

        addListener(window, "scroll", updateReadingProgress);

        if (backToTopButton) {
          addListener(backToTopButton, "click", () => {
            window.scrollTo({
              top: 0,
              behavior: "smooth",
            });
          });
        }

        // 初始更新一次进度条
        updateReadingProgress();
      }
      
      // 3. 目录交互
      function setupTableOfContents() {
        console.log(`[文章脚本:${scriptInstanceId}] 初始化目录交互`);
        const tocContent = document.getElementById("toc-content");
        const tocPanel = document.querySelector("#toc-panel");

        if (!tocPanel || !tocContent) {
          console.warn(`[文章脚本:${scriptInstanceId}] 未找到目录面板或内容`);
          return;
        }

        // 检查窗口大小调整目录面板显示
        function checkTocVisibility() {
          if (window.innerWidth < 1536) {
            tocPanel.classList.add("hidden");
            tocPanel.classList.remove("2xl:block");
          } else {
            tocPanel.classList.remove("hidden");
            tocPanel.classList.add("2xl:block");
          }
        }

        addListener(window, "resize", checkTocVisibility);
        checkTocVisibility();

        // 处理目录链接点击跳转
        const tocLinks = tocContent.querySelectorAll("a");
        console.log(`[文章脚本:${scriptInstanceId}] 找到目录链接数量:`, tocLinks.length);
        
        tocLinks.forEach(link => {
          addListener(link, "click", (e) => {
            e.preventDefault();
            const targetId = link.getAttribute("href")?.substring(1);
            if (!targetId) return;

            const targetElement = document.getElementById(targetId);
            if (targetElement) {
              const offset = 100;
              const targetPosition = targetElement.getBoundingClientRect().top + window.scrollY - offset;

              window.scrollTo({
                top: targetPosition,
                behavior: "smooth",
              });

              targetElement.classList.add("bg-primary-50", "dark:bg-primary-900/20");
              setTimeout(() => {
                targetElement.classList.remove("bg-primary-50", "dark:bg-primary-900/20");
              }, 2000);
            }
          });
        });

        // 监听滚动以更新当前活动的目录项
        const article = document.querySelector("article");
        if (!article) {
          console.warn(`[文章脚本:${scriptInstanceId}] 未找到文章内容元素`);
          return;
        }

        let ticking = false;

        function updateActiveHeading() {
          const headings = Array.from(article.querySelectorAll("h1, h2, h3, h4, h5, h6"));
          const tocLinks = Array.from(tocContent.querySelectorAll("a"));

          // 清除所有活动状态
          tocLinks.forEach((link) => {
            link.classList.remove("text-primary-600", "dark:text-primary-400", "font-medium");
          });

          // 找出当前可见的标题
          const scrollPosition = window.scrollY + 150;
          let currentHeading = null;

          for (const heading of headings) {
            const headingTop = heading.getBoundingClientRect().top + window.scrollY;
            if (headingTop <= scrollPosition) {
              currentHeading = heading;
            } else {
              break;
            }
          }

          // 高亮当前标题对应的目录项
          if (currentHeading) {
            const id = currentHeading.getAttribute('id');
            if (id) {
              const activeLink = tocLinks.find(
                (link) => link.getAttribute("href") === `#${id}`
              );
              if (activeLink) {
                // 高亮当前目录项
                activeLink.classList.add("text-primary-600", "dark:text-primary-400", "font-medium");
                
                // 可选: 确保当前激活的目录项在可视区域内
                const tocContainer = tocContent.querySelector('ul');
                if (tocContainer) {
                  const linkOffsetTop = activeLink.offsetTop;
                  const containerScrollTop = tocContainer.scrollTop;
                  const containerHeight = tocContainer.clientHeight;
                  
                  // 如果当前项不在视口内，滚动目录
                  if (linkOffsetTop < containerScrollTop || 
                      linkOffsetTop > containerScrollTop + containerHeight) {
                    tocContainer.scrollTop = linkOffsetTop - containerHeight / 2;
                  }
                }
              }
            }
          }
        }

        addListener(window, "scroll", () => {
          if (!ticking) {
            window.requestAnimationFrame(() => {
              updateActiveHeading();
              ticking = false;
            });
            ticking = true;
          }
        });

        updateActiveHeading();
      }

      // 4. Mermaid图表渲染
      function setupMermaid() {
        console.log(`[文章脚本:${scriptInstanceId}] 检查Mermaid图表`);
        // 查找所有mermaid代码块
        const mermaidBlocks = document.querySelectorAll(
          'pre.language-mermaid, pre > code.language-mermaid, .mermaid'
        );
        
        if (mermaidBlocks.length === 0) {
          console.log(`[文章脚本:${scriptInstanceId}] 未找到Mermaid图表`);
          return;
        }
        
        console.log(`[文章脚本:${scriptInstanceId}] 找到Mermaid图表数量:`, mermaidBlocks.length);
        
        // 动态加载mermaid库
        const script = document.createElement('script');
        script.src = 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js';
        
        script.onload = function() {
          console.log(`[文章脚本:${scriptInstanceId}] Mermaid库加载成功`);
          
          if (!window.mermaid) {
            console.error(`[文章脚本:${scriptInstanceId}] Mermaid库加载后window.mermaid不存在`);
            return;
          }
          
          // 初始化mermaid配置
          window.mermaid.initialize({
            startOnLoad: false,
            theme: 'default',
            securityLevel: 'loose'
          });
          
          // 将所有mermaid代码块转换为可渲染的格式
          mermaidBlocks.forEach((block, index) => {
            // 获取mermaid代码
            let code = '';
            
            // 检查元素类型并相应处理
            if (block.tagName === 'CODE' && block.classList.contains('language-mermaid')) {
              // 处理 code.language-mermaid 元素
              code = block.textContent || '';
              const pre = block.closest('pre');
              if (pre) {
                // 创建新的div元素替换整个pre
                const div = document.createElement('div');
                div.className = 'mermaid';
                div.id = 'mermaid-diagram-' + index;
                div.textContent = code;
                pre.parentNode.replaceChild(div, pre);
              }
            } else if (block.tagName === 'PRE' && block.classList.contains('language-mermaid')) {
              // 处理 pre.language-mermaid 元素
              code = block.textContent || '';
              const div = document.createElement('div');
              div.className = 'mermaid';
              div.id = 'mermaid-diagram-' + index;
              div.textContent = code;
              block.parentNode.replaceChild(div, block);
            } else if (block.classList.contains('mermaid') && block.tagName !== 'DIV') {
              // 如果是其他带mermaid类的元素但不是div，转换为div
              code = block.textContent || '';
              const div = document.createElement('div');
              div.className = 'mermaid';
              div.id = 'mermaid-diagram-' + index;
              div.textContent = code;
              block.parentNode.replaceChild(div, block);
            }
          });
          
          // 初始化渲染
          try {
            console.log(`[文章脚本:${scriptInstanceId}] 开始渲染Mermaid图表`);
            window.mermaid.run().catch(err => {
              console.error(`[文章脚本:${scriptInstanceId}] Mermaid渲染出错:`, err);
            });
          } catch (error) {
            console.error(`[文章脚本:${scriptInstanceId}] 初始化Mermaid渲染失败:`, error);
          }
        };
        
        script.onerror = function() {
          console.error(`[文章脚本:${scriptInstanceId}] 加载Mermaid库失败`);
          // 显示错误信息
          mermaidBlocks.forEach(block => {
            if (block.tagName === 'CODE') block = block.closest('pre');
            if (block) {
              block.innerHTML = '<div class="mermaid-error-message">无法加载Mermaid图表库</div>';
            }
          });
        };
        
        document.head.appendChild(script);
        
        // 添加Mermaid清理任务
        customCleanupTasks.push(() => {
          console.log(`[文章脚本:${scriptInstanceId}] 执行Mermaid特殊清理`);
          
          // 移除脚本标签
          if (script.parentNode) {
            script.parentNode.removeChild(script);
          }
          
          // 清除全局mermaid对象
          if (window.mermaid) {
            console.log(`[文章脚本:${scriptInstanceId}] 清除window.mermaid对象`);
            try {
              // 尝试清理mermaid内部状态
              if (typeof window.mermaid.destroy === 'function') {
                window.mermaid.destroy();
              }
              window.mermaid = undefined;
            } catch (e) {
              console.error(`[文章脚本:${scriptInstanceId}] 清理mermaid对象出错:`, e);
            }
          }
          
          // 移除页面上可能留下的mermaid相关元素
          try {
            // 移除所有可能的mermaid样式和元素
            const mermaidElements = [
              '#mermaid-style', 
              '#mermaid-cloned-styles', 
              '.mermaid-svg-reference',
              'style[id^="mermaid-"]'
            ];
            
            document.querySelectorAll(mermaidElements.join(', ')).forEach(el => {
              if (el && el.parentNode) {
                console.log(`[文章脚本:${scriptInstanceId}] 移除Mermaid元素:`, el.id || el.className);
                el.parentNode.removeChild(el);
              }
            });
          } catch (e) {
            console.error(`[文章脚本:${scriptInstanceId}] 清理Mermaid元素时出错:`, e);
          }
        });
      }
      
      // 启动所有功能
      setupCodeCopy();
      setupProgressBar();
      setupTableOfContents();
      setupMermaid();
      
      console.log(`[文章脚本:${scriptInstanceId}] 所有功能初始化完成`);
    }
    
    // 执行初始化
    registerCleanupEvents();
    initializeFeatures();
  })();
</script>
