<!-- 弄成一个聊天弹窗 仿照微信聊天弹窗 -->
<template>
  <div class="chat-dialog">
    <el-dialog
      v-model="dialogVisible"
      lock-scroll
      draggable
      :show-close="true"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      width="1000px"
      @close="closeDialog"
    >
      <template #header>
        <div class="dialog-header">
          <div class="title">在线消息</div>
        </div>
      </template>

      <div class="chat-layout">
        <!-- 左侧用户列表 -->
        <div class="user-list">
          <div class="search-box">
            <el-input v-model="searchText" placeholder="搜索" :prefix-icon="Search" clearable />
          </div>
          <div class="user-items">
            <div v-for="(user, k) in filteredUsers" :key="k" :class="['user-item', { active: currentUserId === user.sessionId }]" @click="switchUser(user)">
              <el-avatar :size="40" :src="userStore.userInfoRes.id === user.fromId ? user.toUser?.avatar : user.fromUser?.avatar" />
              <div class="user-info">
                <div class="user-name">{{ user.name }}</div>
                <div class="last-message">{{ user.lastMsg.content }}</div>
              </div>
              <div class="message-status">
                <div class="time">{{ handleCreateTime(user.updateTime) }}</div>
                <el-badge v-if="user.unreadCount" :value="user.unreadCount" class="unread-badge" />
              </div>
            </div>
          </div>
        </div>

        <!-- 右侧聊天区域 -->
        <div class="chat-container">
          <!-- 聊天头部 -->
          <div class="chat-header">
            <div class="header-left">
              <!-- <el-avatar :size="36" :src="currentUser?.avatar" /> -->
              <div class="title-info">
                <div class="title">{{ currentUser?.fromId === userStore.userInfoRes.id ? currentUser?.toTitle : currentUser?.fromTitle }}</div>
                <!-- <div class="subtitle">{{ currentUser?.status }}</div> -->
              </div>
            </div>
          </div>

          <!-- 消息列表区域 -->
          <div ref="messageList" class="message-list" @scroll="handleScroll">
            <!-- 加载更多提示 -->
            <div v-if="chatMessageQuery.hasMore" class="load-more">
              <el-icon v-if="chatMessageQuery.loading"><Loading /></el-icon>
              <span v-else>上拉加载更多</span>
            </div>
            <div
              v-for="(msg, index) in chatMessages"
              :key="index"
              :class="['message-item', msg.fromId === userStore.userInfoRes.id ? 'message-sent' : 'message-received']"
            >
              <div class="avatar">
                <el-avatar :size="40" :src="msg.fromId === userStore.userInfoRes.id ? userStore.userInfoRes.avatar : userAvatar" />
              </div>
              <div class="message-content">
                <div v-if="msg.msgType === 0" class="message-bubble whitespace-pre-wrap">{{ msg.content }}</div>
                <div v-else-if="msg.msgType === 1" class="message-bubble max-w-50%">
                  <img :src="msg.content" alt="图片" class="w-100%" />
                </div>
                <div v-else class="message-bubble max-w-50%">
                  {{ msg.content.split('/').pop() }}
                </div>
                <div class="message-time">{{ dayjs(msg.createTime).format('YYYY-MM-DD HH:mm:ss') }}</div>
              </div>
            </div>
          </div>

          <!-- 输入区域 -->
          <div class="input-area">
            <div class="toolbar">
              <div class="tool-left">
                <el-tooltip content="发送图片" placement="top">
                  <el-icon class="tool-icon" @click="triggerImageUpload"><Picture /></el-icon>
                </el-tooltip>
                <input ref="imageInputRef" type="file" style="display: none" @change="handleImageUpload" />
                <el-popover :visible="showEmoji" placement="top" :width="450" trigger="click">
                  <template #reference>
                    <el-icon class="tool-icon emoji-trigger" @click="showEmoji = !showEmoji"><Sunrise /></el-icon>
                  </template>

                  <div class="emoji-list">
                    <span v-for="emoji in emojiList" :key="emoji" class="emoji-item" @click="insertEmoji(emoji)">
                      {{ emoji }}
                    </span>
                  </div>
                </el-popover>
              </div>
            </div>
            <div class="input-box">
              <el-input
                v-model="inputMessage"
                type="textarea"
                :rows="3"
                placeholder="请输入消息，Enter 发送"
                resize="none"
                maxlength="255"
                @keydown.enter.prevent="(e: any) => (e.shiftKey ? (inputMessage += '\n') : handleSend(0))"
              />
            </div>
            <div class="send-btn">
              <el-button type="primary" :disabled="!inputMessage.trim() || userList.length === 0" @click="handleSend(0)">
                <el-icon class="send-icon"><Position /></el-icon>
                发送
              </el-button>
            </div>
          </div>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
  import { throttle } from 'lodash'
  import { ref, computed, onMounted, nextTick } from 'vue'
  import { Picture, Position, Sunrise, Search, Loading } from '@element-plus/icons-vue'
  import { upload } from '~/api/common'
  import { sendSingleChat, conversationList, getChatDetail, clearUnreadMessage } from '~/api/channel/index'
  import type { chatMessagesReq, msgType, PageResultSessionRespVO, PageResultMessageRespVO } from '~/api/channel/types'
  import useUserStore from '~/stores/user'
  const userStore = useUserStore()
  import dayjs from 'dayjs'

  const inputMessage = ref('')
  const messageList = ref()
  const searchText = ref('')
  const currentUserId = ref()

  const dialogVisible = defineModel<boolean>('dialogVisible', { required: true })
  // 获取传过来的数据
  const props = defineProps({
    sessionType: {
      // 会话类型0:单聊 1:群聊,示例值(2)
      type: String,
      default: '1',
    },
  })
  console.log('会话类型', props.sessionType)

  // 模拟数据
  const userAvatar = 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png'

  const userList = ref<PageResultSessionRespVO[]>([])

  // 获取会话列表
  const getConversationList = async (type?: string) => {
    const res = await conversationList()
    if (res.code === 0) {
      userList.value = res.data
        ?.map((item) => {
          return {
            ...item,
            name: userStore.userInfoRes.id === item.fromId ? item.toTitle : item.fromTitle,
            lastMsg: item.lastMsg ? JSON.parse(item.lastMsg) : { content: '' },
          }
        })
        .filter((user) => userStore.userInfoRes.nickname !== user.name) // 提出自己
      // 默认选中第一个
      if (type === 'init' && userList.value.length > 0) {
        switchUser(userList.value[0])
      }
    }
  }
  getConversationList('init')

  // 聊天记录
  const chatMessages = ref<PageResultMessageRespVO['list']>([])

  const filteredUsers = computed(() => {
    if (!searchText.value) return userList.value
    return userList.value.filter(
      (user) => user.name.toLowerCase().includes(searchText.value.toLowerCase()) || user.lastMsg.content.toLowerCase().includes(searchText.value.toLowerCase())
    )
  })

  const currentUser = computed(() => {
    return userList.value.find((user) => user.sessionId === currentUserId.value)
  })

  const handleCreateTime = (time: string) => {
    // 先判断是否是今天  今天取时分 不是今天取年月日
    const today = dayjs()
    const msgTime = dayjs(time)
    if (today.isSame(msgTime, 'day')) {
      return msgTime.format('HH:mm')
    } else {
      return msgTime.format('YYYY-MM-DD')
    }
  }

  // 聊天消息查询
  const chatMessageQuery = ref({
    pageNo: 1,
    pageSize: 10,
    hasMore: true,
    loading: false,
    sessionId: 0,
    toId: 0,
    isPending: false,
  })
  const switchUser = async (user: PageResultSessionRespVO) => {
    // 切换用户
    chatMessageQuery.value.toId = user.fromId === userStore.userInfoRes.id ? user.toId : user.fromId
    chatMessageQuery.value.sessionId = currentUserId.value = user.sessionId
    user.unreadCount = 0 // 清除未读消息
    // 切换用户时，清空聊天记录
    chatMessageQuery.value.loading = true
    chatMessageQuery.value.pageNo = 1
    chatMessageQuery.value.hasMore = true
    chatMessages.value = []
    await getChatDetailList()
    nextTick(() => {
      scrollToBottom()
    })
    // 清空未读消息
    clearUnreadMessage({ id: user.sessionId })
  }

  const getChatDetailList = async () => {
    const res = await getChatDetail({
      sessionId: chatMessageQuery.value.sessionId,
      pageNo: chatMessageQuery.value.pageNo,
      pageSize: chatMessageQuery.value.pageSize,
    })
    if (res.code === 0) {
      chatMessageQuery.value.isPending = false
      // 数据反过来
      if (res.data.list.length > 0) {
        // 保存当前滚动位置和内容高度
        const scrollElement = messageList.value
        const oldScrollHeight = scrollElement.scrollHeight
        const oldScrollTop = scrollElement.scrollTop
        chatMessages.value = [...res.data.list.reverse(), ...chatMessages.value]
        // 在下一个 tick 后调整滚动位置
        nextTick(() => {
          const newScrollHeight = scrollElement.scrollHeight
          const heightDiff = newScrollHeight - oldScrollHeight
          scrollElement.scrollTop = oldScrollTop + heightDiff
        })
      }
      chatMessageQuery.value.loading = false
      chatMessageQuery.value.pageNo++
      // 判断是否还有更多数据
      if (res.data.list.length < chatMessageQuery.value.pageSize) {
        chatMessageQuery.value.hasMore = false
      }
    }
  }

  // 滚动处理函数
  const handleScroll = async (e: Event) => {
    const target = e.target as HTMLElement
    // 当滚动到顶部附近时触发加载更多
    if (target.scrollTop < 50 && !chatMessageQuery.value.loading && chatMessageQuery.value.hasMore && !chatMessageQuery.value.isPending) {
      // await loadMoreMessages()
      chatMessageQuery.value.isPending = true
      await throttledGetChatList()
    }
  }

  // 创建节流函数，设置 500ms 的间隔
  const throttledGetChatList = throttle(async () => {
    await getChatDetailList()
  }, 1500)

  const handleSend = (msgType: msgType = 0) => {
    if (!inputMessage.value.trim()) return

    const newMessage = {
      msgType: msgType,
      content: inputMessage.value,
      toId: chatMessageQuery.value.toId, // 对方userId
      userId: userStore.userInfoRes.id, // 当前用户id
      fromId: userStore.userInfoRes.id, // 当前用户id
      createTime: dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss'), // 当前时间戳
    }

    chatMessages.value.push(newMessage)
    userStore.mqttClient?.publish(`zbjk_message_single/${currentUserId.value}`, JSON.stringify(newMessage))

    // 更新用户列表中的最后一条消息
    userLastMessage(newMessage)
    // 清空输入框
    inputMessage.value = ''
    // 滚动到底部
    scrollToBottom()
    // 发送单聊信息存储到服务器
    sendSingleChat(newMessage)
  }

  const userLastMessage = (msg: chatMessagesReq) => {
    console.log('msg', msg)
    const user = userList.value.find((u) => u.sessionId === currentUserId.value)
    if (user) {
      user.lastMsg.content = msg.content
      user.updateTime = user.createTime = msg.createTime
    }
  }

  const scrollToBottom = () => {
    if (messageList.value) {
      nextTick(() => {
        messageList.value.scrollTop = messageList.value.scrollHeight
      })
    }
  }

  onMounted(() => {
    userStore.mqttClient?.onMessage((topic: string, message: any) => {
      if (topic.indexOf(`zbjk_message_single`) === -1) return
      console.log('接收消息---------', topic, message)
      console.log('当前用户id', userStore.userInfoRes.id)
      console.log('当前聊天用户id', currentUserId.value)

      // 将消息添加到聊天记录中
      const msg = JSON.parse(message)
      if (msg.sessionId === currentUserId.value) {
        msg.msgType = Number(msg.msgType)
        // 当前用户发送的消息
        chatMessages.value.push(msg)
        // 更新当前用户列表中的最后一条消息
        userLastMessage(msg)
        // 清空未读消息
        clearUnreadMessage({ id: msg.sessionId })
        if (msg.msgType === 1) {
          const img = new Image()
          img.src = msg.content
          img.onload = () => {
            // 滚动到底部
            scrollToBottom()
          }
        } else {
          // 滚动到底部
          scrollToBottom()
        }
      } else {
        // 添加未读消息
        const user = userList.value.find((u) => u.sessionId === msg.sessionId)
        if (user) {
          user.unreadCount++
          user.updateTime = user.createTime = msg.createTime
          user.lastMsg.content = msg.content
          // 正常会拉取后端聊天接口
        } else {
          getConversationList('refresh')
        }
      }
    })

    document.addEventListener('click', (event) => {
      const target = event.target as HTMLElement
      if (!target.closest('.emoji-popover') && !target.closest('.emoji-trigger')) {
        showEmoji.value = false
      }
    })
  })
  // 触发图片上传
  const imageInputRef = ref()
  const triggerImageUpload = (): void => {
    if (imageInputRef.value) {
      imageInputRef.value.click()
    }
  }

  // 处理图片上传
  const handleImageUpload = async (event: Event) => {
    const target = event.target as HTMLInputElement
    const files = target.files

    if (files && files.length > 0) {
      const file = files[0]

      // 检查文件类型 0:文本 1:图片 2:视频 3:文件
      const msgType = file.type.startsWith('image/') ? 1 : file.type.startsWith('video/') ? 2 : 3
      const formData = new FormData()
      formData.append('fieldName', file?.name)
      formData.append('file', file as Blob)
      const res = await upload('/prod-api/app-api/infra/file/upload', formData)
      if (res.code === 0) {
        const imageUrl = res.data
        if (msgType === 1) {
          // 预加载图片
          const img = new Image()
          img.src = imageUrl
          img.onload = () => {
            inputMessage.value = imageUrl
            handleSend(msgType)
          }
        } else {
          inputMessage.value = imageUrl
          handleSend(msgType)
        }
      }

      // 重置文件输入以允许重复选择同一文件
      if (imageInputRef.value) {
        imageInputRef.value.value = ''
      }
    }
  }
  const showEmoji = ref(false)
  const emojiList = [
    '😀',
    '😃',
    '😄',
    '😁',
    '😆',
    '😅',
    '😂',
    '🤣',
    '😊',
    '😇',
    '🙂',
    '🙃',
    '😉',
    '😌',
    '😍',
    '🥰',
    '😘',
    '😗',
    '😙',
    '😚',
    '😋',
    '😛',
    '😝',
    '😜',
    '🤪',
    '🤨',
    '🧐',
    '🤓',
    '😎',
    '🤩',
    '🥳',
    '😏',
    '😒',
    '😞',
    '😔',
    '😟',
    '😕',
    '🙁',
    '☹️',
    '😣',
  ]

  const insertEmoji = (emoji: string) => {
    inputMessage.value += emoji
    showEmoji.value = false
  }

  const closeDialog = () => {
    dialogVisible.value = false
  }
