<template>
  <LayoutContent>
    <div class="flex flex-col w-full h-full">
      <ScrollContainer id="scrollRef" ref="scrollRef">
        <div class="p-4">
          <MessageGroup
            v-for="(item, i) in dataSources"
            :key="i"
            :arr="item"
          ></MessageGroup>
        </div>
      </ScrollContainer>
      <div class="p-2">
        <div class="border border-[#414548]">
          <div class="border-b border-[#414548] h-9 flex items-center px-5">
            <SvgIcon
              @click="handleRefresh"
              name="refresh"
              class="text-white text-base cursor-pointer mr-6"
            ></SvgIcon>
            <SvgIcon
              @click="handleStop"
              name="stop"
              class="text-white text-base cursor-pointer mr-6"
            ></SvgIcon>
          </div>
          <a-textarea
            ref="inputRef"
            class="bg-transparent border-none rounded-none text-white minp focus:shadow-none placeholder-[#FFFFFF40]"
            placeholder="请输入内容"
            :rows="4"
            v-model:value="inputValue"
            @pressEnter="handleEnter"
          />
          <div class="flex pb-5 px-5 pt-4 justify-between">
            <div class="flex items-end">
              <a-button
                @click="handleClear"
                type="primary"
                class="rounded-4px h-9.5 px-6 !bg-[#414548] mr-2.5 border-[#414548] text-white"
              >
                <template #icon>
                  <SvgIcon name="delete" class="text-lg mr-2" />
                </template>
                清除</a-button
              >
              <a-button type="primary" class="rounded-4px h-9.5 px-6">
                <template #icon>
                  <SvgIcon name="cloud-upload" class="text-lg mr-2" />
                </template>
                上传</a-button
              >
              <div class="ml-2">
                <span class="text-[#EC4B4B] text-base">*</span>
                <span class="opacity-40 text-xs">
                  可支持的格式：.doc、.docx、.pdf（小于20M）
                </span>
              </div>
            </div>
            <div>
              <a-button
                @click="handleSubmit"
                type="primary"
                class="rounded-4px h-9.5 px-6"
              >
                <template #icon>
                  <SvgIcon name="generated" class="text-sm mr-2" />
                </template>
                生成</a-button
              >
            </div>
          </div>
        </div>
      </div>
    </div>
  </LayoutContent>
</template>
<script setup>
import { Layout } from 'ant-design-vue'
import MessageGroup from './message-group.vue'
import { ref, computed, onMounted, nextTick, onBeforeMount,getCurrentInstance } from 'vue'
import ScrollContainer from '@/components/ScrollContainer/index.vue'
import http from '@/io/request'
import { v4 as uuidv4 } from 'uuid'
import { useRoute } from 'vue-router'
import { useChat } from '@/stores'



const { proxy } = getCurrentInstance();

let controller = new AbortController()

const inputRef = ref(null)

const LayoutContent = Layout.Content

const route = useRoute()

const { uuid } = route.params

const chatStore = useChat()

const scrollRef = ref(null)

const loading = ref(false)

const inputValue = ref('')

const currentChart = computed(() => chatStore.getCurrentChat)

const conversationList = computed(() => {
  return chatStore.getCurrentChat.filter((item) => {
    const key = Object.keys(item)[0]
    const value = item[key]
    return !value.inversion
  })
})

const conversationUserList = computed(() => {
  return chatStore.getCurrentChat.filter((item) => {
    const key = Object.keys(item)[0]
    const value = item[key]
    return value.inversion
  })
})

const dataSources = computed(() => {
  const arr = chatStore.getCurrentChat
  return groupDataByParentId(arr)
})

function groupDataByParentId(data) {
  return data.reduce((groupedData, item) => {
    const itemId = Object.keys(item)[0]
    const itemData = item[itemId]

    if (itemData.parent_id === '') {
      groupedData[itemId] = []
    } else {
      const parentItemId = itemData.parent_id
      groupedData[parentItemId] = groupedData[parentItemId] || []
      groupedData[parentItemId].push(itemData)
    }

    return groupedData
  }, {})
}

function handleRefresh() {
  if (currentChart.value.length && !loading.value) onConversation('variant')
}

function handleStop() {
  if (loading.value) {
    controller.abort()
    loading.value = false
  }
}

function handleClear() {
  inputValue.value = ''
}

function handleSubmit() {
  onConversation()
}

