<template>
  <div class="mermaid-wrapper" ref="wrapperRef">
    <div class="mermaid svg-mermaid" ref="mermaidRef" :data-graph="graph" @click="openPreview"></div>
    <button class="mermaid-expand" @click.stop="openPreview" title="全屏预览">
      <Maximize2 :size="8" />
    </button>
    <ImagePreview :visible="showPreview" :html="renderedHtml" @close="showPreview = false" />
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { Maximize2 } from '@lucide/vue'
import ImagePreview from './ImagePreview.vue'

const props = defineProps({
  graph: {
    type: String,
    default: '',
  },
  id: {
    type: String,
    default: () => `mermaid-${Math.random().toString(36).slice(2, 9)}`,
  },
})

const wrapperRef = ref(null)
const mermaidRef = ref(null)
const showPreview = ref(false)
const renderedHtml = ref('')
let mut = null

// Zoom/pan state
let scale = 1
let translateX = 0
let translateY = 0
let isDragging = false
let lastX = 0
let lastY = 0

const updateTransform = () => {
  if (!mermaidRef.value) return
  mermaidRef.value.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scale})`
  mermaidRef.value.style.transformOrigin = '0 0'
}

const onWheel = (e) => {
  e.preventDefault()
  const delta = e.deltaY > 0 ? 0.9 : 1.1
  const newScale = Math.min(Math.max(scale * delta, 0.2), 5)

  const rect = wrapperRef.value.getBoundingClientRect()
  const cx = e.clientX - rect.left
  const cy = e.clientY - rect.top

  translateX = cx - (cx - translateX) * (newScale / scale)
  translateY = cy - (cy - translateY) * (newScale / scale)
  scale = newScale

  updateTransform()
}

const onMouseDown = (e) => {
  if (e.button !== 0) return
  isDragging = true
  lastX = e.clientX
  lastY = e.clientY
  wrapperRef.value.style.cursor = 'grabbing'
}

const onMouseMove = (e) => {
  if (!isDragging) return
  translateX += e.clientX - lastX
  translateY += e.clientY - lastY
  lastX = e.clientX
  lastY = e.clientY
  updateTransform()
}

const onMouseUp = () => {
  isDragging = false
  if (wrapperRef.value) wrapperRef.value.style.cursor = 'grab'
}

const onDblClick = () => {
  scale = 1
  translateX = 0
  translateY = 0
  updateTransform()
}

function openPreview() {
  if (mermaidRef.value && mermaidRef.value.innerHTML) {
    renderedHtml.value = mermaidRef.value.innerHTML
    showPreview.value = true
  }
}

const renderMermaid = async () => {
  if (!mermaidRef.value) return

  try {
    const mermaid = (await import('mermaid')).default
    mermaid.initialize({
      startOnLoad: false,
      theme: document.documentElement.classList.contains('dark') ? 'dark' : 'default',
      securityLevel: 'loose',
    })

    const graphData = props.graph || mermaidRef.value.getAttribute('data-graph') || ''
    if (!graphData) return

    const decoded = decodeURIComponent(graphData)
    const { svg } = await mermaid.render(props.id, decoded)
    mermaidRef.value.innerHTML = svg

    // Reset zoom/pan on re-render
    scale = 1
    translateX = 0
    translateY = 0
    updateTransform()
  } catch (error) {
    console.error('Mermaid render error:', error)
    mermaidRef.value.innerHTML = `<pre style="color: red;">Mermaid Error: ${error.message}</pre>`
  }
}

onMounted(() => {
  renderMermaid()

  mut = new MutationObserver(() => renderMermaid())
  mut.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] })

  const el = wrapperRef.value
  if (el) {
    el.addEventListener('wheel', onWheel, { passive: false })
    el.addEventListener('mousedown', onMouseDown)
    window.addEventListener('mousemove', onMouseMove)
    window.addEventListener('mouseup', onMouseUp)
    el.addEventListener('dblclick', onDblClick)
  }
})

onUnmounted(() => {
  if (mut) mut.disconnect()

  const el = wrapperRef.value
  if (el) {
    el.removeEventListener('wheel', onWheel)
    el.removeEventListener('mousedown', onMouseDown)
    el.removeEventListener('dblclick', onDblClick)
  }
  window.removeEventListener('mousemove', onMouseMove)
  window.removeEventListener('mouseup', onMouseUp)
})
</script>

<style scoped>
.mermaid-wrapper {
  overflow: hidden;
  cursor: grab;
  border: 1px solid var(--vp-c-divider);
  border-radius: 8px;
  padding: 24px;
  margin: 24px 0;
  position: relative;
  width: 100%;
  min-height: 200px;
}

.mermaid-wrapper:active {
  cursor: grabbing;
}

.mermaid {
  width: 100%;
  text-align: center;
}

.mermaid :deep(.svg-mermaid) {
  width: 100%;
  height: auto;
  min-width: 600px;
}

.mermaid-expand {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 28px !important;
  height: 28px !important;
  min-width: 28px !important;
  min-height: 28px !important;
  max-width: 28px !important;
  max-height: 28px !important;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--vp-c-divider);
  border-radius: 6px;
  background: var(--vp-c-bg);
  color: var(--vp-c-text-2);
  cursor: pointer;
 /* opacity: 0;
  transition: opacity 0.2s;*/
  z-index: 2;
  flex-shrink: 0;
  padding: 0;
  margin: 0;
  line-height: 1;
}
/*
.mermaid-wrapper:hover .mermaid-expand {
  opacity: 1;
}*/

.mermaid-expand:hover {
  border-color: var(--vp-c-brand-1);
  color: var(--vp-c-brand-1);
}
</style>
