<script setup lang="ts">
import { computed, ref, useTemplateRef } from 'vue'
import { useI18n } from 'vue-i18n'
import { throttle } from 'lodash-es'
import { CheckOne, Down } from '@icon-park/vue-next'
import CustomLoading from './custom-loading.vue'
import { usePersonalAppConfigStore } from '@/store/modules/personal-app-config'
import MarkdownRender from '@/components/markdown-render/markdown-render.vue'
import { useUserStore } from '@/store/modules/user'
import { asBlob } from 'html-docx-js-typescript'
import { downloadFile } from '@/utils/download-file'
import { copyToClip } from '@/utils/copy'

interface Props {
  role: 'user' | 'assistant'
  messageItem: ConversationMessageItem
}

const props = defineProps<Props>()

const emit = defineEmits<{
  audioPlay: []
  audioPause: []
}>()

const { t } = useI18n()

const userStore = useUserStore()
const personalAppConfigStore = usePersonalAppConfigStore()

const markdownRenderRef = useTemplateRef<InstanceType<typeof MarkdownRender>>('markdownRenderRef')

const isShowReasoningContent = ref(true)

const useAvatar = computed(() => {
  return userStore.userInfo.avatarUrl || 'https://gsst-poe-sit.gz.bcebos.com/data/20240910/1725952917468.png'
})

const assistantAvatar = computed(() => {
  return personalAppConfigStore.baseInfo.agentAvatar
})

const isShowAudioControl = computed(() => {
  return props.role === 'assistant' && !props.messageItem.isVoiceLoading
})

const isPlayableAudio = computed(() => {
  return isShowAudioControl.value && !!props.messageItem.voiceFragmentUrlList.length
})

const isShowVoiceLoading = computed(() => {
  return props.role === 'assistant' && props.messageItem.isVoiceLoading && props.messageItem.isVoiceEnabled
})

const isDeepSeekR1 = computed(() => {
  return personalAppConfigStore.commModelConfig.largeModel === 'DeepSeek'
})

function handleAudioControl() {
  if (!isPlayableAudio.value) {
    return
  }

  if (props.messageItem.isVoicePlaying) {
    emit('audioPause')
  } else {
    emit('audioPlay')
  }
}

function handleShowReasoningContentSwitch() {
  isShowReasoningContent.value = !isShowReasoningContent.value
}

const handleContentDownload = throttle(
  () => {
    if (markdownRenderRef.value) {
      const content = markdownRenderRef.value.getRenderTextContent()

      asBlob(content).then((data) => {
        downloadFile(data as Blob).then(() => {
          window.$message.success(t('common_module.copy_success_message'))
        })
      })
    }
  },
  1000,
  { leading: true, trailing: false },
)

const handleContentCopy = throttle(
  () => {
    copyToClip(props.messageItem.textContent).then(() => {
      window.$message.success(t('common_module.copy_success_message'))
    })
  },
  1000,
  { leading: true, trailing: false },
)
</script>

