<template>
  <Teleport to="body">
    <div 
      v-if="isOpen"
      class="fixed inset-0 z-[100] flex items-center justify-center transition-opacity duration-300 pointer-events-auto"
      :class="[
        isMaximized ? 'p-0' : 'p-0 md:p-10',
        isAnimating ? 'opacity-0' : 'opacity-100'
      ]"
    >
    <div class="absolute inset-0 bg-black/90 backdrop-blur-sm" @click="close"></div>
    <div 
      class="relative z-[101] bg-[#0a0a0c] border-0 md:border border-white/10 flex flex-col overflow-hidden shadow-2xl transform transition-all duration-300"
      :class="[
        isAnimating ? 'scale-95' : 'scale-100',
        isMaximized
          ? 'fixed inset-0 w-full h-[100dvh] max-w-none rounded-none'
          : 'w-full max-w-6xl h-[100dvh] max-h-[100dvh] md:h-[80vh] md:max-h-[80vh] rounded-none md:rounded-2xl'
      ]"
    >
      <div class="h-14 md:h-16 border-b border-white/10 flex items-center gap-3 px-4 md:px-6 bg-white/5 shrink-0 min-w-0">
        <div class="flex gap-2 shrink-0">
          <button
            type="button"
            class="w-3 h-3 rounded-full bg-[#ff5f56] hover:brightness-110 transition-all"
            aria-label="关闭"
            @click="close"
          />
          <button
            type="button"
            class="w-3 h-3 rounded-full bg-[#ffbd2e] hover:brightness-110 transition-all"
            aria-label="最小化"
            @click="close"
          />
          <button
            type="button"
            class="w-3 h-3 rounded-full bg-[#27c93f] hover:brightness-110 transition-all"
            aria-label="最大化"
            @click="toggleMaximize"
          />
        </div>
        <span class="font-bold text-white truncate text-sm md:text-base min-w-0 flex-1">{{ title }}</span>
      </div>

      <div v-if="posts && posts.length > 0" class="px-4 md:px-6 py-2 bg-white/[0.02] border-b border-white/10 flex items-center gap-2 shrink-0 overflow-x-auto hide-scrollbar">
        <span class="text-xs text-art-muted font-mono shrink-0">关联文章</span>
        <a
          v-for="p in posts"
          :key="p.id"
          :href="`/blog/${p.id}`"
          target="_blank"
          rel="noopener noreferrer"
          class="text-xs px-2 py-1 rounded bg-white/5 border border-white/10 text-art-accent hover:text-white hover:border-art-accent/50 transition-colors truncate shrink-0 max-w-[70vw] md:max-w-none"
          @click.stop
        >
          {{ p.title }} ↗
        </a>
      </div>

      <!-- Mobile tabs -->
      <div class="md:hidden flex border-b border-white/10 shrink-0">
        <button
          type="button"
          class="flex-1 px-4 py-2.5 text-xs font-mono transition-colors"
          :class="mobileTab === 'code'
            ? 'text-art-accent bg-white/5 border-b-2 border-art-accent'
            : 'text-white/40'"
          @click="mobileTab = 'code'"
        >
          代码
        </button>
        <button
          type="button"
          class="flex-1 px-4 py-2.5 text-xs font-mono transition-colors"
          :class="mobileTab === 'preview'
            ? 'text-art-accent bg-white/5 border-b-2 border-art-accent'
            : 'text-white/40'"
          @click="mobileTab = 'preview'"
        >
          {{ showHtmlPreview ? '预览 / 备注' : '备注' }}
        </button>
      </div>

      <div class="flex-1 flex flex-col md:flex-row min-h-0 overflow-hidden">
        <!-- Left: code panel -->
        <div
          class="flex flex-col min-h-0 bg-[#0d0d0d] md:border-r border-white/10"
          :class="[
            codePanelCollapsed ? 'hidden' : 'w-full md:w-1/2',
            mobileTab === 'code' ? 'flex flex-1' : 'hidden md:flex'
          ]"
        >
          <div class="sticky top-0 z-10 flex justify-end px-3 md:px-4 py-2 bg-[#0d0d0d]/95 backdrop-blur-sm border-b border-white/5 shrink-0">
            <button
              class="text-xs bg-white/10 px-2 py-1 rounded text-white/50 hover:text-white transition-colors"
              @click="copyCode"
            >
              复制
            </button>
          </div>
          <div class="flex-1 overflow-auto p-4 md:p-6 min-h-0">
            <pre class="font-mono text-xs md:text-sm leading-relaxed m-0"><code ref="codeBlock" :class="languageClass">{{ code }}</code></pre>
          </div>
        </div>

        <!-- Right: preview / description -->
        <div
          class="relative flex flex-col min-h-0 overflow-hidden bg-[#1a1a1a]"
          :class="[
            codePanelCollapsed ? 'w-full md:w-full flex-1' : 'w-full md:w-1/2',
            mobileTab === 'preview' ? 'flex flex-1' : 'hidden md:flex'
          ]"
          :style="previewBackgroundStyle"
        >
          <div v-if="showHtmlPreview" class="hidden md:flex items-center border-b border-white/10 shrink-0">
            <button
              v-for="tab in rightTabs"
              :key="tab.id"
              class="flex-1 px-4 py-2.5 text-xs font-mono transition-colors"
              :class="activeRightTab === tab.id
                ? 'text-art-accent bg-white/5 border-b-2 border-art-accent'
                : 'text-white/40 hover:text-white/70'"
              @click="activeRightTab = tab.id"
            >
              {{ tab.label }}
            </button>
            <button
              v-if="showCollapseToggle"
              type="button"
              class="shrink-0 px-3 py-2 text-xs font-mono text-art-muted hover:text-white border-l border-white/10 transition-colors"
              @click="codePanelCollapsed = !codePanelCollapsed"
            >
              {{ codePanelCollapsed ? '展开源码' : '收起源码' }}
            </button>
          </div>

          <div v-if="showHtmlPreview" class="md:hidden flex border-b border-white/10 shrink-0">
            <button
              v-for="tab in rightTabs"
              :key="tab.id"
              class="flex-1 px-3 py-2 text-xs font-mono transition-colors"
              :class="activeRightTab === tab.id
                ? 'text-art-accent bg-white/5 border-b-2 border-art-accent'
                : 'text-white/40'"
              @click="activeRightTab = tab.id"
            >
              {{ tab.label }}
            </button>
          </div>

          <iframe
            v-if="showHtmlPreview && activeRightTab === 'preview'"
            class="flex-1 w-full border-0 bg-white min-h-0"
            sandbox="allow-scripts"
            :srcdoc="code"
          />
          <div v-else class="flex-1 overflow-auto p-4 md:p-8 text-white/80 min-h-0">
            <h4 v-if="!showHtmlPreview" class="text-sm text-art-muted mb-3">备注</h4>
            <article
              v-if="description"
              class="snippet-description prose prose-invert prose-sm max-w-none text-art-muted leading-relaxed"
              v-html="renderedDescription"
            />
            <p v-else class="text-sm text-white/30 font-mono">暂无备注</p>
          </div>
        </div>
      </div>
    </div>
  </div>
  </Teleport>
