<script setup lang="ts">
import { computed, nextTick, ref, toValue } from 'vue'
import type { AgentApplicationRecordItem, MessageItemInterface } from '../types'
import { fetchAgentApplicationSelectList } from '@/apis/home-agent'
import { nanoid } from 'nanoid'
import fetchEventStreamSource from '../utils/fetch-event-stream-source'
import { throttle } from 'lodash-es'
import { useI18n } from 'vue-i18n'

interface Props {
  currentSessionId: string
  messageListLength: number
}

const props = defineProps<Props>()
const emit = defineEmits<{
  messageListScrollToBottom: []
  addMessageItem: [messageId: string, messageItem: MessageItemInterface]
  updateSpecifyMessageItem: [messageId: string, newMessageItem: Partial<MessageItemInterface>]
  deleteMessageItem: [messageId: string]
  createNewSession: []
  historyRecordListUpdate: []
}>()

const questionContent = defineModel<string>('questionContent', { required: true })
const currentAgentApplication = defineModel<AgentApplicationRecordItem>('currentAgentApplication', { required: true })
const isAgentResponding = defineModel<boolean>('isAgentResponding', { required: true })
const currentFetchEventSourceController = defineModel<AbortController | null>('currentFetchEventSourceController', {
  required: true,
})

const { t } = useI18n()

const isShowApplicationSelectMenu = ref(false)
const agentApplicationSelectList = ref<AgentApplicationRecordItem[]>([])

const currentLatestMessageItemKeyMap = ref(new Map<'assistant' | 'user', string>())

const isQuestionSubmitBtnDisabled = computed(() => {
  return questionContent.value.trim().length === 0 || isAgentResponding.value
})

;(function () {
  getAgentApplicationSelectList()
})()

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

function getAgentApplicationSelectList() {
  fetchAgentApplicationSelectList<AgentApplicationRecordItem[]>().then((res) => {
    agentApplicationSelectList.value = res.data

    currentAgentApplication.value = res.data[0]
  })
}

function handleApplicationSelectMenuSwitchShow() {
  isShowApplicationSelectMenu.value = !isShowApplicationSelectMenu.value
}

function handleApplicationSelectBtnBlur() {
  setTimeout(() => {
    isShowApplicationSelectMenu.value = false
  }, 100)
}

function handleApplicationChange(agentApplicationItem: AgentApplicationRecordItem) {
  if (currentAgentApplication.value.agentId === agentApplicationItem.agentId) {
    return
  }

  currentAgentApplication.value = toValue(agentApplicationItem)
}

function handleCreateNewSession() {
  if (isAgentResponding.value) {
    window.$message.ctWarning(t('home_module.interrupt_dialogue_prompt')).then(() => {
      currentFetchEventSourceController.value && currentFetchEventSourceController.value.abort()

      isAgentResponding.value = false

      emit('createNewSession')

      /* 延时，避免页面刷新后，历史记录列表未刷新 */
      setTimeout(() => {
        emit('historyRecordListUpdate')
      }, 300)
    })
  } else {
    if (props.messageListLength === 0) {
      window.$message.warning(t('home_module.currently_in_the_latest_session'))

      return
    }

    emit('createNewSession')
  }
}

function questionSubmit() {
  const latestUserMessageKey = nanoid()
  const latestAssistantMessageKey = nanoid()

  currentLatestMessageItemKeyMap.value.set('user', latestUserMessageKey)
  currentLatestMessageItemKeyMap.value.set('assistant', latestAssistantMessageKey)

  emit('addMessageItem', latestUserMessageKey, {
    role: 'user',
    agentId: '',
    content: questionContent.value.trim(),
    timestamp: Date.now(),
    isAnswerLoading: false,
    avatar: '',
    name: '',
  })

  const agentAvatar = currentAgentApplication.value.agentAvatar
  const agentName = currentAgentApplication.value.agentTitle

  nextTick(() => {
    emit('addMessageItem', latestAssistantMessageKey, {
      role: 'assistant',
      agentId: '',
      content: '',
      timestamp: Date.now(),
      isAnswerLoading: true,
      avatar: agentAvatar,
      name: agentName,
    })

    emit('messageListScrollToBottom')
  })

  isAgentResponding.value = true

  let isFirstClip = true
  let messageContent = ''

  currentFetchEventSourceController.value = fetchEventStreamSource(
    '/agentApplicationRest/callAgentApplication.json',
    {
      dialogsId: props.currentSessionId, //会话ID
      agentId: currentAgentApplication.value.agentId, //应用ID
      input: questionContent.value.trim(), //提问文本
    },
    {
      onmessage: (message) => {
        messageContent += message

        if (isFirstClip) {
          emit('updateSpecifyMessageItem', currentLatestMessageItemKeyMap.value.get('assistant')!, {
            content: message,
            isAnswerLoading: false,
          })

          isFirstClip = false
        } else {
          emit('updateSpecifyMessageItem', currentLatestMessageItemKeyMap.value.get('assistant')!, {
            content: messageContent,
          })
        }

        messageListScrollToBottomThrottle()
      },
      onend: () => {},
      onclose: () => {
        isAgentResponding.value = false

        nextTick(() => {
          emit('historyRecordListUpdate')
        })
      },
      onerror: () => {
        emit('deleteMessageItem', currentLatestMessageItemKeyMap.value.get('assistant')!)
      },
    },
  )

  questionContent.value = ''
}

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

    if (questionContent.value.trim().length > 0) {
      questionSubmit()
    }
  }
}
</script>