<template>
  <div class="mb-5 flex last:mb-0">
    <NImage
      :src="role === 'user' ? useAvatar : assistantAvatar"
      preview-disabled
      :width="32"
      :height="32"
      object-fit="cover"
      class="mr-2 mt-1.5 h-8 w-8 flex-shrink-0 rounded-full"
    />

    <div class="flex flex-col items-start overflow-x-auto">
      <template v-if="role === 'assistant' && isDeepSeekR1">
        <div class="my-[7px] select-none text-[14px]">
          <div class="inline-flex cursor-pointer" @click="handleShowReasoningContentSwitch">
            <span v-if="messageItem.isTextContentLoading" class="mr-[6px]">
              {{ t('common_module.deep_thinking', { modelName: personalAppConfigStore.commModelConfig.largeModel }) }}
            </span>
            <span v-else class="mr-[6px]">
              {{ t('common_module.have_thought_deeply') }}
            </span>
            <Down
              theme="outline"
              size="21"
              fill="#333"
              :stroke-width="3"
              class="transition-[rotate] duration-100 ease-linear"
              :class="{ '-rotate-180': isShowReasoningContent }"
            />
          </div>
        </div>

        <n-collapse-transition :show="isShowReasoningContent">
          <div class="my-[14px] border-l-[1px] border-solid border-l-[#ccc] p-[13px]">
            <div>
              <img
                v-if="!messageItem.reasoningContent && !messageItem.textContent"
                src="@/assets/images/home/bubble-loading.gif"
                alt="bubble-loading"
              />
              <template v-else>
                <MarkdownRender
                  ref="markdownRenderRef"
                  :raw-text-content="
                    messageItem.reasoningContent
                      ? messageItem.reasoningContent
                      : t('common_module.dialogue_module.empty_message_content')
                  "
                  color="#999"
                />
              </template>
            </div>
          </div>
        </n-collapse-transition>
      </template>

      <div
        class="min-w-[80px] max-w-full flex-wrap rounded-xl border border-[#e8e9eb] px-4 py-[11px]"
        :class="role === 'user' ? 'bg-[#4b87ff] text-white' : 'bg-white text-[#333]'"
      >
        <img
          v-show="role === 'user' && messageItem.imageUrl"
          :src="messageItem.imageUrl"
          class="max-h-[120px]! mb-[11px] rounded-[10px] object-contain"
        />

        <div
          v-show="role === 'assistant' && messageItem.pluginName"
          class="mb-[8px] flex items-center gap-[5px] font-['Microsoft_YaHei_UI'] text-[#999]"
        >
          <div
            v-show="messageItem.isTextContentLoading"
            class="bg-px-plugin_loading-gif h-[14px] w-[14px] bg-contain bg-center bg-no-repeat"
          />
          <CheckOne v-show="!messageItem.isTextContentLoading" theme="outline" size="16" fill="#40bd23" />

          <span class="leading-5">
            {{
              messageItem.isTextContentLoading
                ? t('common_module.plugin_in_progress', { pluginName: messageItem.pluginName })
                : t('common_module.plugin_executed_successfully', { pluginName: messageItem.pluginName })
            }}
          </span>
        </div>

        <div v-if="messageItem.isTextContentLoading" class="py-1.5 pl-4">
          <CustomLoading />
        </div>

        <div v-else>
          <p class="break-all">
            <MarkdownRender
              ref="markdownRenderRef"
              :raw-text-content="
                messageItem.isEmptyContent
                  ? t('common_module.dialogue_module.empty_message_content')
                  : messageItem.textContent
              "
              :color="role === 'user' ? '#fff' : '#192338'"
            />
          </p>

          <div v-show="role === 'assistant' && messageItem.isAnswerResponseLoading" class="mb-[5px] mt-4 px-4">
            <CustomLoading />
          </div>
        </div>
      </div>

      <div class="flex w-full items-center justify-between">
        <div>
          <div
            v-show="isShowAudioControl"
            class="text-font-color flex items-center gap-0.5"
            :class="isPlayableAudio ? 'hover:text-theme-color cursor-pointer hover:opacity-80' : 'cursor-not-allowed'"
            @click="handleAudioControl"
          >
            <i v-if="!messageItem.isVoicePlaying" class="iconfont icon-play text-[24px]" />
            <div
              v-else
              class="mx-1.5 my-3 h-[12px] w-[12px] bg-[url(@/assets/images/playing.gif)] bg-[length:100%_100%]"
            />

            <span
              v-show="isPlayableAudio"
              class="text-[12px]"
              :class="messageItem.isVoicePlaying ? 'text-theme-color' : ''"
            >
              {{ messageItem.isVoicePlaying ? t('common_module.stop_playing') : t('common_module.start_playing') }}
            </span>
            <n-popover style="max-width: 310px">
              <template #trigger>
                <span v-show="!isPlayableAudio" class="text-[12px]"> {{ t('common_module.unplayable') }} </span>
              </template>
              {{ t('common_module.unplayable_tip') }}
            </n-popover>
          </div>

          <div v-if="isShowVoiceLoading" class="py-3.5 pl-6">
            <CustomLoading />
          </div>
        </div>

        <div
          v-show="role === 'assistant' && messageItem.textContent && !messageItem.isAnswerResponseLoading"
          class="py-[10px] pr-[14px] text-end"
        >
          <i
            class="iconfont icon-download hover:text-theme-color mr-[14px] transform cursor-pointer text-[14px]"
            @click="handleContentDownload"
          />
          <i
            class="iconfont icon-copy1 hover:text-theme-color transform cursor-pointer text-[14px]"
            @click="handleContentCopy"
          />
        </div>
      </div>
    </div>
  </div>
</template>
