<template>
  <div class="markdown-viewer">

    <!-- 目录侧边栏 -->
    <aside class="toc-sidebar" ref="tocSidebar">
      <div class="toc-header">
        <h2>目录</h2>
      </div>
      <div class="toc-content">
        <MDOutlineTree :data="tocTreeData"/>
      </div>
    </aside>

    <!-- 主内容区域 -->
    <main class="content" ref="content">
      <div v-if="loading" class="loading-indicator">加载中...</div>
      <div v-else-if="error" class="error-message">{{ error }}</div>
      <div v-else v-html="renderedContent" class="markdown-content"></div>
    </main>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, nextTick, onBeforeMount, unref } from 'vue';
import { marked } from 'marked';
import { throttle } from 'lodash-es';
import MDOutlineTree from './MDOutlineTree.vue'
let hljs;
const hljsPms = import('highlight.js').then(res => {
  hljs = window.hljs = res.default;
  return import('highlightjs-line-numbers.js');
}).then(() => {
  hljs.initLineNumbersOnLoad();
  return hljs;
});


const props = defineProps({
  filePath: {
    type: String,
    required: true
  },
  debounceTime: {
    type: Number,
    default: 100
  }
});

// 响应式数据
const loading = ref(true);
const error = ref(null);
const markdownText = ref('');
const renderedContent = ref('');
const toc = ref([]);
const activeSection = ref('');
const content = ref(null);
const tocSidebar = ref(null);
const tocTreeData = ref([])
// 配置marked
const renderer = new marked.Renderer();
renderer.code = (code, language) => {
  const highlighted = hljs.highlightAuto(code).value;
  return `
    <div class="code-block">
      <pre class="hljs"><code>${highlighted}</code></pre>
    </div>
  `;
};
marked.setOptions({ renderer });
// 渲染h头
renderer.heading = ({ text, depth }) => {
  const escapedText = toc.value.length
  // text.toLowerCase().replace(/[^\w]+/g, '-');
  toc.value.push({
    id: escapedText,
    level: depth,
		title: text,
		anchor: escapedText
	})
  const node = {
    key: escapedText,
    title: text
  }
  let parent;
  let currParent;
  let data;
  let loopData = data = unref(tocTreeData.value);
  let d = depth;
  while (d >= 1) {
    if (d === 1) {
      loopData.push(node);
    }
    parent = loopData.at(-1);
    if (!parent) {
      loopData.push(parent = { key: Math.rendom(), children: [] });
    }
    loopData = parent.children = parent.children ?? [];
    d--;
  }

  return `
    <h${depth} id="${escapedText}">
      <a name="${escapedText}" class="anchor" href="#${escapedText}">
        <span class="header-link"></span>
      </a>
      ${text}
    </h${depth}>`;
};
let renderList = renderer.listitem

renderer.listitem = (src)=>{
  return renderList.call(renderer, src);
}
marked.setOptions({
  renderer,
  highlight: (code, lang) => {
    if (lang && hljs.getLanguage(lang)) {
      return hljs.highlight(lang, code).value;
    }
    return hljs.highlightAuto(code).value;
  },
  pedantic: false,
  gfm: true,
  breaks: false,
  sanitize: false,
  smartLists: true,
  smartypants: false,
  xhtml: false
});

// 加载Markdown文件
const loadMarkdownFile = async () => {
  try {
    const filePath = props.filePath
    loading.value = true;
    error.value = null;
    let fetchMdPms

    if(filePath.startsWith('__localWebViewPath/')){
      if(!window.vscodeApi){
        console.error('获取__localWebViewPath的md文档时, 无法获取VSCode API')
        return
      }
      window.vscodeApi.postMessage({
        type: 'log',
        message: '[MarkdownViewer] 获取本地markdown...' + filePath
      });
      window.vscodeApi.postMessage({
        type: 'loadMd',
        mdPath: filePath
      });
      window.addEventListener('message', event => {
        if (event.data.type === 'mdContent') {
          window.vscodeApi.postMessage({
            type: 'log',
            message: '[MarkdownViewer] 获取本地markdown成功'
          });
          markdownText.value = event.data.data
        }
      });
    }else{
      fetchMdPms = fetch(props.filePath);
      const response = await fetchMdPms
      if (!response.ok) throw new Error('无法加载Markdown文件');
      markdownText.value = await response.text();
    }
    await hljsPms;
    // 初始化高亮和行号插件
    hljs.highlightAll();
    renderMarkdown();
  } catch (err) {
    error.value = err.message;
    console.error('加载Markdown文件失败:', err);
  } finally {
    loading.value = false;
  }
};

// 渲染Markdown
const renderMarkdown = () => {
  console.log(markdownText.value);

  toc.value = []; // 清空目录
  renderedContent.value = marked(markdownText.value);
  // 等待DOM更新后初始化高亮
  nextTick(() => {
    document.querySelectorAll('pre code').forEach(block => {
      hljs.highlightElement(block);
    });
    // setupHeadingObservers();
  });
};

