<script setup lang="ts">
import { ref, computed, onBeforeUnmount } from "vue";

const props = defineProps<{
  markdownContent: string;
}>();

const emit = defineEmits<{
  headingClick: [heading: { text: string; level: number }];
}>();

interface OutlineItem {
  text: string;
  level: number; // 1, 2, 3
  id: string;
}

const headings = computed<OutlineItem[]>(() => {
  if (!props.markdownContent) return [];
  const result: OutlineItem[] = [];
  const regex = /^(#{1,3})\s+(.+)$/gm;
  let match: RegExpExecArray | null;
  while ((match = regex.exec(props.markdownContent)) !== null) {
    const level = match[1].length;
    const text = match[2]
      .replace(
        /\*{1,3}|_{1,3}|`+|~~|\[([^\]]*)\]\([^)]*\)/g,
        (_, linkText) => linkText || "",
      )
      .trim();
    if (text) {
      result.push({
        text,
        level,
        id: `heading-${result.length}`,
      });
    }
  }
  return result;
});

const onHeadingClick = (item: OutlineItem) => {
  emit("headingClick", { text: item.text, level: item.level });
};

// ---- panel resize ----
const MIN_PANEL_WIDTH = 150;
const MAX_PANEL_WIDTH = 500;
const DEFAULT_PANEL_WIDTH = 208; // w-52

const panelWidth = ref(DEFAULT_PANEL_WIDTH);
const isResizing = ref(false);

let resizeStartX = 0;
let resizeStartWidth = 0;

function startResize(e: MouseEvent) {
  resizeStartX = e.clientX;
  resizeStartWidth = panelWidth.value;
  isResizing.value = true;
  document.addEventListener("mousemove", onResize);
  document.addEventListener("mouseup", stopResize);
  document.body.style.cursor = "col-resize";
  document.body.style.userSelect = "none";
  e.preventDefault();
}

function onResize(e: MouseEvent) {
  if (!isResizing.value) return;
  const delta = e.clientX - resizeStartX;
  panelWidth.value = Math.min(MAX_PANEL_WIDTH, Math.max(MIN_PANEL_WIDTH, resizeStartWidth + delta));
}

function stopResize() {
  isResizing.value = false;
  document.removeEventListener("mousemove", onResize);
  document.removeEventListener("mouseup", stopResize);
  document.body.style.cursor = "";
  document.body.style.userSelect = "";
}

onBeforeUnmount(() => {
  document.removeEventListener("mousemove", onResize);
  document.removeEventListener("mouseup", stopResize);
  document.body.style.cursor = "";
  document.body.style.userSelect = "";
});
</script>

<template>
  <aside
    class="outline-panel flex flex-col shrink-0 overflow-hidden"
    :class="{ 'transition-all duration-300 ease-in-out': !isResizing }"
    :style="{ width: panelWidth + 'px' }"
  >
    <!-- Header -->
    <div class="outline-panel-header flex items-center px-3 py-3">
      <span class="outline-panel-title text-xs font-semibold uppercase tracking-wider">
        大纲
      </span>
    </div>

    <!-- Outline content -->
    <div class="flex-1 overflow-y-auto px-2 py-2">
      <template v-if="headings.length === 0">
        <p class="outline-empty text-xs px-2 py-4 text-center leading-relaxed">
          暂无标题<br />使用 H1-H3 标题<br />自动生成大纲
        </p>
      </template>
      <template v-else>
        <div
          v-for="item in headings"
          :key="item.id"
          :class="[
            'outline-item px-2 py-1 rounded-md text-sm cursor-pointer transition-colors truncate',
            item.level === 1
              ? 'outline-item-level-1 font-medium ml-0'
              : item.level === 2
                ? 'outline-item-level-2 ml-3'
                : 'outline-item-level-3 ml-6 text-xs',
          ]"
          :title="item.text"
          @click="onHeadingClick(item)"
        >
          {{ item.text }}
        </div>
      </template>
    </div>

    <!-- Resize handle -->
    <div
      class="outline-resize-handle"
      :class="{ 'outline-resize-handle-active': isResizing }"
      @mousedown="startResize"
    >
      <div class="outline-resize-handle-bar"></div>
    </div>
  </aside>
</template>

<style scoped>
.outline-panel {
  position: relative;
  border-right: 1px solid var(--app-border);
  background: color-mix(in srgb, var(--app-sidebar-bg) 82%, transparent);
}

/* ---- Resize handle ---- */
.outline-resize-handle {
  position: absolute;
  top: 0;
  right: -2px;
  bottom: 0;
  z-index: 25;
  display: flex;
  width: 7px;
  align-items: center;
  justify-content: center;
  cursor: col-resize;
  transition: background-color 0.15s ease;
}

.outline-resize-handle:hover,
.outline-resize-handle-active {
  background: color-mix(in srgb, var(--app-accent) 18%, transparent);
}

.outline-resize-handle-bar {
  width: 1px;
  height: 100%;
  border-radius: 1px;
  background: transparent;
  transition: background-color 0.15s ease;
}

.outline-resize-handle:hover .outline-resize-handle-bar,
.outline-resize-handle-active .outline-resize-handle-bar {
  background: color-mix(in srgb, var(--app-accent) 36%, transparent);
}

.outline-panel-header {
  border-bottom: 1px solid var(--app-border);
}

.outline-panel-title,
.outline-item-level-2 {
  color: var(--app-muted);
}

.outline-empty,
.outline-item-level-3 {
  color: var(--app-subtle);
}

.outline-item:hover {
  background: var(--app-hover);
}

.outline-item-level-1 {
  color: var(--app-text);
}
</style>
