<template>
  <div class="w-full h-full">
    <!-- 主渲染区域 -->
    <div
      :class="{ 'streaming': isStreaming }"
    >
      <!-- 消息渲染器 - GitHub 风格 -->
      <div
        class="markdown-body"
        :class="{ 'streaming': isStreaming }"
        v-html="renderedContent"
      />
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, watch, onUnmounted, onMounted } from 'vue'
import { renderMarkdown } from '@/utils/markdown'
import type { ChatMessageRendererV2Props } from '@/services/ai-bridge'
import 'github-markdown-css/github-markdown.css'

const props = withDefaults(defineProps<ChatMessageRendererV2Props>(), {
  config: () => ({
    enableTypewriter: true,
    typewriterSpeed: 10,
    enableMarkdown: true,
    enableHighlighting: true
  })
})

const emit = defineEmits<{
  'stream-start': []
  'stream-chunk': [chunk: string]
  'stream-end': [fullContent: string]
  'error': [error: Error]
}>()

const internalContent = ref('')
const renderedContent = ref('')
const isPageVisible = ref(true)

watch(() => props.content, (newContent) => {
  if (newContent !== undefined && newContent !== null) {
    updateContent(newContent)
  }
}, { immediate: true })

watch(() => props.isStreaming, (newValue, oldValue) => {
  if (newValue && !oldValue) {
    handleStreamStart()
  } else if (!newValue && oldValue) {
    handleStreamEnd()
  }
})

async function updateContent(newContent = '') {
  if (props.isStreaming && internalContent.value) {
    await updateStreamingContent(newContent)
  } else {
    await updateStaticContent(newContent)
  }
}

async function updateStreamingContent(newFullContent: string) {
  const prev = internalContent.value

  let delta: string
  if (newFullContent.startsWith(prev)) {
    delta = newFullContent.slice(prev.length)
  } else {
    console.warn('[ChatMessageRendererV2] 流式内容乱序，使用完整内容')
    delta = newFullContent
    internalContent.value = ''
  }

  internalContent.value += delta
  emit('stream-chunk', delta)
  await renderContent(internalContent.value)
}

async function updateStaticContent(newContent: string) {
  internalContent.value = newContent
  await renderContent(newContent)
}

async function renderContent(content: string) {
  if (!content) {
    renderedContent.value = ''
    return
  }

  try {
    if (props.config?.enableMarkdown !== false) {
      renderedContent.value = await renderMarkdown(content)
    } else {
      renderedContent.value = content.replace(/\n/g, '<br>')
    }
  } catch (error) {
    console.error('[ChatMessageRendererV2] 渲染错误:', error)
    renderedContent.value = content
  }
}

function handleStreamStart() {
  internalContent.value = ''
  renderedContent.value = ''
  emit('stream-start')
}

function handleStreamEnd() {
  emit('stream-end', internalContent.value)
}

function handleVisibilityChange() {
  const wasVisible = isPageVisible.value
  isPageVisible.value = !document.hidden

  if (!wasVisible && isPageVisible.value && props.content) {
    updateContent(props.content)
  }
}

onMounted(() => {
  document.addEventListener('visibilitychange', handleVisibilityChange)
  handleVisibilityChange()
})

onUnmounted(() => {
  document.removeEventListener('visibilitychange', handleVisibilityChange)
})

defineExpose({
  reset: () => {
    internalContent.value = ''
    renderedContent.value = ''
  }
})
</script>

<style scoped lang="less">
</style>
