<script setup lang="ts">
import { computed, inject, onMounted, onUnmounted, ref } from 'vue'
import { Emitter } from 'mitt'
import { useI18n } from 'vue-i18n'
import { fetchCustomEventSource } from '@/composables/useEventSource'
import { useUserStore } from '@/store/modules/user'
import { useLayoutConfig } from '@/composables/useLayoutConfig'

interface Props {
  agentId: string
  dialogsId: string
  messageList: ConversationMessageItem[]
  continuousQuestionStatus: 'default' | 'close'
}

const { t } = useI18n()

const props = defineProps<Props>()

const emit = defineEmits<{
  addMessageItem: [value: ConversationMessageItem]
  updateSpecifyMessageItem: [messageItemIndex: number, newObj: Partial<ConversationMessageItem>]
  deleteLastMessageItem: []
  updatePageScroll: []
  clearAllMessage: []
  toLogin: []
  createContinueQuestions: [value: string]
  resetContinueQuestionList: []
}>()

const { isMobile } = useLayoutConfig()

const userStore = useUserStore()

const emitter = inject<Emitter<MittEvents>>('emitter')

const inputMessageContent = ref('')

const isAnswerResponseWait = ref(false)

let controller: AbortController | null = null

const isLogin = computed(() => {
  return userStore.isLogin
})

const isAllowClearMessage = computed(() => {
  return props.messageList.length > 0
})

const isSendBtnDisabled = computed(() => {
  return !inputMessageContent.value.trim()
})

const inputPlaceholder = computed(() => {
  return isLogin.value ? t('common_module.dialogue_module.question_input_placeholder') : ''
})

const isCreateContinueQuestions = computed(() => {
  return props.continuousQuestionStatus === 'default'
})

onMounted(() => {
  emitter?.on('selectQuestion', (featuredQuestion) => {
    if (!isLogin.value) {
      window.$message.warning(t('common_module.not_login_text'))
      return
    }

    inputMessageContent.value = featuredQuestion
    handleMessageSend()
  })
})

onUnmounted(() => {
  blockMessageResponse()
  emitter?.off('selectQuestion')
})

function messageItemFactory() {
  return {
    timestamp: Date.now(),
    role: 'user',
    textContent: '',
    isEmptyContent: false,
    isTextContentLoading: false,
    isAnswerResponseLoading: false,
  } as const
}

function handleEnterKeypress(event: KeyboardEvent) {
  if (event.code === 'Enter' && !event.shiftKey) {
    event.preventDefault()

    if (!inputMessageContent.value.trim() || isAnswerResponseWait.value) return ''

    handleMessageSend()
  }
}

function handleMessageSend() {
  if (!isLogin.value) {
    window.$message.warning(t('common_module.not_login_text'))
    return
  }

  if (!inputMessageContent.value.trim() || isAnswerResponseWait.value) return ''

  emit('resetContinueQuestionList')
  emit('addMessageItem', { ...messageItemFactory(), textContent: inputMessageContent.value })
  emit('updatePageScroll')

  emit('addMessageItem', {
    ...messageItemFactory(),
    role: 'assistant',
    isTextContentLoading: true,
    isAnswerResponseLoading: true,
  })
  emit('updatePageScroll')

  const input = inputMessageContent.value
  const currentMessageIndex = props.messageList.length - 1
  let replyTextContent = ''
  isAnswerResponseWait.value = true
  inputMessageContent.value = ''

  controller = new AbortController()

  fetchCustomEventSource({
    path: '/api/rest/agentApplicationRest/callAgentApplication.json',
    payload: {
      agentId: props.agentId,
      dialogsId: props.dialogsId,
      input,
    },
    controller,
    onMessage: (data: any) => {
      if (data === '[DONE]') {
        emit('updateSpecifyMessageItem', currentMessageIndex, {
          isEmptyContent: !replyTextContent,
          isTextContentLoading: false,
          isAnswerResponseLoading: false,
        })
        isCreateContinueQuestions.value && emit('createContinueQuestions', replyTextContent)
        emit('updatePageScroll')
        blockMessageResponse()
        return
      }

      if (data) {
        replyTextContent += data

        emit('updateSpecifyMessageItem', currentMessageIndex, {
          textContent: replyTextContent,
          isTextContentLoading: false,
        })
        emit('updatePageScroll')
      }
    },
    onRequestError: () => {
      errorMessageResponse()
    },
    onError: () => {
      errorMessageResponse()
    },
    onFinally: () => {
      controller = null
    },
  })
}

function errorMessageResponse() {
  emit('updateSpecifyMessageItem', props.messageList.length - 1, {
    isTextContentLoading: false,
    textContent: '',
  })
  emit('deleteLastMessageItem')
  emit('deleteLastMessageItem')
  blockMessageResponse()
}

function handleClearAllMessage() {
  if (!isAllowClearMessage.value) return

  emit('clearAllMessage')
}

function blockMessageResponse() {
  controller?.abort()
  isAnswerResponseWait.value = false
}

function handleToLogin() {
  emit('toLogin')
}

defineExpose({
  blockMessageResponse,
})
</script>

<template>
  <div class="my-5">
    <div class="flex items-center">
      <div class="mr-2 flex items-center justify-center" :class="isMobile ? 'h-6 w-6' : 'h-8 w-8'">
        <NPopover trigger="hover">
          <template #trigger>
            <i
              class="iconfont icon-clear text-base leading-none"
              :class="
                isAllowClearMessage
                  ? 'hover:text-theme-color cursor-pointer text-[#5c5f66]'
                  : 'cursor-not-allowed text-[#b8babf]'
              "
              @click="handleClearAllMessage"
            />
          </template>
          <span class="text-xs"> {{ t('common_module.dialogue_module.clear_message_popover_message') }}</span>
        </NPopover>
      </div>

      <div class="relative flex-1">
        <NInput
          v-model:value="inputMessageContent"
          :placeholder="inputPlaceholder"
          :disabled="!isLogin"
          class="rounded-xl! shadow-[0_1px_#09122105,0_1px_1px_#09122105,0_3px_3px_#09122103,0_9px_9px_#09122103]! py-[4px] pr-[50px]"
          @keypress="handleEnterKeypress"
        />
        <div
          class="bg-px-send-png absolute bottom-2 right-[20px] h-[24px] w-[24px]"
          :class="isSendBtnDisabled || isAnswerResponseWait || !isLogin ? 'opacity-60' : 'cursor-pointer'"
          @click="handleMessageSend"
        />

        <div v-show="!isLogin" class="absolute left-3 top-[5px] flex h-[30px] items-center text-[#84868c]">
          {{ t('share_agent_module.please') }}
          <span class="text-theme-color cursor-pointer px-1 hover:opacity-80" @click="handleToLogin">
            {{ t('common_module.login') }}
          </span>
          {{ t('share_agent_module.after_action') }}
        </div>
      </div>
    </div>

    <div class="mt-[9px]">
      <span class="flex w-full justify-center text-xs text-[#b8babf]">
        {{ t('common_module.dialogue_module.generate_warning_message') }}
      </span>
    </div>
  </div>
</template>
