<template>
    <div class="chat-page">
        <div class="left-panel">
            <WxUserCard @load="onLoadUserList" :cardlist="userList" height="calc(100vh - 120px)"
                @change="onSelectUser" />
        </div>
        <div class="right-panel">
            <div :class="['chat-body', { 'chat-body--loading': isLoadingMessages, 'chat-body--dragging': isDragging }]"
                ref="chatBody" @scroll="handleScroll" @dragover.prevent="handleDragOver"
                @dragenter.prevent="handleDragEnter" @dragleave.prevent="handleDragLeave" @drop.prevent="handleDrop">
                <!-- 加载更多提示 -->
                <div v-if="loadingMore" class="loading-more">加载中...</div>
                <!-- 拖拽提示 -->
                <div v-if="isDragging" class="drag-overlay">
                    <div class="drag-hint">
                        <el-icon style="font-size: 48px; color: var(--el-color-primary);">
                            <svg class="icon" aria-hidden="true">
                                <use xlink:href="#icon-tupian1"></use>
                            </svg>
                        </el-icon>
                        <p>松开鼠标发送图片</p>
                    </div>
                </div>

                <WxChatRecord :msgList="messages" :sendeInfo="sendeInfo" msgType="user" @retry="handleRetry" />
            </div>

            <div class="chat-footer">
                <div class="footer-left" style="">
                    <!-- 附件预览区（粘贴的图片先进入此处，点击发送后再发送） -->
                    <div v-if="attachments.length" class="attach-preview-row" style="display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:4px 8px;">
                        <div v-for="(att, idx) in attachments" :key="att._id" class="attach-item"
                            style="position:relative;width:64px;height:64px;border:1px solid var(--el-border-color);border-radius:6px;overflow:hidden;display:flex;align-items:center;justify-content:center;background:#fff;">
                            <img :src="att.previewUrl" alt="preview" style="max-width:100%;max-height:100%;" />
                            <span @click="removeAttachment(idx)"
                                  style="position:absolute;top:2px;right:2px;background:rgba(0,0,0,.55);color:#fff;border-radius:10px;line-height:16px;height:16px;width:16px;text-align:center;cursor:pointer;font-size:12px;">×</span>
                        </div>
                        <el-link type="danger" @click="clearAttachments">清空</el-link>
                    </div>
                    <div class="upload-row"
                        style="display:flex; align-items:center; gap:12px;margin-left: 6px;position: relative; top: 10px;">
                        <el-icon style="font-size:24px;cursor:pointer" @click="triggerImageInput">
                            <svg class="icon" aria-hidden="true">
                                <use xlink:href="#icon-tupian1"></use>
                            </svg>
                        </el-icon>
                        <input ref="imageInput" type="file" accept="image/*" multiple style="display:none"
                            @change="handleImageChange" />
                        <V3Emoji @click-emoji="onEmojiSelect" :recent="true"></V3Emoji>
                    </div>
                    <el-input type="textarea" v-model="draft" placeholder="输入消息..." :rows="2" style="flex:1"
                        @keydown="handleInputKeydown" @paste="handlePaste" />
                </div>
                <!-- 发送按钮 -->
                <div class="send-button-container" style="margin-left: 12px;">
                    <el-button type="primary" @click="send" :disabled="(!draft.trim() && attachments.length === 0) || isSending || isUploading"
                        :loading="isSending" style="height: 60px;">
                        {{ isSending ? '发送中...' : '发送' }}
                    </el-button>
                    <el-button type="primary" @click="sendTemplateMessage" :loading="isSending2" style="height: 60px;">
                        {{ isSending2 ? '发送中...' : '发送模板消息' }}
                    </el-button>
                </div>
            </div>
        </div>
    </div>
</template>

<script setup>
import { ref, reactive, onMounted, nextTick, watch, onUnmounted } from 'vue'
import WxChatRecord from '@/components/ChatRecord/index.vue'
import WxUserCard from '@/components/UserCard/index.vue'
import UserMessage from '@/components/UserMessage/index.vue'
import mihoutai from '@/assets/images/mihoutai.png'
import V3Emoji from "vue3-emoji";
import { getUserList, send_message, get_messages, send_template_message, checkMiniProgramStatus } from '@/api/chat'
import { useRoute } from 'vue-router'
import { uploadFile } from '@/api/upload'
import { ElMessage } from 'element-plus'
import appDetail from '@/store/modules/appDetail'
const appInfoStore = appDetail()

const route = useRoute()

// 好友列表数据
const userList = ref([])

const activeUser = ref({})
const messages = ref([])
const draft = ref('')
const imageInput = ref(null)
const chatBody = ref(null)
const isLoadingMessages = ref(false)
// 附件（待发送的粘贴图片）
const attachments = ref([])

// 发送者信息
const sendeInfo = reactive({
    userInfo: { user_id: '', user_name: '', user_avatar: '' },
    robotInfo: { wx_id: '', head_url: '' }
})

// 消息分页查询参数
const msgQuery = reactive({
    page: 1,
    page_size: 100,
    app_id: route.query.app_id,
    user_id: ''
})

