<script setup lang="ts">
import { computed, nextTick, onMounted, ref, watch } from 'vue'
import { Image } from 'ant-design-vue'
import { MdPreview } from 'md-editor-v3'
import 'md-editor-v3/lib/style.css'
import type { MessageItem } from './index.d'
import { SvgIcon } from '@/components/SvgIcon'
import { MessageStatusEnum, MessageTypeEnum } from '@/enums/messageEnum'
import { MenuTypeEnum } from '@/enums/menuEnum'
import { copyText } from '@/utils/copyTextToClipboard'
import { useMessageStore } from '@/store/moules/messageStore/index'

const props = defineProps({
  elIndex: {
    type: Number,
    default: 0,
  },
  height: {
    type: String,
    default: 'calc(100% - 120px)',
  },
  list: {
    type: Array as PropType<MessageItem[]>,
    default: () => [],
  },
  aiWidthType: {
    type: String as PropType<'auto' | 'full'>,
    default: 'full',
  },
})

const emit = defineEmits(['onScrollTop', 'reloadMessage'])

defineExpose({ seamlessScrollToTop, getElementOffsetTop })

const messageStore = useMessageStore()

const messageRef = ref<any>(null)
const filstDivTop = ref(0)

const defaultScrollTop = ref(0) // 默认滚动距离
const isAutoScroll = ref(true) // 是否自动滚动
const conversationData = computed(() => messageStore.getConversationData)

watch(
  () => props.list[props.list.length - 1],
  () => {
    if (isAutoScroll.value) {
      scrollToBottom()
    }
  },
  { immediate: true },
)

/**
 * @description: 滚动到底部
 */
async function scrollToBottom() {
  if (!messageRef.value) {
    return
  }
  await nextTick()
  if (messageRef.value) {
    defaultScrollTop.value = messageRef.value.scrollTop
    messageRef.value.scrollTo(0, messageRef.value.scrollHeight)
  }
}

/**
 * @description: 监听滚动
 */
function onScroll() {
  if (!messageRef.value) {
    return
  }

  // 滚动距离 - 默认距离 > -1px，停止自动滚动
  if (messageRef.value.scrollTop - defaultScrollTop.value > -1) {
    isAutoScroll.value = true
  }
  else {
    isAutoScroll.value = false
  }
  emit('onScrollTop', messageRef.value.scrollTop)
}

/**
 * @description: 上滑加载无缝滚动
 */
async function seamlessScrollToTop() {
  if (!messageRef.value) {
    return
  }
  messageRef.value.scrollTo(0, filstDivTop.value)
}

/**
 * @description: 获取某个元素的滚动条位置
 */
async function getElementOffsetTop() {
  if (messageRef.value) {
    filstDivTop.value = messageRef.value.children[props.elIndex].offsetTop
  }
}

/**
 * @description: 重新回答
 */
function reloadMessage() {
  emit('reloadMessage')
}

onMounted(async () => {
  scrollToBottom()
})
</script>

<template>
  <div ref="messageRef" class="app-message" @scroll="onScroll">
    <div v-for="(item, index) in list" :key="item.time + index" class="item">
      <div v-if="item.messageType === MessageTypeEnum.USER" class="user">
        <div class="content">
          <MdPreview
            :editor-id="`preview-only-ai${index}`"
            :model-value="item.content"
          />
        </div>
        <img class="icon-user" src="@/assets/images/conversation/user.png" alt="">
      </div>
      <div
        v-if="item.messageType === MessageTypeEnum.AI || item.messageType === MessageTypeEnum.DESCRIBE"
        class="ai"
      >
        <img class="icon-ai" src="@/assets/images/conversation/logo.png" alt="">
        <div class="content" :class="[aiWidthType === 'auto' ? 'width-auto' : 'width-full']">
          <MdPreview
            v-if="
              conversationData?.type === MenuTypeEnum.TEXT_TO_TEXT
                || conversationData?.type === MenuTypeEnum.ROLE
                || conversationData?.type === MenuTypeEnum.REPOSITORY
                || conversationData?.type === MenuTypeEnum.VISUAL_ANALYSIS
            "
            :editor-id="`preview-only-ai${index}`"
            :model-value="item.content"
          />
          <div v-if="conversationData?.type === MenuTypeEnum.TEXT_TO_IMAGE" class="pt-2 pb-2">
            <Image
              :width="200"
              :height="200"
              :src="item.content"
              fallback="data:image/png;base64,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"
            ></Image>
            <p v-if="!item.content.includes('http')">
              {{ item.content }}
            </p>
          </div>
        </div>
        <div v-if="item.messageType !== MessageTypeEnum.DESCRIBE" class="w-full">
          <div v-if="item.messageStatus === MessageStatusEnum.ERROR" class="error">
            哎呀，出问题了...
          </div>

          <div v-if="item.messageStatus === MessageStatusEnum.END" class="btns">
            <div class="copy" @click="copyText(item.content)">
              <SvgIcon class="icon" name="copy"></SvgIcon>
              复制
            </div>
            <div v-if="index === list.length - 1" class="reload" @click="reloadMessage">
              <SvgIcon class="icon" name="again"></SvgIcon>
              重新回答
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
@include app('message') {
  height: v-bind(height);
  overflow: auto;
  box-sizing: border-box;
  :deep(.md-editor-preview) {
    font-size: 14px;
  }
  :deep(.md-editor-preview-wrapper) {
    padding: 0;
    .text-to-image {
      width: 30%;
    }
  }

  .item {
    padding: 0 15px;
    margin-top: 20px;
    .user,
    .ai {
      display: flex;
    }
    .user {
      justify-content: flex-end;
      .content {
        max-width: calc(100% - 110px);
        padding: 5px 15px;
        background: #edf3ff;
        border-radius: 10px;
        :deep(.md-editor-preview-wrapper) {
          img {
            width: 100px;
            height: 100px;
            display: block;
          }
        }

        div {
          background: #edf3ff;
        }
      }
      .icon-user {
        width: 40px;
        height: 40px;
        margin-left: 15px;
      }
    }
    .ai {
      position: relative;
      margin-bottom: 15px;
      display: flex;
      flex-wrap: wrap;
      .icon-ai {
        width: 40px;
        height: 40px;
        margin-right: 15px;
      }
      .icon {
        margin-right: 5px;
      }
      .content {
        padding: 5px 15px;
        background: #ffffff;
        box-shadow: 0px 2px 10px 0px rgba(128, 135, 152, 0.4);
        border-radius: 10px;
        border: 1px solid #e3ebfc;
      }
      .width-auto {
        max-width: calc(100% - 110px);
      }
      .width-full {
        width: calc(100% - 110px);
      }
      .error {
        width: 100%;
        color: red;
        height: 30px;
        padding-left: 60px;
        margin-top: 10px;
      }
      .btns {
        width: 100%;
        height: 30px;
        padding-left: 60px;
        margin: 10px auto 0 auto;
        display: flex;
        align-items: center;
        .copy {
          color: #4670e3;
          margin-right: 20px;
          cursor: pointer;
        }
        .reload {
          color: #4670e3;
          cursor: pointer;
        }
      }
    }
  }
}
</style>