<template>
  <div class="mt-auto pr-[10px]">
    <div class="mb-[10px] flex select-none justify-between">
      <!-- <div
        class="relative box-border flex h-[34px] w-[145px] cursor-pointer items-center rounded-[10px] border border-[#9EA3FF] px-[12px]"
      >
        <div class="flex w-full items-center justify-between">
          <div class="flex items-center">
            <div class="bg-px-home-cuixiang_icon-png mr-[5px] h-[16px] w-[16px]"></div>
            <div class="text-[14px]">萃想AI</div>
          </div>

          <Up theme="outline" size="18" fill="#333" :stroke-width="3" />
        </div>

        <div
          class="absolute -top-[10px] left-1/2 w-[200px] -translate-x-1/2 -translate-y-full rounded-[10px] bg-[#fff] p-[6px] shadow-md"
        >
          hello
        </div>
      </div> -->

      <div class="relative">
        <n-button
          class="application-select-btn !h-[34px] !rounded-[10px] !p-0"
          @click="handleApplicationSelectMenuSwitchShow"
          @blur="handleApplicationSelectBtnBlur"
        >
          <div class="box-border flex !w-[160px] w-full items-center justify-between px-[12px]">
            <div class="mr-[5px] flex flex-1 items-center overflow-hidden">
              <div
                class="mr-[10px] h-[16px] w-[16px] rounded-full bg-cover"
                :class="{ 'bg-px-home-cuixiang_icon-png': !currentAgentApplication.agentAvatar }"
                :style="{ backgroundImage: `url(${currentAgentApplication.agentAvatar})` }"
              ></div>
              <div class="flex-1 truncate text-start text-[14px]">{{ currentAgentApplication.agentTitle || '-' }}</div>
            </div>

            <i
              class="iconfont icon-left rotate-90 text-[12px] transition-[rotate] duration-300 ease-in-out"
              :class="{ '!rotate-270': isShowApplicationSelectMenu }"
            ></i>
          </div>
        </n-button>

        <Transition name="application-select-menu">
          <ul
            v-show="isShowApplicationSelectMenu"
            class="absolute -top-[10px] left-1/2 w-[200px] -translate-x-1/2 -translate-y-full rounded-[6px] bg-[#fff] p-[10px] pb-[4px] pr-0 shadow-md"
          >
            <n-virtual-list
              style="max-height: 200px"
              :item-size="35"
              :items="agentApplicationSelectList"
              key-field="agentId"
              items-style="padding-right: 10px;"
            >
              <template #default="{ item }">
                <li
                  class="relative mb-[6px] flex cursor-pointer items-center overflow-hidden rounded-[4px] bg-[#f3f3f5] px-[10px] py-[4px] transition hover:bg-[#E7E7E7]"
                  @click="handleApplicationChange(item)"
                >
                  <div
                    class="mr-[10px] h-[16px] w-[16px] rounded-full bg-cover"
                    :class="{ 'bg-px-home-cuixiang_icon-png': !item.agentAvatar }"
                    :style="{ backgroundImage: `url(${item.agentAvatar})` }"
                  ></div>
                  <div class="flex-1 truncate">{{ item.agentTitle }}</div>

                  <i
                    v-if="item.agentId === currentAgentApplication.agentId"
                    class="iconfont icon-xuanze absolute bottom-0 right-0 text-[14px] text-[#777ef9]"
                  ></i>
                </li>
              </template>
            </n-virtual-list>
          </ul>
        </Transition>
      </div>

      <n-button class="application-select-btn !h-[34px] !rounded-[10px] !p-0" @click="handleCreateNewSession">
        <div class="box-border flex w-full items-center justify-between px-[12px]">
          <i class="iconfont icon-session mr-[5px] text-[14px]"></i>
          <span class="text-[14px]">{{ t('home_module.starting_a_new_session') }}</span>
        </div>
      </n-button>
    </div>

    <div>
      <n-input
        v-model:value.trim="questionContent"
        class="content-input"
        type="textarea"
        :autosize="{ minRows: 5, maxRows: 5 }"
        :placeholder="t('home_module.please_enter_a_question')"
        @keydown="handleQuestionSubmitEnter"
      >
        <template #suffix>
          <div class="flex h-full items-end pb-[10px]">
            <n-button type="primary" :disabled="isQuestionSubmitBtnDisabled" @click="() => questionSubmit()">
              <i class="iconfont icon-send-icon"></i>
            </n-button>
          </div>
        </template>
      </n-input>
    </div>

    <div class="mt-[20px] text-center text-[13px] text-[#999]">
      {{ t('home_module.all_of_the_above_content_is_generated_by_ai_and_is_for_reference_only') }}
    </div>
  </div>
</template>

<style lang="scss" scoped>
.content-input {
  :deep(.n-input__border) {
    border-color: #9ea3ff;
  }
}

:deep(.application-select-btn) {
  .n-button__border {
    border-color: #9ea3ff;
  }
}

.application-select-menu-enter-active,
.application-select-menu-leave-active {
  transition-timing-function: ease-in-out;
  transition-duration: 0.2s;
  transition-property: opacity, scale;
  transform-origin: left center;
}

.application-select-menu-enter-from,
.application-select-menu-leave-to {
  opacity: 0;
  scale: 0.8;
}
</style>