// 状态变量
const loadingMore = ref(false)
const noMoreMessages = ref(false)
const isAutoScroll = ref(true) // 是否自动滚动到底部
const messageTimer = ref(null) // 定时器实例
const isSending = ref(false) // 防止重复发送
const lastSendTime = ref(0) // 最后发送时间，用于防抖
const isUploading = ref(false) // 防止重复上传
const isDragging = ref(false) // 拖拽状态
const dragCounter = ref(0) // 拖拽计数器，用于处理嵌套元素
// 小程序状态轮询定时器
const appStatusTimer = ref(null)

// 选择用户
const onSelectUser = async (id) => {
    const u = userList.value.find((it) => it.sender_id == id)
    if (u) {
        userList.value.forEach((it) => (it.active = it.sender_id === id))
        activeUser.value = u
        sendeInfo.userInfo = { user_id: u.sender_id, user_name: u.sender_name, user_avatar: u.sender_avatar }
        sendeInfo.robotInfo = { wx_id: 'robot', head_url: mihoutai }

        // 重置消息列表和分页
        messages.value = []
        msgQuery.page = 1
        msgQuery.user_id = u.sender_id
        noMoreMessages.value = false

        // 为避免切换用户时看到明显的滚动过程：
        // - 在开始加载消息前将 chat 区域设置为不可见（但依然可滚动），
        // - 加载完成后恢复显示并滚到底部（保持原有的交互顺序）。
        isLoadingMessages.value = true

        // 保持原有行为：先滚动到底部再加载（不 await），以免改变用户可感知的交互顺序
        scrollToBottom()
        // 启动加载（不 await，使界面更流畅）
        getMessages().finally(() => {
            // 在消息加载结束后恢复可见性并尝试滚到底部
            isLoadingMessages.value = false
            // 确保滚到底部以避免残留偏移
            scrollToBottom()
        })

        // 重启定时器
        restartMessageTimer()
    }
}


let msgTotal = 0
// 消息排序函数
const sortMessagesByTime = (messages) => {
    const sorted = messages.sort((a, b) => {
        // 尝试解析时间戳
        const getTimestamp = (msg) => {
            // 优先使用真实的时间戳字段
            if (msg.timestamp) {
                const ts = new Date(msg.timestamp).getTime()
                if (!isNaN(ts)) return ts
            }

            if (msg.created_at) {
                const ts = new Date(msg.created_at).getTime()
                if (!isNaN(ts)) return ts
            }

            // 处理send_time字段
            if (msg.send_time) {
                // 标准时间格式：2025-10-22 01:52:19
                if (typeof msg.send_time === 'string') {
                    // 如果是相对时间（如"刚刚"、"3分钟前"），使用当前时间减去相应的时间
                    if (msg.send_time.includes('刚刚')) {
                        return Date.now() - 1000 // 1秒前
                    } else if (msg.send_time.includes('分钟前')) {
                        const minutes = parseInt(msg.send_time.match(/(\d+)分钟前/)?.[1] || '0')
                        return Date.now() - (minutes * 60 * 1000)
                    } else if (msg.send_time.includes('小时前')) {
                        const hours = parseInt(msg.send_time.match(/(\d+)小时前/)?.[1] || '0')
                        return Date.now() - (hours * 60 * 60 * 1000)
                    } else if (msg.send_time.includes('天前')) {
                        const days = parseInt(msg.send_time.match(/(\d+)天前/)?.[1] || '0')
                        return Date.now() - (days * 24 * 60 * 60 * 1000)
                    }

                    // 尝试解析标准时间格式
                    const timestamp = new Date(msg.send_time).getTime()
                    if (!isNaN(timestamp)) return timestamp
                }
            }

            // 如果有ID，尝试从ID中提取时间信息
            if (msg.id || msg._id || msg.message_id) {
                const id = String(msg.id || msg._id || msg.message_id)
                // 如果ID是纯数字且可能是时间戳
                if (/^\d+$/.test(id)) {
                    const numId = parseInt(id)
                    // 检查是否是合理的时间戳范围（2020年到2030年）
                    if (numId > 1577836800000 && numId < 1893456000000) { // 13位时间戳
                        return numId
                    } else if (numId > 1577836800 && numId < 1893456000) { // 10位时间戳
                        return numId * 1000
                    }
                }
                // 如果ID包含时间戳
                const timestampMatch = id.match(/(\d{13})/) // 13位时间戳
                if (timestampMatch) return parseInt(timestampMatch[1])
            }

            // 默认返回当前时间
            return Date.now()
        }

        return getTimestamp(a) - getTimestamp(b)
    })

    // 调试信息：显示排序后的消息时间
    // console.log('消息排序结果:', sorted.map(m => ({
    //     id: m.id || m._id || m.message_id,
    //     send_time: m.send_time,
    //     content: typeof m.content === 'object' ?
    //         (m.content.message || JSON.stringify(m.content)) :
    //         String(m.content).slice(0, 20) + '...'
    // })))

    return sorted
}