</template>

<script setup lang="ts">
import { ref, watch, computed, nextTick } from 'vue'
import hljs from 'highlight.js'
import type { CodeType, PostBrief } from '../services/api'
import { resolveHighlightLanguage, isHtmlFrontendType } from '../utils/codeHighlight'
import { renderMarkdown } from '../utils/markdownRenderer'
import { useToast } from '../composables/useToast'

const props = defineProps<{
  isOpen: boolean
  title: string
  code: string
  type?: string
  codeType?: CodeType | null
  description?: string
  posts?: PostBrief[]
}>()

const emit = defineEmits(['close'])

const toast = useToast()
const isAnimating = ref(true)
const isMaximized = ref(false)
const codePanelCollapsed = ref(false)
const codeBlock = ref<HTMLElement | null>(null)
const activeRightTab = ref<'preview' | 'description'>('preview')
const mobileTab = ref<'code' | 'preview'>('code')

const rightTabs = [
  { id: 'preview' as const, label: '效果预览' },
  { id: 'description' as const, label: '备注' },
]

const highlightLang = computed(() => {
  if (props.codeType?.name) return props.codeType.name
  return props.type || 'plaintext'
})

const languageClass = computed(() => `language-${resolveHighlightLanguage(highlightLang.value)}`)

const showHtmlPreview = computed(() => isHtmlFrontendType(props.codeType ?? null))

const showCollapseToggle = computed(
  () => showHtmlPreview.value && activeRightTab.value === 'preview'
)

const renderedDescription = ref('')
let descriptionGeneration = 0

const renderDescription = (content: string) => {
  const generation = ++descriptionGeneration
  renderedDescription.value = ''

  const run = async () => {
    try {
      const html = await renderMarkdown(content)
      if (generation !== descriptionGeneration) return
      renderedDescription.value = html
    } catch (err) {
      console.error('Failed to render snippet description:', err)
    }
  }

  void run()
}

