<template>
  <div class="asistant-container flex flex-column">
    <div class="header">
      <HeaderTitle hasSetting styleType="3" />
    </div>
    <div class="loading-container" v-if="isLoading">
      <GenerateLoading />
    </div>
    <template v-else>
      <div class="content flex-1" v-if="!isLoading">
        <NoticeList
          ref="noticeListRef"
          :list="messageList"
          :is-streaming="isStreaming"
          :streaming-message="currentStreamingMessage"
        />
      </div>
      <div class="footer" v-if="!isLoading">
        <InputArea @send-message="handleSendMessage" />
        <div class="continue">
          <button class="btn" @click="handleContinue">Continue</button>
        </div>
      </div>
    </template>
  </div>
</template>
<script setup lang="ts">
import HeaderTitle from '@/components/HeaderTitle.vue'
import NoticeList from './components/NoticeList.vue'
import InputArea from './components/InputArea.vue'
import GenerateLoading from './components/GenerateLoading.vue'
import { ref, onMounted, onUnmounted, onActivated } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { useUserInfoStore, useGenerateStore } from '@/stores'
import { streamChatAddress } from '@/api/workshop'
import { generateUUID } from '@/utils/tools'
import { showToast } from 'vant'

const router = useRouter()
const route = useRoute()
const generateStore = useGenerateStore()
const userInfoStore = useUserInfoStore()

defineOptions({
  name: 'asistant'
})

// 定义NoticeList组件引用类型
interface NoticeListRef {
  simulateSendMessage: () => void
  scrollToBottom: () => void
}
// 定义消息类型
interface ChatMessage {
  sessionId: string | number
  type: string
  content: string
  timestamp: string
  id?: string
  self?: boolean
}

const isLoading = ref<boolean>(false)
const noticeListRef = ref<NoticeListRef | null>(null)
const messageList = ref<ChatMessage[]>([])

// 流式消息相关状态
const isStreaming = ref<boolean>(false)
const currentStreamingMessage = ref<ChatMessage | null>(null)
const sessionId = ref<string>('')

const sendPrefilledMessage = () => {
  const { message, ...restQuery } = route.query
  if (typeof message === 'string' && message.trim()) {
    handleSendMessage(message)
    router.replace({
      path: route.path,
      query: restQuery
    })
  }
}

onMounted(() => {
  sessionId.value = Math.floor(Date.now() / 1000).toString()
  generateStore.setSessionId(sessionId.value)
  sendPrefilledMessage()
})

onActivated(() => {
  noticeListRef.value?.scrollToBottom()
})

onUnmounted(() => {
  abort.abort()
})

const handleSendMessage = (message: string): void => {
  console.log('发送:', message)

  // 添加用户消息到列表
  const userMessage: ChatMessage = {
    id: generateUUID(),
    type: 'text',
    content: message,
    timestamp: new Date().toISOString(),
    sessionId: sessionId.value,
    self: true
  }
  messageList.value.push(userMessage)

  // 开始流式接收AI回复
  handleFetchMessage(message)
}