// 获取消息（区分加载历史和最新消息）
// isHistory: 是否为向上翻页加载历史
// pageOverride: 可选的临时 page 值（不会修改 msgQuery.page），用于定时拉取最新时使用 page=1
const getMessages = async (isHistory = true, pageOverride = null) => {
    if (loadingMore.value) return
    if (isHistory && noMoreMessages.value) return
    if (!msgQuery.user_id) return

    // 只有在历史加载时才设置loadingMore状态，避免轮询时的界面抖动
    const isPolling = !isHistory && pageOverride === 1
    if (!isPolling) {
        loadingMore.value = true
    }

    // 在第一次加载（page=1 且 isHistory=true）期间也将 isLoadingMessages 保持为 true
    if ((pageOverride ?? msgQuery.page) === 1 && isHistory) {
        isLoadingMessages.value = true
    }
    const queryPage = pageOverride ?? msgQuery.page
    const query = { ...msgQuery, page: queryPage }

    try {
        const res = await get_messages({ ...query })
        msgTotal = res.total || 0
        const list = res.list || []

        // console.log(`获取消息 - isHistory: ${isHistory}, page: ${queryPage}, 返回消息数: ${list.length}`)

        if (list.length > 0) {
            const newMessages = list.map(item => {
                // 处理消息内容，确保与ChatRecord组件兼容
                try {
                    const text = JSON.parse(item.content)
                    item.content = {
                        message: text.message || text.messages
                    }
                } catch (e) {
                    // 如果解析失败，说明是纯字符串，包装为对象格式
                    item.content = { message: item.content }
                }
                return item
            })

            if (isHistory) {
                // 在向上加载历史时，需要在 prepend 前记录 scrollHeight 以便恢复视图位置
                const el = chatBody.value
                const prevScrollHeight = el ? el.scrollHeight : 0

                if (queryPage === 1) {
                    // 第一次加载（第一页）直接替换，并排序
                    messages.value = sortMessagesByTime([...newMessages])
                } else {
                    // 向上翻页，prepend，然后重新排序整个列表
                    const allMessages = [...newMessages, ...messages.value]
                    messages.value = sortMessagesByTime(allMessages)
                    // 等待 DOM 更新后恢复滚动位置，避免跳动
                    await nextTick()
                    if (el) {
                        // 保持用户看到原来位置（新内容高度增加导致的偏移）
                        el.scrollTop = el.scrollHeight - prevScrollHeight
                    }
                }
            } else {
                // 拉取最新消息（追加到末尾），改进去重逻辑
                const currentMessages = [...messages.value]
                let hasUpdates = false

                // 处理每条新消息
                for (const newMsg of newMessages) {
                    let isProcessed = false

                    // 1. 首先尝试匹配临时消息（基于内容和时间）
                    const tempMsgIndex = currentMessages.findIndex(existingMsg => {
                        if (!existingMsg._isTemp || existingMsg._failed) return false

                        // 检查发送者和消息类型
                        const senderMatch = existingMsg.sender_id === newMsg.sender_id
                        const typeMatch = existingMsg.msg_type === newMsg.msg_type

                        // 检查时间差（10秒内）
                        const timeDiff = Math.abs(Date.now() - (existingMsg._timestamp || 0))
                        const timeMatch = timeDiff < 10000

                        // 根据消息类型进行不同的内容匹配
                        let contentMatch = false
                        if (existingMsg.msg_type === 1) {
                            // 文本消息：比较文本内容
                            const existingContent = existingMsg._tempContent ||
                                (typeof existingMsg.content === 'object' ? existingMsg.content.message : existingMsg.content)
                            const newContent = typeof newMsg.content === 'object' ? newMsg.content.message : newMsg.content
                            contentMatch = existingContent === newContent
                        } else if (existingMsg.msg_type === 2) {
                            // 图片消息：比较文件信息（文件名和大小）
                            if (existingMsg._tempImageFile) {
                                const newContent = typeof newMsg.content === 'object' ? newMsg.content.message : newMsg.content
                                // 如果新消息包含文件名，尝试匹配
                                if (typeof newContent === 'string' && newContent.includes(existingMsg._tempImageFile.name.split('.')[0])) {
                                    contentMatch = true
                                }
                            }
                        }

                        return senderMatch && typeMatch && contentMatch && timeMatch
                    })

                    if (tempMsgIndex !== -1) {
                        // 找到匹配的临时消息，替换它
                        // console.log('找到匹配的临时消息，进行替换:', {
                        //     tempId: currentMessages[tempMsgIndex]._id,
                        //     realId: newMsg.id || newMsg._id || newMsg.message_id
                        // })
                        currentMessages[tempMsgIndex] = {
                            ...newMsg,
                            _isTemp: false // 标记为非临时消息
                        }
                        hasUpdates = true
                        isProcessed = true
                    } else {
                        // 2. 检查是否已存在相同的真实消息（基于ID）
                        const existingMsgIndex = currentMessages.findIndex(existingMsg => {
                            if (existingMsg._isTemp) return false // 跳过临时消息

                            // 优先使用真实ID字段进行匹配
                            const existingId = existingMsg.id || existingMsg._id || existingMsg.message_id
                            const newId = newMsg.id || newMsg._id || newMsg.message_id

                            if (existingId && newId && existingId === newId) {
                                return true
                            }

                            // 如果没有ID，使用多字段组合进行匹配
                            const existingContentStr = typeof existingMsg.content === 'object' ?
                                (existingMsg.content.message || JSON.stringify(existingMsg.content)) :
                                String(existingMsg.content)
                            const newContentStr = typeof newMsg.content === 'object' ?
                                (newMsg.content.message || JSON.stringify(newMsg.content)) :
                                String(newMsg.content)

                            const compositeMatch = existingMsg.sender_id === newMsg.sender_id &&
                                existingMsg.send_time === newMsg.send_time &&
                                existingMsg.msg_type === newMsg.msg_type &&
                                existingContentStr === newContentStr

                            return compositeMatch
                        })

                        if (existingMsgIndex === -1) {
                            // 3. 真正的新消息，添加到列表
                            // console.log('发现新消息:', {
                            //     id: newMsg.id || newMsg._id || newMsg.message_id,
                            //     content: typeof newMsg.content === 'object' ? newMsg.content.message : newMsg.content
                            // })
                            currentMessages.push(newMsg)
                            hasUpdates = true
                            isProcessed = true
                        } else {
                            // console.log('消息已存在，跳过:', {
                            //     id: newMsg.id || newMsg._id || newMsg.message_id
                            // })
                        }
                    }
                }

                if (hasUpdates) {
                    // 重新排序并更新消息列表
                    messages.value = sortMessagesByTime(currentMessages)
                    // console.log('消息列表已更新，当前消息数:', messages.value.length)
                } else {
                    // console.log('没有新消息需要处理')
                }
            }

            // 使用 total 判断是否还有更多历史消息（仅在已知 total 时判断）
            if (msgTotal && isHistory) {
                noMoreMessages.value = messages.value.length >= msgTotal
            } else if (list.length < msgQuery.page_size && isHistory) {
                // 如果后端没有 total，退回到 page_size 判断
                noMoreMessages.value = true
            }

            // 非历史加载且处于自动滚动状态时滚到底部
            if (!isHistory && isAutoScroll.value) {
                await scrollToBottom()
            }
        } else if (isHistory) {
            noMoreMessages.value = true
        }
    } catch (err) {
        // 可扩展错误处理
    } finally {
        // 只有在非轮询时才清理loadingMore状态
        const isPolling = !isHistory && pageOverride === 1
        if (!isPolling) {
            loadingMore.value = false
        }

        // 如果这是第一页历史加载，确保 loading 标志被清理（页面外也会在调用者 finally 中清理）
        if ((pageOverride ?? msgQuery.page) === 1 && isHistory) {
            isLoadingMessages.value = false
        }

        // 如果是向上翻页（非第一页）并且 prepend 后视图仍然靠近顶部，自动继续翻页
        try {
            if (isHistory && queryPage !== 1) {
                await nextTick()
                const el2 = chatBody.value
                const nearTop = el2 ? el2.scrollTop <= 50 : false
                if (nearTop && !noMoreMessages.value) {
                    // 继续加载下一页历史（递增 page）
                    msgQuery.page = msgQuery.page + 1
                    await getMessages(true)
                }
            }
        } catch (e) {
            // 忽略自动加载中的错误，保持用户可见性
        }
    }
}