async function onConversation(action = 'next') {
  let message = inputValue.value
  if (loading.value) return
  if ((!message || message.trim() === '') && action == 'next') return
  controller = new AbortController()
  const params = {
    action: action,
    conversation_id: chatStore.active,
    message: {
      text: message,
      id: uuidv4(),
    },
  }
  if (action == 'next') {
    const lastContext =
      conversationList.value[conversationList.value.length - 1]
    params.parent_message_id = uuidv4()
    if (lastContext) {
      params.parent_message_id = lastContext[Object.keys(lastContext)[0]]?.id
    }

    chatStore.addChatByUuid(chatStore.active, {
      text: message,
      inversion: true,
      parent_id: params.parent_message_id || '',
      id: params.message.id,
    })
    scrollToBottom()
    chatStore.addChatByUuid(chatStore.active, {
      text: '⋯',
      id: uuidv4(),
      parent_id: params.message.id,
      inversion: false,
    })
  }
  if (action == 'variant') {
    const lastUserContext =
      conversationUserList.value[conversationUserList.value.length - 1]
    if (lastUserContext) {
      const obj = lastUserContext[Object.keys(lastUserContext)[0]]
      params.message.text = obj.text
      params.message.id = obj.id
      params.parent_message_id = obj.id
    }

    chatStore.addChatByUuid(chatStore.active, {
      text: '⋯',
      id: uuidv4(),
      parent_id: params.parent_message_id,
      inversion: false,
    })
  }

  loading.value = true
  inputValue.value = ''

  scrollToBottom()
  let tempMessage_id = null
  try {
    const fetchChatAPIOnce = async () => {
      await http.post('/api/v1/conversation', params, {
        signal: controller.signal,
        requestBaseUrl: 'chat',
        onDownloadProgress: async ({ event }) => {
          const xhr = event.target
          const { responseText } = xhr
          if (xhr.status == 200) {
            const arr = parseEventMessages(responseText)
            const { conversation_id, message_id } = arr[0]
            tempMessage_id = message_id
            const msg = arr.reduce((acc, item) => {
              return acc + item.text
            }, '')
            chatStore.updateChatByUuid(
              conversation_id,
              chatStore.getCurrentChat.length - 1,
              {
                [message_id]: {
                  conversation_id: conversation_id,
                  id: message_id,
                  text: msg,
                  inversion: false,
                  loading: true,
                  parent_id: params.message.id || '',
                },
              }
            )
            scrollToBottomIfAtBottom()
          }
        },
      })

      chatStore.updateChatSome(chatStore.getCurrentChat.length - 1, {
        loading: false,
      })
      await chatStore.getChat(chatStore.active)
    }

    await fetchChatAPIOnce()
  } catch (error) {
    if (error.message === 'canceled') {
      chatStore.updateChatSome(chatStore.getCurrentChat.length - 1, {
        loading: false,
      })
      return
    }
    const errorMessage = error?.errmsg ?? '好像出错了，请稍后再试。'

    chatStore.updateChatSome(chatStore.getCurrentChat.length - 1, {
      loading: false,
      text: errorMessage,
    })
  } finally {
    loading.value = false
  }
}

function parseEventMessages(dataString) {
  const lines = dataString.trim().split('\n')
  const eventMessages = []
  let currentEvent = {}

  for (const line of lines) {
    if (line.startsWith('event:message')) {
      if (Object.keys(currentEvent).length > 0) {
        eventMessages.push(currentEvent)
        currentEvent = {}
      }
    } else if (line.startsWith('data:')) {
      const jsonData = line.substring('data:'.length)
      currentEvent = JSON.parse(jsonData)
    }
  }

  if (Object.keys(currentEvent).length > 0) {
    eventMessages.push(currentEvent)
  }

  return eventMessages
}

function handleEnter(event) {
  if (event.key === 'Enter' && !event.shiftKey) {
    event.preventDefault()
    handleSubmit()
  }
}

function handleDataChange(data) {
  inputValue.value = data
}

onMounted(async () => {
  proxy.$mitt.on('temp-copy', handleDataChange)
  if (inputRef.value) {
    inputRef.value.focus()
  }
  await chatStore.getChat(uuid)
  scrollToBottom()
})

function scrollToBottom() {
  nextTick()
  scrollRef.value.scrollBottom()
}

function scrollToBottomIfAtBottom() {
  nextTick()
  scrollRef.value.scrollToBottomIfAtBottom()
}
</script>
<style lang="scss" scoped>
.scroll-smooth {
  scroll-behavior: smooth;
}
</style>
