<script setup lang="ts">
import { computed, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { nanoid } from 'nanoid'
import { throttle } from 'lodash-es'
import CMessage from './c-message'
import { MessageItemInterface, MultiModelDialogueItem, QuestionMessageItem } from '../types'
import { fetchEventStreamSource } from '../utils/fetch-event-stream-source'

const { t } = useI18n()

interface Props {
  agentId: string
  isAnswerResponseWait: boolean
}

const props = defineProps<Props>()

const emit = defineEmits<{
  addQuestionMessageItem: [messageId: string, messageItem: MessageItemInterface]
  addAnswerMessageItem: [messageId: string, messageItem: MessageItemInterface, index: number]
  updateMessageItem: [messageId: string, messageItem: Partial<MessageItemInterface>, index: number]
  deleteMessageItem: [messageId: string, index: number]
  messageListScrollToBottom: []
  clearAllMessage: []
}>()

const multiModelDialogueList = defineModel<MultiModelDialogueItem[]>('multiModelDialogueList', { required: true })

const questionContent = ref('')

const isQuestionSubmitDisabled = computed(() => {
  return questionContent.value.trim().length === 0
})

const isAllSelectedModelName = computed(() => {
  return multiModelDialogueList.value.every((modelItem) => modelItem.modelNickName)
})

const isAllowClearAllMessage = computed(() => {
  return multiModelDialogueList.value.some((modelItem) => modelItem.messageList.size > 0)
})

const messageListScrollToBottomThrottle = throttle(() => {
  emit('messageListScrollToBottom')
}, 1000)

function handleClearAllMessage() {
  isAllowClearAllMessage.value && emit('clearAllMessage')
}

function messageItemFactory() {
  return {
    role: 'user',
    avatar: '',
    nickName: '',
    content: '',
    timestamp: Date.now(),
    isTextContentLoading: false,
    isAnswerResponseLoading: false,
  } as MessageItemInterface
}

function handleQuestionSubmit() {
  if (isQuestionSubmitDisabled.value || props.isAnswerResponseWait) return

  if (!isAllSelectedModelName.value) {
    window.$message.warning(t('multi_model_dialogue_module.please_select_model_first'))
    return
  }

  const questionMessageId = nanoid()

  emit('addQuestionMessageItem', questionMessageId, { ...messageItemFactory(), content: questionContent.value })

  emit('messageListScrollToBottom')

  multiModelDialogueList.value.forEach((modelItem, modelIndex) => {
    const messages: QuestionMessageItem[] = []

    const { topP, temperature, agentSystem, modelNickName } = modelItem

    modelItem.messageList.forEach((messageItem) => {
      messages.push({
        content: [
          {
            type: 'text',
            text: messageItem.content,
            image_url: {
              url: '',
            },
          },
        ],
        role: messageItem.role,
      })
    })

    questionContent.value = ''
    modelItem.isAnswerResponseWait = true

    const answerMessageId = nanoid()
    let messageContent = ''
    let isFirstClip = true

    emit(
      'addAnswerMessageItem',
      answerMessageId,
      { ...messageItemFactory(), role: 'assistant', isTextContentLoading: true, isAnswerResponseLoading: true },
      modelIndex,
    )
    emit('messageListScrollToBottom')

    modelItem.controller = new AbortController()

    fetchEventStreamSource({
      path: '/api/rest/agentApplicationInfoRest/preview.json',
      payload: {
        agentId: props.agentId,
        messages,
        topP,
        temperature,
        agentSystem,
        modelNickName,
      },
      controller: modelItem.controller,
      onMessage: (data: any) => {
        if (data === '[DONE]') {
          emit('updateMessageItem', answerMessageId, { isAnswerResponseLoading: false }, modelIndex)
          emit('messageListScrollToBottom')
          modelItem.isAnswerResponseWait = false
          return
        }

        if (data) {
          messageContent += data

          if (isFirstClip) {
            emit(
              'updateMessageItem',
              answerMessageId,
              { content: messageContent, isTextContentLoading: false },
              modelIndex,
            )
            isFirstClip = false
          } else {
            emit('updateMessageItem', answerMessageId, { content: messageContent }, modelIndex)
          }

          messageListScrollToBottomThrottle()
        }
      },
      onRequestError: () => {
        errorMessageResponse(questionMessageId, answerMessageId, modelIndex)
      },
      onError: (err: any) => {
        CMessage.error(err.message || '', { to: `#${modelItem.id}` })
      },
      onFinally: () => {
        modelItem.controller = null
        modelItem.isAnswerResponseWait = false
      },
    })
  })
}

function errorMessageResponse(questionMessageId: string, answerMessageId: string, modelIndex: number) {
  emit('deleteMessageItem', questionMessageId, modelIndex)
  emit('deleteMessageItem', answerMessageId, modelIndex)
}
</script>

<template>
  <footer class="flex flex-col items-center">
    <div class="mb-4 flex items-center gap-[18px]">
      <NPopover trigger="hover">
        <template #trigger>
          <div
            class="border-inactive-border-color flex h-[54px] w-[54px] shrink-0 items-center justify-center rounded-full border bg-white"
            :class="
              isAllowClearAllMessage
                ? 'text-font-color hover:text-theme-color cursor-pointer'
                : 'text-gray-font-color cursor-not-allowed'
            "
            @click="handleClearAllMessage"
          >
            <i class="iconfont icon-clear text-xl leading-none" />
          </div>
        </template>
        <span class="text-xs"> {{ t('common_module.dialogue_module.clear_message_popover_message') }}</span>
      </NPopover>

      <div class="relative">
        <NInput
          v-model:value="questionContent"
          :placeholder="t('common_module.dialogue_module.question_input_placeholder')"
          class="rounded-[26px]! w-[725px]! border-[#9EA3FF]! border py-[10px] pl-3 pr-[44px]"
          @keydown.enter="handleQuestionSubmit"
        />
        <i
          class="iconfont icon-send-icon absolute right-6 top-[18px] text-xl leading-none"
          :class="
            isQuestionSubmitDisabled || isAnswerResponseWait
              ? 'text-hover-theme-color cursor-not-allowed'
              : 'text-theme-color cursor-pointer hover:opacity-80'
          "
          @click="handleQuestionSubmit"
        />
      </div>
    </div>
    <span class="text-gray-font-color select-none">
      {{ t('common_module.dialogue_module.generate_warning_message') }}
    </span>
  </footer>
</template>