// 滚动事件处理
const handleScroll = (e) => {
    const { scrollTop, scrollHeight, clientHeight } = e.target
    const isNearBottom = scrollHeight - scrollTop - clientHeight < 50 // 距离底部小于50px视为在底部

    // 更新自动滚动状态
    isAutoScroll.value = isNearBottom

    // 控制定时器
    if (isNearBottom && !messageTimer.value && msgQuery.user_id) {
        // 在底部且无定时器，启动定时器
        startMessageTimer()
    } else if (!isNearBottom && messageTimer.value) {
        // 不在底部且有定时器，停止定时器
        stopMessageTimer()
    }

    // 滚动到顶部时加载更多历史消息
    if (scrollTop <= 0 && !loadingMore.value && !noMoreMessages.value) {
        loadMoreMessages()
    }
}

// 加载更多历史消息
const loadMoreMessages = () => {
    if (msgQuery.user_id && !loadingMore.value && !noMoreMessages.value) {
        msgQuery.page++
        getMessages(true)
    }
}

// 发送消息
const send = async () => {
    const content = draft.value.trim()
    if ((!content && attachments.value.length === 0) || isSending.value || isUploading.value) return

    // 防抖检查
    const now = Date.now()
    if (now - lastSendTime.value < 500) {
        // console.log('发送过于频繁，已忽略')
        return
    }

    // 如果有文本，按原逻辑发送文本
    if (content) {
        // 检查是否有相同内容的发送中消息
        const hasSendingMessage = messages.value.some(msg =>
            msg._sending &&
            msg.sender_id === '888888' &&
            msg.msg_type === 1 &&
            typeof msg.content === 'object' &&
            msg.content.message === content &&
            (now - (msg._timestamp || 0)) < 5000
        )

        if (hasSendingMessage) {
            // console.log('存在相同内容的发送中消息，已忽略')
        } else {
            isSending.value = true
            lastSendTime.value = now

            // 生成临时消息ID，使用特殊前缀标识
            const tempId = `temp_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
            const msg = {
                _id: tempId,
                _sending: true,
                _failed: false,
                _isTemp: true, // 标记为临时消息
                sender_id: '888888',
                sender_name: '平台',
                msg_type: 1,
                content: { message: content },
                send_time: '刚刚',
                _timestamp: now,
                _tempContent: content // 保存原始内容用于匹配
            }

            messages.value.push(msg)
            draft.value = ''

            // 滚动到底部
            setTimeout(() => scrollToBottom(), 100)
            isAutoScroll.value = true

            // 发送到服务器
            send_message({
                app_id: route.query.app_id,
                content: JSON.stringify({
                    message: content
                }),
                msg_type: 1,
                to_user_id: activeUser.value.sender_id
            }).then((response) => {
                msg._sending = false
                msg._failed = false
                // 发送成功后，立即轮询获取最新消息以获取真实ID
                setTimeout(() => {
                    getMessages(false, 1) // 轮询最新消息
                }, 500)
            }).catch((error) => {
                msg._sending = false
                msg._failed = true
                ElMessage({ type: 'error', message: '消息发送失败' })
            }).finally(() => {
                // 重置发送状态
                isSending.value = false
            })
        }
    }

    // 如果存在待发送附件，逐个上传发送
    if (attachments.value.length > 0) {
        const filesToSend = attachments.value.map(a => a.file)
        // 先清空附件预览并回收URL
        attachments.value.forEach(a => {
            if (a.previewUrl && a.previewUrl.startsWith('blob:')) {
                URL.revokeObjectURL(a.previewUrl)
            }
        })
        attachments.value = []

        // 串行发送
        const queue = filesToSend.slice()
        const processNext = () => {
            if (queue.length === 0) return
            if (isUploading.value) {
                setTimeout(processNext, 150)
                return
            }
            const f = queue.shift()
            uploadImageFile(f)
            setTimeout(processNext, 150)
        }
        processNext()
    }
}

// 键盘事件处理
const handleInputKeydown = (e) => {
    if (e.key === 'Enter' && !e.shiftKey) {
        e.preventDefault()
        // 添加防抖延迟
        setTimeout(() => {
            send()
        }, 50)
    }
}

// 图片上传相关
const triggerImageInput = () => {
    imageInput.value && imageInput.value.click()
}

// 提取图片上传逻辑为可复用函数
const uploadImageFile = (file) => {
    if (!file) return

    // 检查是否有选中用户
    if (!activeUser.value.sender_id) {
        ElMessage({ type: 'warning', message: '请先选择用户' })
        return
    }

    // 防止重复上传
    if (isUploading.value) {
        // console.log('图片正在上传中，请稍候')
        return
    }

    // 检查文件类型是否为图片
    if (!file.type.startsWith('image/')) {
        ElMessage({ type: 'error', message: '只能上传图片文件' })
        return
    }

    // 检查文件大小（限制为10MB）
    if (file.size > 10 * 1024 * 1024) {
        ElMessage({ type: 'error', message: '图片大小不能超过10MB' })
        return
    }

    isUploading.value = true

    // 本地预览
    const url = URL.createObjectURL(file)
    const tempId = `temp_img_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
    const now = Date.now()
    const msg = {
        _id: tempId,
        _sending: true,
        _failed: false,
        _isTemp: true, // 标记为临时消息
        sender_id: '888888',
        sender_name: '平台',
        msg_type: 2,
        content: { message: url },
        send_time: '刚刚',
        _timestamp: now,
        _tempImageFile: file // 保存文件信息用于匹配
    }
    messages.value.push(msg)

    // 滚动到底部
    setTimeout(() => scrollToBottom(), 100)
    isAutoScroll.value = true

    // 上传文件
    const form = new FormData()
    form.append('file', file)
    form.append('app_id', route.query.app_id)
    form.append('msg_type', 2)
    form.append('to_user_id', activeUser.value.sender_id)
    uploadFile(form, import.meta.env.VITE_APP_BASE_API + 'admin/upload/image').then((resp) => {
        // 上传成功，调用send_message接口发送图片消息
        const imageUrl = import.meta.env.VITE_APP_BASE_API_img + resp.preview_image_url.replace('/api/', '')

        send_message({
            app_id: route.query.app_id,
            msg_type: 2,
            content: JSON.stringify({ message: imageUrl }),
            to_user_id: activeUser.value.sender_id
        }).then(() => {
            // 发送成功，移除临时消息
            const index = messages.value.findIndex(m => m._id === tempId)
            if (index !== -1) {
                messages.value.splice(index, 1)
            }

            // 清理本地预览URL
            if (url.startsWith('blob:')) {
                URL.revokeObjectURL(url)
            }

            // 轮询获取最新消息
            setTimeout(() => {
                getMessages(false, 1)
            }, 500)
        }).catch((sendError) => {
            // 发送失败，更新临时消息状态
            msg._sending = false
            msg._failed = true
            // console.error('发送图片消息失败:', sendError)
            ElMessage({ type: 'error', message: '发送图片失败' })
        })
    }).catch((error) => {
        msg._sending = false
        msg._failed = true
        // console.error('图片上传失败:', error)
        ElMessage({ type: 'error', message: '图片上传失败' })
    }).finally(() => {
        isUploading.value = false
        // 清理本地预览URL
        if (url.startsWith('blob:')) {
            URL.revokeObjectURL(url)
        }
    })
}

const handleImageChange = (e) => {
    const files = Array.from(e.target.files || [])
    if (files.length) {
        // 加入附件预览区，等待手动点击发送
        const imageFiles = files.filter(f => f && f.type && f.type.startsWith('image/'))
        if (imageFiles.length === 0) ElMessage({ type: 'error', message: '只能上传图片文件' })
        addAttachmentFiles(imageFiles)
    }
    // 清空input值，以便下次选择同一文件时也能触发change事件
    e.target.value = ''
}

// 处理粘贴发送图片
const handlePaste = (e) => {
    try {
        const clipboard = e.clipboardData || window.clipboardData
        if (!clipboard) return
        const items = clipboard.items || []
        if (!items || items.length === 0) return

        // 收集剪贴板中的图片文件
        const imageFiles = []
        for (let i = 0; i < items.length; i++) {
            const it = items[i]
            if (it && it.kind === 'file') {
                const file = it.getAsFile && it.getAsFile()
                if (file && file.type && file.type.startsWith('image/')) {
                    imageFiles.push(file)
                }
            }
        }

        if (imageFiles.length === 0) {
            // 没有图片，保持默认粘贴文本行为
            return
        }

        // 阻止默认插入到文本框，走图片发送逻辑
        e.preventDefault()

        // 将粘贴的图片添加到附件区，等待用户手动点击发送
        addAttachmentFiles(imageFiles)
    } catch (err) {
        // 失败时不影响默认粘贴行为
    }
}

// 附件辅助：添加、移除、清空
const addAttachmentFiles = (files) => {
    const list = Array.from(files || [])
    list.forEach((file) => {
        if (!file || !file.type || !file.type.startsWith('image/')) return
        if (file.size > 10 * 1024 * 1024) {
            ElMessage({ type: 'error', message: '图片大小不能超过10MB' })
            return
        }
        const previewUrl = URL.createObjectURL(file)
        attachments.value.push({
            _id: `att_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,
            file,
            previewUrl
        })
    })
}

const removeAttachment = (index) => {
    const item = attachments.value[index]
    if (item && item.previewUrl && item.previewUrl.startsWith('blob:')) {
        URL.revokeObjectURL(item.previewUrl)
    }
    attachments.value.splice(index, 1)
}

const clearAttachments = () => {
    attachments.value.forEach(a => {
        if (a.previewUrl && a.previewUrl.startsWith('blob:')) {
            URL.revokeObjectURL(a.previewUrl)
        }
    })
    attachments.value = []
}

// 拖拽事件处理
const handleDragEnter = (e) => {
    e.preventDefault()
    e.stopPropagation()
    dragCounter.value++
    // 检查拖拽内容是否包含文件
    if (e.dataTransfer.types.includes('Files')) {
        isDragging.value = true
    }
}

const handleDragOver = (e) => {
    e.preventDefault()
    e.stopPropagation()
    // 设置拖拽效果为复制
    if (e.dataTransfer) {
        e.dataTransfer.dropEffect = 'copy'
    }
}

const handleDragLeave = (e) => {
    e.preventDefault()
    e.stopPropagation()
    dragCounter.value--
    // 只有当计数器为0时才取消拖拽状态（处理嵌套元素）
    if (dragCounter.value === 0) {
        isDragging.value = false
    }
}

const handleDrop = (e) => {
    e.preventDefault()
    e.stopPropagation()
    dragCounter.value = 0
    isDragging.value = false

    // 检查是否有选中用户
    if (!activeUser.value.sender_id) {
        ElMessage({ type: 'warning', message: '请先选择用户' })
        return
    }

    // 获取拖拽的文件
    const files = Array.from(e.dataTransfer.files)

    if (files.length === 0) {
        return
    }

    // 过滤出图片文件
    const imageFiles = files.filter(file => file.type.startsWith('image/'))

    if (imageFiles.length === 0) {
        ElMessage({ type: 'warning', message: '请拖拽图片文件' })
        return
    }

    // 加入附件预览区，等待手动点击发送
    addAttachmentFiles(imageFiles)
}

// 重发消息
const handleRetry = (id) => {
    const msg = messages.value.find((m) => m._id === id)
    if (!msg) return

    msg._failed = false
    msg._sending = true

    if (msg.msg_type === 0) {
        send_message({
            app_id: route.query.app_id,
            content: msg.content.content,
            msg_type: 1,
            to_user_id: activeUser.value.sender_id
        }).then(() => {
            msg._sending = false
        }).catch(() => {
            msg._sending = false;
            msg._failed = true;
            ElMessage({ type: 'error', message: '重发失败' })
        })
    } else if (msg.msg_type === 2) {
        const form = new FormData()
        form.append('file', msg.content.file)
        form.append('app_id', route.query.app_id)
        form.append('msg_type', 2)
        form.append('to_user_id', activeUser.value.sender_id)
        send_message(form).then(() => {
            msg._sending = false
        }).catch(() => {
            msg._sending = false;
            msg._failed = true;
            ElMessage({ type: 'error', message: '重发失败' })
        })
    }
}

// 滚动到底部
const scrollToBottom = async () => {
    await nextTick()
    const el = chatBody.value
    if (!el) return
    try {
        el.scrollTop = el.scrollHeight
    } catch (e) {
        // 忽略错误
    }
}

// 表情选择
const onEmojiSelect = (emoji) => {
    draft.value = (draft.value || '') + emoji
}

// 获取用户列表
const params = reactive({
    page: 1,
    page_size: import.meta.env.VITE_APP_PAGE_SIZE,
    app_id: route.query.app_id
})

const getUsers = (append = false) => {
    getUserList(params).then((res) => {
        if (append) {
            userList.value = res.list // userList.value.concat(res.list || [])
        } else {
            userList.value = res.list || []
        }
        // 首次加载且没有选中用户时，默认选中第一个
        if (!append && userList.value.length && !activeUser.value.sender_id) {
            onSelectUser(userList.value[0].sender_id)
        }
    })
}

// 加载更多用户
const onLoadUserList = async () => {
    params.page = params.page + 1
    await getUsers(true)
    await nextTick()
    const el = document.querySelector('.left-panel .infinite-list')
    if (el) {
        el.scrollTop = el.scrollHeight
    }
}

// 定时器相关函数
const startMessageTimer = () => {
    // 清除现有定时器
    if (messageTimer.value) {
        clearInterval(messageTimer.value)
    }

    // 每秒获取一次最新消息，不修改 msgQuery.page，使用 pageOverride=1
    messageTimer.value = setInterval(() => {
        if (!msgQuery.user_id) return
        // 获取最新消息（第一页），用于追加新消息
        // console.log('定时器轮询消息，用户ID:', msgQuery.user_id)
        getMessages(false, 1)
    }, 1000)
}

// 用户列表轮询定时器
const userListTimer = ref(null)

const startUserListTimer = () => {
    // 清除现有定时器
    if (userListTimer.value) {
        clearInterval(userListTimer.value)
    }

    // 每秒获取一次用户列表
    userListTimer.value = setInterval(() => {
        getUsers(false) // 不追加，直接替换
    }, 1000)
}

const stopUserListTimer = () => {
    if (userListTimer.value) {
        clearInterval(userListTimer.value)
        userListTimer.value = null
    }
}

// 格式化最新消息内容
const formatLastMessage = (user) => {
    if (!user.content) return ''

    try {
        // 尝试解析JSON格式的content
        const contentObj = JSON.parse(user.content)

        // 优先返回messages字段
        if (contentObj.messages) {
            const content = String(contentObj.messages).slice(0, 30)
            return content.length > 30 ? content + '...' : content
        }

        // 其次返回text字段
        if (contentObj.text) {
            const content = String(contentObj.text).slice(0, 30)
            return content.length > 30 ? content + '...' : content
        }

        // 最后返回content字段
        if (contentObj.content) {
            const content = String(contentObj.content).slice(0, 30)
            return content.length > 30 ? content + '...' : content
        }

        // 如果都没有，返回JSON字符串的前30个字符
        const content = JSON.stringify(contentObj).slice(0, 30)
        return content.length > 30 ? content + '...' : content

    } catch (error) {
        // JSON解析失败，说明是纯字符串
        let content = String(user.content)

        // 根据消息类型添加前缀
        if (user.msg_type === 2) {
            content = '[图片] ' + content
        } else if (user.msg_type === 3) {
            content = '[文件] ' + content
        } else if (user.msg_type === 4) {
            content = '[语音] ' + content
        } else if (user.msg_type === 5) {
            content = '[视频] ' + content
        }

        // 限制长度
        content = content.slice(0, 30)
        return content.length > 30 ? content + '...' : content
    }
}

const stopMessageTimer = () => {
    if (messageTimer.value) {
        clearInterval(messageTimer.value)
        messageTimer.value = null
    }
}

const restartMessageTimer = () => {
    stopMessageTimer()
    if (msgQuery.user_id) {
        startMessageTimer()
    }
}

const sendTemplateMessage = (templateId) => {
    if (!activeUser.value.sender_id) return
    send_template_message({
        "app_id": route.query.app_id,
        "app_secret": route.query.app_secret,
        "template_id": route.query.template_id,
        "touser": activeUser.value.sender_id
    }).then((res) => {
        if (res.success == true) {
            ElMessage({ type: 'success', message: '模板消息发送成功' })
            // 发送成功后，立即轮询获取最新消息以获取真实ID
            setTimeout(() => {
                getMessages(false, 1) // 轮询最新消息
            }, 500)
        } else {
            ElMessage({ type: 'error', message: '推送失败，对方没有订阅！' })
        }

    })

}


const getAppStaus = async () => {
    try {
        const res = await checkMiniProgramStatus({
            app_id: route.query.app_id
        })
        // appInfoStore.appDetail 是一个 ref，使用 .value 同步
        if (appInfoStore && appInfoStore.appDetail) {
            appInfoStore.appDetail.check_status_text = res.check_status_text || ''
        }
        return res
    } catch (error) {
        if (appInfoStore && appInfoStore.appDetail) {
            appInfoStore.appDetail.check_status_text = ''
        }
        // console.error('获取应用状态失败:', error)
        return null
    }
}

const startAppStatusTimer = () => {
    if (appStatusTimer.value) clearInterval(appStatusTimer.value)
    // 立即触发一次，然后每60秒触发
    getAppStaus()
    appStatusTimer.value = setInterval(() => {
        if (!route.query.app_id) return
        getAppStaus()
    }, 60 * 1000)
}

const stopAppStatusTimer = () => {
    if (appStatusTimer.value) {
        clearInterval(appStatusTimer.value)
        appStatusTimer.value = null
    }
}
// 组件挂载时
onMounted(() => {
    getUsers()
    getAppStaus()
    // 启动用户列表轮询
    startUserListTimer()

    // 监听窗口关闭，清理定时器
    window.addEventListener('beforeunload', () => {
        stopMessageTimer()
        stopUserListTimer()
    })
})

// 组件卸载时清理定时器
onUnmounted(() => {
    stopMessageTimer()
    stopUserListTimer()
})

// 监听活跃用户变化，重启定时器
watch(activeUser, (newVal) => {
    if (newVal.sender_id) {
        restartMessageTimer()
    } else {
        stopMessageTimer()
    }
})

// 当 messages 变化时，尝试可靠地滚动到底部：
// - 等待 DOM 更新（nextTick），
// - 立即滚动并在短延迟后再滚一次以应对图片等资源加载导致的高度变化，
// - 对未加载的图片注册 load 事件，加载完成后再滚动。
watch(messages, async (newVal, oldVal) => {
    // 只有在自动滚动模式下才触发
    if (!isAutoScroll.value) return

    await nextTick()
    // 立即尝试滚动到底部
    scrollToBottom()

    // 在短延迟后再尝试一次，以容忍布局抖动或图片加载
    setTimeout(() => scrollToBottom(), 120)

    // 如果存在未完成加载的图片，注册 load 事件，加载后滚到底部
    const el = chatBody.value
    if (el) {
        const imgs = el.querySelectorAll('img')
        imgs.forEach(img => {
            if (!img.complete) {
                img.addEventListener('load', () => {
                    if (isAutoScroll.value) scrollToBottom()
                }, { once: true })
            }
        })
    }
})
</script>

<style scoped lang="scss">
.chat-page {
    display: flex;
    height: calc(100vh - 64px);
}

:deep(.el-textarea__inner) {
    background-color: transparent;
    padding-left: 8px !important;
}

.left-panel {
    width: 280px;
    border-right: 1px solid var(--el-border-color);
    background: var(--el-bg-color);
    display: flex;
    flex-direction: column;
}

.left-header {
    height: 60px;
    line-height: 60px;
    padding: 0 16px;
    font-weight: 600;
}

.right-panel {
    flex: 1;
    display: flex;
    flex-direction: column;
}

.chat-header {
    height: 64px;
    display: flex;
    align-items: center;
    padding: 0 16px;
    border-bottom: 1px solid var(--el-border-color);
}

.chat-header .avatar {
    width: 40px;
    height: 40px;
    margin-right: 12px;
}

.chat-body {
    flex: 1;
    padding: 16px;
    overflow: auto;
    background: #f5f7fa;
    position: relative;
}

.chat-body--dragging {
    background: rgba(64, 158, 255, 0.05);
}

.drag-overlay {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(64, 158, 255, 0.1);
    border: 2px dashed var(--el-color-primary);
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
    pointer-events: none;
}

.drag-hint {
    text-align: center;
    color: var(--el-color-primary);
    font-size: 16px;
    font-weight: 500;
}

.drag-hint p {
    margin-top: 12px;
    margin-bottom: 0;
}

/* Hide scrollbar but keep scrolling functionality */
.chat-body {
    /* For WebKit-based browsers (Chrome, Safari, Edge Chromium) */
    -webkit-overflow-scrolling: touch;
}

.chat-body::-webkit-scrollbar {
    width: 0px;
    height: 0px;
}

/* For Firefox */
.chat-body {
    scrollbar-width: none;
    /* Firefox */
}

/* For IE and older Edge */
.chat-body {
    -ms-overflow-style: none;
    /* IE 10+ */
}

/* When loading messages during user switch, hide visual content to avoid jump/flicker */
.chat-body--loading {
    opacity: 0;
    transition: opacity 180ms ease-in-out;
    pointer-events: none;
    /* prevent interaction during transient loading */
}

// 加载更多样式
.loading-more {
    text-align: center;
    padding: 10px;
    color: #666;
    font-size: 14px;
}

.chat-footer {
    height: 96px;
    padding: 5px 15px;
    border-top: 1px solid var(--el-border-color);
    display: flex;
    align-items: center;
    gap: 10px;
    padding-top: 10px;
}

.chat-footer .footer-left {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.chat-footer .el-button {
    height: 40px;
    align-self: flex-end;
}

.chat-footer .actions {
    display: flex;
    align-items: center
}
.attach-preview-row{
    position: absolute;
    bottom: 90px;
}
</style>