<template>
  <div class="prompt-display" v-html="renderedContent"></div>
</template>

<script setup>
import { ref, watch, onUnmounted } from 'vue'
import { renderMarkdown } from '@/utils/markdown'

const props = defineProps({
  content: {
    type: String,
    default: ''
  },
  isStreaming: {
    type: Boolean,
    default: false
  }
})

// 当前显示的内容（用于打字机效果）
const displayedContent = ref('')
// 目标内容（完整内容）
const targetContent = ref('')
// 动画帧 ID
let animationFrameId = null
// 打字机速度（字符/帧，可根据性能调整）
const TYPING_SPEED = 3
// 是否正在执行打字机动画
const isTyping = ref(false)

/**
 * 高性能打字机效果渲染
 * 使用 requestAnimationFrame 实现平滑的逐字符显示
 */
function typewriterEffect() {
  if (!isTyping.value) return
  
  const currentLength = displayedContent.value.length
  const targetLength = targetContent.value.length
  
  if (currentLength >= targetLength) {
    // 已完成，停止动画
    isTyping.value = false
    displayedContent.value = targetContent.value
    return
  }
  
  // 每次增加多个字符以提高性能
  const nextLength = Math.min(currentLength + TYPING_SPEED, targetLength)
  displayedContent.value = targetContent.value.slice(0, nextLength)
  
  // 继续下一帧
  animationFrameId = requestAnimationFrame(typewriterEffect)
}

/**
 * 开始打字机效果
 */
function startTypewriter() {
  if (animationFrameId) {
    cancelAnimationFrame(animationFrameId)
  }
  
  isTyping.value = true
  animationFrameId = requestAnimationFrame(typewriterEffect)
}

/**
 * 停止打字机效果
 */
function stopTypewriter() {
  if (animationFrameId) {
    cancelAnimationFrame(animationFrameId)
    animationFrameId = null
  }
  isTyping.value = false
}

/**
 * 计算渲染的 HTML 内容
 */
const renderedContent = ref('')

/**
 * 更新渲染内容
 */
function updateRenderedContent() {
  const content = displayedContent.value
  if (!content) {
    renderedContent.value = ''
    return
  }
  
  // 渲染 markdown 为 HTML
  renderedContent.value = renderMarkdown(content)
}

// 监听 displayedContent 变化，更新渲染
watch(displayedContent, () => {
  updateRenderedContent()
}, { immediate: true })

/**
 * 处理内容更新
 */
function handleContentUpdate(newContent) {
  if (!newContent) {
    targetContent.value = ''
    displayedContent.value = ''
    stopTypewriter()
    return
  }
  
  // 更新目标内容
  targetContent.value = newContent
  
  if (props.isStreaming) {
    // 流式传输模式：使用打字机效果显示内容
    // 流式传输时，内容会逐步到达，使用打字机效果增强体验
    const currentLength = displayedContent.value.length
    const newLength = newContent.length
    
    if (newLength !== currentLength) {
      // 内容发生变化
      if (newLength < currentLength) {
        // 内容被重置或缩短，直接显示新内容
        displayedContent.value = newContent
        stopTypewriter()
      } else {
        // 内容增加，使用打字机效果显示新增部分
        if (!isTyping.value) {
          startTypewriter()
        }
      }
    }
  } else {
    // 静态内容模式：直接显示全部内容，不使用打字机效果
    displayedContent.value = newContent
    stopTypewriter()
  }
}

// 监听 content 变化
watch(() => props.content, (newContent) => {
  handleContentUpdate(newContent)
}, { immediate: true })

// 监听 isStreaming 变化
watch(() => props.isStreaming, (newVal, oldVal) => {
  if (!newVal && oldVal) {
    // 流式传输结束，确保显示完整内容，停止打字机效果
    if (targetContent.value) {
      displayedContent.value = targetContent.value
    }
    stopTypewriter()
  } else if (newVal) {
    // 开始流式传输，如果内容有变化，启动打字机效果
    // 打字机效果会在 handleContentUpdate 中根据内容变化自动启动
  }
})

// 组件卸载时清理
onUnmounted(() => {
  stopTypewriter()
})
</script>

<style scoped>
/* 修复 pre 标签撑开容器的问题 */
.prompt-display :deep(pre) {
  max-width: 100%;
  overflow-x: auto;
  word-break: break-word;
  white-space: pre-wrap;
  word-wrap: break-word;
}
</style>