const abort = new AbortController()
const handleFetchMessage = (message: string) => {
  const params = {
    message: message,
    sessionId: sessionId.value,
    gender: 'male'
  }

  // 创建AI消息对象
  const aiMessage: ChatMessage = {
    id: generateUUID(),
    type: 'text',
    content: '',
    timestamp: new Date().toISOString(),
    sessionId: sessionId.value
  }

  // 添加到消息列表
  isStreaming.value = true
  messageList.value.push(aiMessage)
  currentStreamingMessage.value = aiMessage

  // 直接使用 fetch 进行流式请求
  const token = userInfoStore.state.token
  const baseURL = import.meta.env.MODE === 'development' ? '' : import.meta.env.VITE_APP_URL

  // 构建查询参数
  const queryParams = new URLSearchParams()
  Object.entries(params).forEach(([key, value]) => {
    queryParams.append(key, String(value))
  })

  const url = `${baseURL}${streamChatAddress}?${queryParams.toString()}`

  fetch(url, {
    method: 'GET',
    headers: {
      Authorization: token,
      'Content-Type': 'application/json'
    },
    credentials: 'include'
  })
    .then(async (response) => {
      // 检查响应内容类型，判断是否为流式响应
      const contentType = response.headers.get('content-type') || ''
      const isStreamResponse =
        contentType.includes('text/event-stream') || contentType.includes('stream')

      if (!response.ok) {
        // 非流式错误响应，使用 text() 读取错误信息
        const errorText = await response.text()
        console.error('请求错误:', errorText)
        showToast({
          message: `failed to fetch: ${response.status}`,
          position: 'top',
          icon: 'none'
        })
        throw new Error(`发起对话错误--- ${response.status}: ${errorText}`)
      }

      // 不是流式响应，使用 text()读取错误信息
      if (!isStreamResponse) {
        const text = await response.text()

        try {
          const errorData = JSON.parse(text)
          if (errorData.message || errorData.error) {
            showToast({
              message: errorData.message || errorData.error || '请求失败',
              position: 'top',
              icon: 'none'
            })
          }
        } catch (e) {
          // 如果不是 JSON，直接显示文本内容
          showToast({
            message: text || '请求失败',
            position: 'top',
            icon: 'none'
          })
          throw new Error(text || '请求失败')
        }

        isStreaming.value = false
        currentStreamingMessage.value = null
        return
      }

      // 流式响应处理
      let contentBody = ''
      let buffer = ''
      const reader = response.body?.getReader()
      if (!reader) throw new Error('无法获取流读取器')

      const decoder = new TextDecoder()

      try {
        let flag = true
        while (flag) {
          const { done, value } = await reader.read()
          if (done) {
            console.log('传输结束 end---', contentBody)
            isStreaming.value = false
            currentStreamingMessage.value = null
            flag = false
            break
          }

          buffer += decoder.decode(value, { stream: true })

          // 优先按空行拆分事件块（SSE标准）
          let events = buffer.split(/\n\n/)
          buffer = events.pop() // 保留不完整块

          for (let event of events) {
            if (!event.trim()) continue

            // 过滤掉 id: 等字段，只取 data:
            const dataLines = event
              .split(/\n/)
              .filter((line) => line.startsWith('data:'))
              .map((line) => line.replace(/^data:\s*/, '').trim())

            if (dataLines.length === 0) continue
            const jsonText = dataLines.join('\n')

            try {
              const jsonData = JSON.parse(jsonText)
              if (jsonData.content && jsonData.content.length > 0 && jsonData.type !== 'end') {
                contentBody += jsonData.content
                currentStreamingMessage.value.content = contentBody
              }
            } catch (e) {
              // JSON 不完整：保留到下一次循环
              if (!jsonText.trim().endsWith('}')) {
                buffer = 'data: ' + jsonText // 重新放回缓存
                continue
              } else {
                console.warn('⚠️ JSON 格式错误，跳过:', jsonText)
              }
            }
          }
        }
      } catch (error) {
        console.error('流式传输错误:', error)
        isStreaming.value = false
        currentStreamingMessage.value = null
      } finally {
        reader.releaseLock()
      }
    })
    .catch((error) => {
      console.error('fetch请求失败:', error)
      isStreaming.value = false
      currentStreamingMessage.value = null
    })
}

const handleContinue = () => {
  // router.push('/workshop/selectStyle')
  // 模拟接口之后再跳转
  isLoading.value = true
  generateStore.clearProductData()
  setTimeout(() => {
    router.push('/workshop/selectStyle')
    isLoading.value = false
  }, 1000)
}
</script>
<style lang="less" scoped>
.asistant-container {
  height: 100vh;
  overflow: hidden;
}

.header {
  flex-shrink: 0;
}

.content {
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.footer {
  flex-shrink: 0;

  .continue {
    font-family: 'satoshiRegular';
    font-size: 3.6rem;
    color: #fff;
    text-align: right;
    padding: 2.6rem 4.5rem;
    .btn {
      border-radius: 7px;
      background-color: #000;
      width: 24.6rem;
      height: 5.9rem;
    }
  }
}

.loading-container {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #fff;
}
</style>