watch(
  [() => props.description, () => props.isOpen],
  ([description, isOpen]) => {
    if (!isOpen || !description) {
      renderedDescription.value = ''
      return
    }
    renderDescription(description)
  },
  { immediate: true }
)

const highlightCode = () => {
  if (codeBlock.value) {
    delete codeBlock.value.dataset.highlighted
    hljs.highlightElement(codeBlock.value)
  }
}

const toggleMaximize = () => {
  isMaximized.value = !isMaximized.value
}

watch(() => props.isOpen, (newVal) => {
  if (newVal) {
    isMaximized.value = false
    codePanelCollapsed.value = false
    activeRightTab.value = 'preview'
    mobileTab.value = 'code'
    document.body.style.overflow = 'hidden'
    setTimeout(() => { isAnimating.value = false }, 10)
    nextTick(highlightCode)
  } else {
    document.body.style.overflow = ''
    isAnimating.value = true
  }
})

watch(() => props.code, () => nextTick(highlightCode))

watch(activeRightTab, (tab) => {
  if (tab === 'description') {
    codePanelCollapsed.value = false
  }
})

watch(codePanelCollapsed, (collapsed) => {
  if (!collapsed) {
    nextTick(highlightCode)
  }
})

const close = () => {
  isAnimating.value = true
  setTimeout(() => emit('close'), 300)
}

const copyCode = () => {
  navigator.clipboard.writeText(props.code)
  toast.success('代码已复制')
}

const previewBackgroundStyle = {
  backgroundImage: `
    linear-gradient(45deg, #1a1a1a 25%, transparent 25%), 
    linear-gradient(-45deg, #1a1a1a 25%, transparent 25%), 
    linear-gradient(45deg, transparent 75%, #1a1a1a 75%), 
    linear-gradient(-45deg, transparent 75%, #1a1a1a 75%)`,
  backgroundSize: '20px 20px',
  backgroundPosition: '0 0, 0 10px, 10px -10px, -10px 0px'
}
</script>

<style scoped>
.hide-scrollbar {
  -ms-overflow-style: none;
  scrollbar-width: none;
}
.hide-scrollbar::-webkit-scrollbar {
  display: none;
}

:deep(.snippet-description.prose pre) {
  background-color: transparent !important;
  margin: 0 !important;
  padding: 0 !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  border: none !important;
  white-space: pre !important;
}

:deep(.snippet-description.prose code) {
  font-family: 'JetBrains Mono', Menlo, Monaco, Consolas, monospace;
}

:deep(.snippet-description.prose :not(pre) > code) {
  color: #d4b383;
  background-color: rgba(212, 179, 131, 0.1);
  padding: 0.2em 0.4em;
  border-radius: 0.3em;
  font-weight: 500;
  word-break: break-word;
}

:deep(.snippet-description.prose h1),
:deep(.snippet-description.prose h2),
:deep(.snippet-description.prose h3) {
  color: #fff;
  font-family: serif;
  margin-top: 1.5em;
  margin-bottom: 0.6em;
  line-height: 1.3;
}

:deep(.snippet-description.prose h2) {
  font-size: 1.25rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  padding-bottom: 0.3rem;
}

:deep(.snippet-description.prose h3) {
  font-size: 1.1rem;
  color: rgba(255, 255, 255, 0.9);
}

:deep(.snippet-description.prose a) {
  color: #d4b383;
  text-decoration: none;
  border-bottom: 1px dashed rgba(212, 179, 131, 0.5);
  transition: all 0.2s;
  word-break: break-all;
}

:deep(.snippet-description.prose a:hover) {
  color: #fff;
  border-bottom-style: solid;
}

:deep(.snippet-description.prose blockquote) {
  border-left: 3px solid #d4b383;
  background: rgba(255, 255, 255, 0.02);
  padding: 0.8rem 1rem;
  border-radius: 0 0.5rem 0.5rem 0;
  color: rgba(255, 255, 255, 0.7);
  font-style: italic;
}

:deep(.snippet-description.prose ul li::marker) {
  color: #d4b383;
}

:deep(.snippet-description.prose img) {
  max-width: 100%;
  height: auto;
  border-radius: 0.5rem;
}

:deep(.snippet-description.prose video) {
  max-width: 100%;
  height: auto;
  border-radius: 0.5rem;
}
</style>