// 设置IntersectionObserver来检测当前可见的标题
let observer = null;
const setupHeadingObservers = () => {
  // 先清理之前的observer
  if (observer) {
    observer.disconnect();
  }

  const headings = document.querySelectorAll('h1, h2, h3, h4, h5, h6');
  observer = new IntersectionObserver(
    (entries) => {
      entries.forEach(entry => {
        if (entry.isIntersecting && entry.intersectionRatio >= 0.5) {
          activeSection.value = entry.target.id;
        }
      });
    },
    {
      root: null,
      rootMargin: '0px 0px -50% 0px',
      threshold: [0, 0.5, 1]
    }
  );

  headings.forEach(heading => {
    observer.observe(heading);
  });
};

// 滚动到指定标题
const scrollToHeading = (anchor) => {
  const element = document.getElementById(anchor);
  if (element) {

    // 平滑滚动
    element.scrollIntoView({
      behavior: 'smooth',
      block: 'start'
    });

    // 更新URL哈希而不触发滚动
    history.replaceState(null, null, `#${anchor}`);
  }
};


// 处理窗口大小变化
const handleResize = throttle(() => {
  if (window.innerWidth >= 768) {
  }
}, props.debounceTime);

// 生命周期钩子
onBeforeMount(()=>{
  loadMarkdownFile();
})
onMounted(() => {
  window.addEventListener('resize', handleResize);
});

onUnmounted(() => {
  window.removeEventListener('resize', handleResize);
  if (observer) {
    observer.disconnect();
  }
});
</script>

<style scoped>
/* 行号容器样式 */
.hljs-ln-numbers {
  text-align: center;
  border-right: 1px solid;
  /* 右侧分割线 */
  padding-right: 10px;
}

/* 代码块容器 */
.code-block {
  position: relative;
  padding-left: 3em;
  /* 留出行号空间 */
}

/* 行号与代码对齐 */
.hljs-ln td:first-child {
  vertical-align: top;
}

.markdown-viewer {
  display: flex;
  /* min-height: 100vh; */
  position: relative;
}

.toc-sidebar {
  width: min(30vw, 280px);
  height: calc(100vh - 100px);
  overflow-y: auto;
  padding: 20px;
  box-sizing: border-box;
  border-right: 1px solid;
  position: sticky;
  top: 0;
  transition: transform 0.3s ease;
  z-index: 10;
}

.toc-header {
  padding-bottom: 15px;
  border-bottom: 1px solid;
  margin-bottom: 15px;
}

.toc-header h2 {
  margin: 0;
  font-size: 1.2rem;
}
.toc-content {
  height: calc(100vh - 200px);
}
.toc-content ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.toc-content li {
  margin: 6px 0;
  line-height: 1.4;
}

.toc-content a {
  display: block;
  padding: 4px 8px;
  text-decoration: none;
  border-radius: 3px;
  transition: all 0.2s;
  font-size: 0.9rem;
}

.toc-content a.active {
  font-weight: 600;
}

.content {
  flex: 1;
  height: calc(100vh - 100px);
  padding: 16px;
  overflow-y: auto;
  max-width: 800px;
  margin: 0 auto;
}

.loading-indicator,
.error-message {
  padding: 20px;
  text-align: center;
}



/* Markdown内容样式 */
.markdown-content {
  line-height: 1.6;
}

.markdown-content :deep(h1),
.markdown-content :deep(h2),
.markdown-content :deep(h3),
.markdown-content :deep(h4),
.markdown-content :deep(h5),
.markdown-content :deep(h6) {
  margin-top: 1.5em;
  margin-bottom: 0.8em;
  position: relative;
}

.markdown-content :deep(h1) {
  font-size: 2em;
  padding-bottom: 0.3em;
}

.markdown-content :deep(h2) {
  font-size: 1.5em;
  padding-bottom: 0.3em;
}

.markdown-content :deep(.anchor) {
  position: absolute;
  left: -20px;
  opacity: 0;
  transition: opacity 0.2s;
}

.markdown-content :deep(h1:hover .anchor),
.markdown-content :deep(h2:hover .anchor),
.markdown-content :deep(h3:hover .anchor),
.markdown-content :deep(h4:hover .anchor),
.markdown-content :deep(h5:hover .anchor),
.markdown-content :deep(h6:hover .anchor) {
  opacity: 1;
}

/* 移动端样式 */
@media (max-width: 400px) {
  .mobile-menu-button {
    display: block;
  }

  .toc-sidebar {
    position: fixed;
    top: 100px;
    bottom: 0;
    left: 0;
    transform: translateX(-100%);
    width: 30%;
    max-width: 300px;
    box-shadow: 2px 0 10px rgba(0, 0, 0, 0.1);
  }

  .markdown-viewer.mobile-menu-open .toc-sidebar {
    transform: translateX(0);
  }

  .content {
    padding: 20px;
    width: 100%;
    max-width: none;
  }
}

/* 代码块样式 */
.markdown-content :deep(pre) {
  border-radius: 6px;
  padding: 16px;
  overflow: auto;
  line-height: 1.45;
  margin-bottom: 16px;
}

.markdown-content :deep(code) {
  font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace;
  font-size: 85%;
}
</style>