</script>

<style lang="scss" scoped>
  .emoji-list {
    display: grid;
    grid-template-columns: repeat(10, 1fr);
    gap: 8px;

    .emoji-item {
      cursor: pointer;
      font-size: 20px;
      padding: 4px;
      display: flex;
      align-items: center;
      justify-content: center;
      transition: all 0.2s;

      &:hover {
        background: #f5f5f5;
        border-radius: 4px;
        transform: scale(1.2);
      }
    }
  }
  .chat-dialog {
    :deep(.el-dialog__header) {
      margin: 0;
      padding: 0;
      border-radius: 8px 8px 0 0;
      overflow: hidden;
    }

    :deep(.el-dialog__body) {
      padding: 0px !important;
      overflow: hidden;
      display: flex;
    }

    :deep(.el-dialog) {
      border-radius: 8px;
      overflow: hidden;
      box-shadow: 0 12px 32px 4px rgba(0, 0, 0, 0.1);
    }

    :deep(.el-dialog__headerbtn) {
      top: 24px;
      right: 12px;
      z-index: 10;

      .el-dialog__close {
        font-size: 16px;
        transition: all 0.3s;

        &:hover {
          opacity: 0.8;
        }
      }
    }
  }

  .dialog-header {
    display: flex;
    align-items: center;
    padding: 0 16px;
    // height: 40px;

    .title {
      font-size: 14px;
      font-weight: normal;
    }
  }

  .chat-layout {
    display: flex;
    flex: 1;
  }

  .user-list {
    width: 280px;
    border-right: 1px solid #eee;
    display: flex;
    flex-direction: column;
    background-color: #34353a;

    .search-box {
      padding: 12px 12px 12px 12px;
      :deep(.el-input__wrapper) {
        background-color: #4f5054 !important;
        box-shadow: none !important;
      }
      :deep(.el-input__inner) {
        color: #fff;
        border-radius: 16px;
        border: none;

        &:focus {
          box-shadow: none;
        }
      }
    }

    .user-items {
      flex: 1;
      overflow-y: auto;

      .user-item {
        display: flex;
        align-items: flex-start;
        padding: 12px;
        cursor: pointer;
        transition: all 0.3s;

        &:hover {
          // background-color: #f5f5f5;
        }

        &.active {
          background-color: rgba(255, 255, 255, 0.12) !important;
        }

        .user-info {
          flex: 1;
          margin: 0 12px;
          overflow: hidden;

          .user-name {
            font-size: 14px;
            font-weight: 500;
            margin-bottom: 4px;
            color: #fff;
          }

          .last-message {
            font-size: 14px;
            color: #999;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
          }
        }

        .message-status {
          text-align: right;

          .time {
            font-size: 12px;
            color: #999;
            margin-bottom: 4px;
          }

          .unread-badge {
            :deep(.el-badge__content) {
              background-color: #c561f9;
            }
          }
        }
      }
    }
  }

  .chat-container {
    flex: 1;
    display: flex;
    flex-direction: column;

    .chat-header {
      padding: 16px 20px;
      background: #fff;
      border-bottom: 1px solid #eee;

      .header-left {
        display: flex;
        align-items: center;
        gap: 12px;

        .title-info {
          .title {
            font-size: 16px;
            font-weight: 500;
            color: #333;
            margin-bottom: 4px;
          }

          .subtitle {
            font-size: 12px;
            color: #999;
          }
        }
      }
    }
  }

  .message-list {
    flex: 1;
    padding: 24px;
    box-sizing: border-box;
    overflow-y: auto;
    background-color: #f7f8fa;
    min-height: 300px;
    .load-more {
      text-align: center;
      padding: 10px 0;
      color: #999;
      font-size: 12px;
    }

    .message-item {
      display: flex;
      margin-bottom: 24px;

      &.message-sent {
        flex-direction: row-reverse;

        .message-content {
          margin-right: 12px;
          margin-left: 80px;
          align-items: flex-end;

          .message-bubble {
            background: #1a65ff;
            color: #fff;
            border-radius: 12px 2px 12px 12px;
            box-shadow: 0 4px 12px rgba(197, 97, 249, 0.2);
          }
        }
      }

      &.message-received {
        .message-content {
          margin-left: 12px;
          margin-right: 80px;

          .message-bubble {
            background-color: #fff;
            border-radius: 2px 12px 12px 12px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
          }
        }
      }
    }

    .message-content {
      display: flex;
      flex-direction: column;

      .message-bubble {
        padding: 12px 16px;
        font-size: 14px;
        max-width: 400px;
        word-break: break-word;
        line-height: 1.6;
      }

      .message-time {
        font-size: 12px;
        color: #999;
        margin-top: 6px;
      }
    }
  }

  .input-area {
    background-color: #fff;
    border-top: 1px solid #eee;
    padding: 16px 24px;
    box-sizing: border-box;

    .toolbar {
      display: flex;
      justify-content: space-between;
      padding: 0 0 12px;

      .tool-left {
        display: flex;
        gap: 20px;
      }

      .tool-icon {
        font-size: 20px;
        color: #666;
        cursor: pointer;
        transition: all 0.3s;

        &:hover {
          color: #c561f9;
          transform: scale(1.1);
        }
      }
    }

    .input-box {
      margin-bottom: 12px;

      :deep(.el-textarea__inner) {
        border: 1px solid #fff !important;
        border-radius: 8px;
        padding: 12px;
        font-size: 14px;
        transition: all 0.3s;
        outline: none !important;
        box-shadow: none !important;

        &:focus {
          border-color: #c561f9;
          box-shadow: none !important;
          // box-shadow: 0 0 0 2px rgba(197, 97, 249, 0.1);
        }

        &::placeholder {
          color: #999;
        }
      }
    }

    .send-btn {
      display: flex;
      justify-content: flex-end;

      .el-button {
        background: #1a65ff;
        border: none;
        padding: 10px 24px;
        font-size: 14px;
        border-radius: 8px;
        transition: all 0.3s;
        display: flex;
        align-items: center;
        gap: 6px;

        .send-icon {
          font-size: 16px;
        }

        &:hover {
          transform: translateY(-1px);
          // box-shadow: 0 4px 12px rgba(197, 97, 249, 0.3);
        }

        &:active {
          transform: translateY(0);
        }

        &.is-disabled {
          background: #e0e0e0;
          opacity: 0.6;
        }
      }
    }
  }

  // 自定义滚动条样式
  .message-list {
    &::-webkit-scrollbar {
      width: 6px;
    }

    &::-webkit-scrollbar-thumb {
      background-color: rgba(0, 0, 0, 0.1);
      border-radius: 3px;

      &:hover {
        background-color: rgba(0, 0, 0, 0.2);
      }
    }

    &::-webkit-scrollbar-track {
      background-color: transparent;
    }
  }
</style>
