<template>
	<!-- #ifdef APP -->
	<scroll-view style="flex:1">
	<!-- #endif -->
	<view class="page">
		<!-- 自定义导航栏 -->
		<view class="nav" :style="{ paddingTop: headerPaddingTop + 'px', height: headerTotalHeight + 'px' }">
			<view class="nav-back" @tap="goBack">
				<view class="nav-back-icon"></view>
			</view>
			<text class="nav-title">{{ roomName }}</text>
		</view>
		<!-- 聊天室人员和操作 -->
		<view class="room-toolbar" :style="{ top: headerPaddingTop + 44 + 'px' }">
			<view class="member-count" @tap="showMembers = !showMembers">
				<text class="member-count-text">{{ totalMembers.length > 0 ? totalMembers.length + ' 人在线' : '暂无人员' }}</text>
			</view>
			<view class="toolbar-right">
				<button class="toolbar-btn" @tap="handleWorkcaseAction">
					<text class="toolbar-btn-text">{{ workcaseId ? '查看工单' : '创建工单' }}</text>
				</button>
				<button class="toolbar-btn meeting-btn" @tap="startMeeting">
					<text class="toolbar-btn-text meeting-text">发起会议</text>
				</button>
			</view>
		</view>
		<!-- 弹窗显示人员列表和在线情况 -->
		<view v-if="showMembers" class="members-popup-mask" @tap="showMembers = false">
			<view class="members-popup" :style="{ top: headerPaddingTop + 88 + 'px' }" @tap.stop>
				<view class="members-list">
					<view v-if="totalMembers.length === 0" class="members-empty">
						<text class="members-empty-text">暂无人员在线</text>
					</view>
					<view v-else class="member-item" v-for="member in totalMembers" :key="member.oderId">
						<view class="member-avatar">
							<text class="member-avatar-text">{{ member.userName?.charAt(0) || '客' }}</text>
						</view>
						<text class="member-name">{{ member.userName || '未知' }}</text>
						<view class="member-status" :class="member.isOnline ? 'online' : 'offline'"></view>
					</view>
				</view>
			</view>
		</view>
		<!-- 聊天消息区域 -->
		<scroll-view class="chat-area" scroll-y="true" :scroll-top="scrollTop"
			:scroll-with-animation="false"
			:style="{ top: (headerPaddingTop + 88) + 'px' }"
			@scrolltoupper="loadMoreMessages"
			upper-threshold="50">
			<!-- 加载更多提示 -->
			<view v-if="loadingMore" class="loading-more">
				<text class="loading-more-text">加载中...</text>
			</view>
			<view v-else-if="!hasMore" class="loading-more">
				<text class="loading-more-text">没有更多消息了</text>
			</view>
			<view class="message-list">
				<view class="message-item" v-for="msg in messages" :key="msg.messageId">
					<!-- 系统消息（居中显示） -->
					<view class="message-row system-row" v-if="msg.senderType === 'system'">
						<view class="system-message-container">
							<!-- 评分消息卡片 -->
							<template v-if="msg.messageType === 'comment'">
								<CommentMessageCard
									:room-id="roomId"
									:can-comment="getCanComment()"
									:initial-rating="commentLevel"
									@submit="handleCommentSubmit"
								/>
							</template>
							<!-- 其他系统消息 -->
							<template v-else>
								<view class="system-message-text">
									<text>{{ msg.content }}</text>
								</view>
							</template>
							<text class="message-time">{{ formatTime(msg.sendTime) }}</text>
						</view>
					</view>

					<!-- 普通用户/客服消息 -->
					<view v-else :class="msg.senderId === currentUserId ? 'self' : 'other'">
					<!-- 对方消息（左侧） -->
					<view class="message-row other-row" v-if="msg.senderId !== currentUserId">
						<view>
							<view class="avatar">
								<text class="avatar-text">{{ msg.senderName?.charAt(0) || '客' }}</text>
							</view>
							<text class="sender-name">{{ msg.senderName || '客服' }}</text>
						</view>
						<!-- 会议消息卡片 -->
						<view class="message-content meeting-card-wrapper" v-if="msg.messageType === 'meet' && msg.contentExtra">
							<MeetingCard :meetingId="msg.content" @join="handleJoinMeeting" />
							<text class="message-time">{{ formatTime(msg.sendTime) }}</text>
						</view>
						<!-- 普通消息 -->
						<view class="message-content" v-else>
							<view class="bubble other-bubble">
								<rich-text :nodes="renderMarkdown(msg.content || '')" class="message-rich-text"></rich-text>
								<!-- 文件列表 -->
								<view v-if="msg.files && msg.files.length > 0" class="message-files">
									<view v-for="fileId in msg.files" :key="fileId" class="message-file-item" @tap="downloadFile(fileId)">
										<text class="file-icon">📎</text>
										<text class="file-name">{{ getFileNameFromId(fileId) }}</text>
									</view>
								</view>
							</view>
							<text class="message-time">{{ formatTime(msg.sendTime) }}</text>
						</view>
					</view>
					<!-- 自己消息（右侧） -->
					<view class="message-row self-row" v-else>
						<!-- 会议消息卡片 -->
						<view class="message-content meeting-card-wrapper" v-if="msg.messageType === 'meet' && msg.contentExtra">
							<MeetingCard :meetingId="msg.content" @join="handleJoinMeeting" />
							<text class="message-time">{{ formatTime(msg.sendTime) }}</text>
						</view>
						<!-- 普通消息 -->
						<view class="message-content" v-else>
							<view class="bubble self-bubble">
								<text class="message-text">{{ msg.content }}</text>
								<!-- 文件列表 -->
								<view v-if="msg.files && msg.files.length > 0" class="message-files">
									<view v-for="fileId in msg.files" :key="fileId" class="message-file-item" @tap="downloadFile(fileId)">
										<text class="file-icon">📎</text>
										<text class="file-name">{{ getFileNameFromId(fileId) }}</text>
									</view>
								</view>
							</view>
							<text class="message-time">{{ formatTime(msg.sendTime) }}</text>
						</view>
						<view class="avatar self-avatar">
							<text class="avatar-text">我</text>
						</view>
					</view>
					</view>
				</view>
			</view>
		</scroll-view>

		<!-- 底部输入区 -->
		<view class="footer">
			<!-- 文件预览区域 -->
			<view v-if="selectedFiles.length > 0" class="file-preview-container">
				<view v-for="(file, index) in selectedFiles" :key="index" class="file-preview-item">
					<view class="file-info">
						<text class="file-name">{{ file.name }}</text>
						<text class="file-size">{{ formatFileSize(file.size) }}</text>
					</view>
					<view class="file-actions">
						<text class="file-delete" @tap="removeFile(index)">删除</text>
					</view>
				</view>
			</view>
			
			<!-- 输入和操作行 -->
			<view class="input-row">
				<view class="input-actions">
					<view class="action-btn" @tap="chooseFile">
						<text class="action-icon">📎</text>
					</view>
				</view>
				<input class="chat-input" v-model="inputText" placeholder="输入消息..." 
					@confirm="sendMessage" />
				<view class="send-btn" @tap="sendMessage" :class="{ disabled: isUploading || selectedFiles.length === 0 && !inputText.trim() }">
					<text class="send-icon">➤</text>
				</view>
			</view>
		</view>

	</view>
	<!-- #ifdef APP -->
	</scroll-view>
	<!-- #endif -->
</template>

<script setup lang="ts">
import { ref, reactive, computed, nextTick, onMounted, onUnmounted, watch } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import MeetingCard from '../../meeting/meetingCard/MeetingCard.uvue'
import CommentMessageCard from './CommentMessageCard/CommentMessageCard.uvue'
import type { ChatRoomMessageVO, CustomerVO, ChatMemberVO, TbChatRoomMessageDTO, VideoMeetingVO } from '@/types/workcase'
import { workcaseChatAPI } from '@/api/workcase'
import { fileAPI } from '@/api/file'
import { wsClient } from '@/utils/websocket'
import { WS_HOST } from '@/config'
// 响应式数据
const headerPaddingTop = ref<number>(44)
const headerTotalHeight = ref<number>(88)
const roomId = ref<string>('')
const workcaseId = ref<string>('')
const roomName = ref<string>('聊天室')
const guestId = ref<string>('')  // 聊天室访客ID
const deviceCode = ref<string>('')  // 聊天室设备代码
const commentLevel = ref<number>(0)  // 已有评分
const inputText = ref<string>('')
const scrollTop = ref<number>(0)
const loading = ref<boolean>(false)
const sending = ref<boolean>(false)
const loadingMore = ref<boolean>(false)
const currentPage = ref<number>(1)
const hasMore = ref<boolean>(true)

// 文件上传相关变量
const uploadingFiles = ref<any[]>([])
const selectedFiles = ref<any[]>([])
const isUploading = ref<boolean>(false)

// 用户信息（从storage获取）
const currentUserId = ref<string>('')
const currentUserName = ref<string>('我')

function loadUserInfo() {
	try {
		const userInfo = uni.getStorageSync('userInfo')
		const loginDomain = uni.getStorageSync('loginDomain')
		if (userInfo) {
			const user = typeof userInfo === 'string' ? JSON.parse(userInfo) : userInfo
			currentUserId.value = user.userId || user.id || ''
			// 优先从 loginDomain.userInfo 获取用户名
			if (loginDomain) {
				const domain = typeof loginDomain === 'string' ? JSON.parse(loginDomain) : loginDomain
				if (domain.userInfo && domain.userInfo.username) {
					currentUserName.value = domain.userInfo.username
				} else if (domain.userInfo && domain.userInfo.realName) {
					currentUserName.value = domain.userInfo.realName
				} else {
					currentUserName.value = user.username || user.nickName || user.realName || user.name || '用户'
				}
			} else {
				currentUserName.value = user.username || user.nickName || user.realName || user.name || '用户'
			}
		}
		console.log('[chatRoom] 用户信息:', currentUserId.value, currentUserName.value)
	} catch (e) {
		console.error('获取用户信息失败:', e)
	}
}

// 消息列表
const messages = reactive<ChatRoomMessageVO[]>([])
// 加载遮罩（已禁用）
// const showLoadingMask = ref<boolean>(true)

// 所有默认客服
const defaultWorkers = reactive<CustomerVO[]>([])
async function loadDefaultWorkers() {
	const res = await workcaseChatAPI.getAvailableCustomerServices()
	if(res.success && res.dataList) {
		defaultWorkers.splice(0, defaultWorkers.length, ...res.dataList)
	}
}
// 查询进入聊天室的人员, 包含了访客
const chatMembers = reactive<ChatMemberVO[]>([])
async function loadChatMembers() {
	const res = await workcaseChatAPI.getChatRoomMemberList(roomId.value)
	if(res.success && res.dataList) {
		chatMembers.splice(0, chatMembers.length, ...res.dataList)
	}
}
const showMembers = ref(false)

// 计算聊天室人数: 默认客服转成ChatMemberVO + 进入聊天室的人员，去重，进入聊天室的人员是在线状态
interface MemberDisplay {
	oderId: string
	userId: string
	userName: string
	isOnline: boolean
}
const totalMembers = computed<MemberDisplay[]>(() => {
	const memberMap = new Map<string, MemberDisplay>()
	
	// 先添加默认客服（离线状态）
	defaultWorkers.forEach((worker, index) => {
		memberMap.set(worker.userId || '', {
			oderId: `worker-${index}`,
			userId: worker.userId || '',
			userName: worker.username || '客服',
			isOnline: false
		})
	})
	
	// 再添加聊天室成员（在线状态），覆盖同一用户
	chatMembers.forEach((member, index) => {
		memberMap.set(member.userId || '', {
			oderId: member.memberId || `member-${index}`,
			userId: member.userId || '',
			userName: member.userName || '未知',
			isOnline: true
		})
	})
	
	return Array.from(memberMap.values())
})

function getCanComment(): boolean {
	return currentUserId.value === guestId.value
}
// 生命周期
onMounted(() => {
	const windowInfo = uni.getWindowInfo()
	const statusBarHeight = windowInfo.statusBarHeight || 44
	
	// #ifdef MP-WEIXIN
	try {
		const menuButtonInfo = uni.getMenuButtonBoundingClientRect()
		headerPaddingTop.value = menuButtonInfo.top
		headerTotalHeight.value = menuButtonInfo.bottom + 8
	} catch (e) {
		headerPaddingTop.value = statusBarHeight
		headerTotalHeight.value = statusBarHeight + 44
	}
	// #endif
	// #ifndef MP-WEIXIN
	headerPaddingTop.value = statusBarHeight
	headerTotalHeight.value = statusBarHeight + 44
	// #endif

	// 获取页面参数
	const pages = getCurrentPages()
	const currentPage = pages[pages.length - 1] as any
	if (currentPage && currentPage.options) {
		roomId.value = currentPage.options.roomId || ''
		workcaseId.value = currentPage.options.workcaseId || ''
	}

	loadUserInfo()
	loadChatRoom()
	loadDefaultWorkers()
	loadChatMembers()
	initWebSocket()
})

// 页面显示时重新查询聊天室信息（从工单页返回时会自动刷新）
onShow(() => {
	refreshChatRoomInfo()
})

// 组件卸载时断开WebSocket
onUnmounted(() => {
	disconnectWebSocket()
})

// 监听roomId变化，切换聊天室时重新订阅
watch(roomId, (newRoomId, oldRoomId) => {
	if (oldRoomId && newRoomId !== oldRoomId) {
		// 取消旧聊天室订阅
		wsClient.unsubscribe(`/topic/chat/${oldRoomId}`)
	}
	if (newRoomId && wsClient.isConnected()) {
		// 订阅新聊天室
		wsClient.subscribe(`/topic/chat/${newRoomId}`, handleNewMessage)
	}
})

// 加载聊天室
const PAGE_SIZE = 20
const messageTotal = ref<number>(0)

// 刷新聊天室信息（仅更新 workcaseId 等基本信息，不重新加载消息）
async function refreshChatRoomInfo() {
	if (!roomId.value) return
	try {
		const roomRes = await workcaseChatAPI.getChatRoomById(roomId.value)
		if (roomRes.success && roomRes.data) {
			roomName.value = roomRes.data.roomName || '聊天室'
			workcaseId.value = roomRes.data.workcaseId || ''
			guestId.value = roomRes.data.guestId || ''
			deviceCode.value = roomRes.data.deviceCode || ''
			commentLevel.value = roomRes.data.commentLevel || 0
			messageTotal.value = roomRes.data.messageCount || 0
		}
	} catch (e) {
		console.error('刷新聊天室信息失败:', e)
	}
}

async function loadChatRoom() {
	if (!roomId.value) return
	loading.value = true
	try {
		// 自动加入聊天室成员表（如果不存在）
		try {
			const userId = uni.getStorageSync('userId') || currentUserId.value
			const userName = uni.getStorageSync('userName') || currentUserName.value
			await workcaseChatAPI.addChatRoomMember({
				roomId: roomId.value,
				userId: userId,
				userName: userName,
				userType: 'guest'
			})
		} catch (error) {
			// 已存在成员或其他错误，忽略
			console.debug('[chatRoom] 加入聊天室成员表:', error)
		}
		
		// 获取聊天室信息
		const roomRes = await workcaseChatAPI.getChatRoomById(roomId.value)
		if (roomRes.success && roomRes.data) {
			roomName.value = roomRes.data.roomName || '聊天室'
			workcaseId.value = roomRes.data.workcaseId || ''
			guestId.value = roomRes.data.guestId || ''
			deviceCode.value = roomRes.data.deviceCode || ''
			messageTotal.value = roomRes.data.messageCount || 0
			commentLevel.value = roomRes.data.commentLevel!
		}
		// 后端是降序查询，page1是最新消息
		currentPage.value = 1
		hasMore.value = true // 默认有更多，loadMessages中会根据实际情况更新
		// 获取消息列表
		await loadMessages()
	} catch (e) {
		console.error('加载聊天室失败:', e)
	} finally {
		loading.value = false
	}
}

// 加载消息列表（后端降序，page1是最新消息，需要反转显示）
async function loadMessages() {
	console.log('[loadMessages] 开始加载, currentPage:', currentPage.value, 'roomId:', roomId.value)
	if (!roomId.value) return
	try {
		const msgRes = await workcaseChatAPI.getChatMessagePage({
			filter: { roomId: roomId.value },
			pageParam: { page: currentPage.value, pageSize: PAGE_SIZE }
		})
		console.log('[loadMessages] 响应:', msgRes)
		if (msgRes.success && msgRes.dataList) {
			const pageInfo = msgRes.pageDomain?.pageParam
			const actualTotalPages = pageInfo?.totalPages || 1
			hasMore.value = actualTotalPages > currentPage.value
			console.log('[loadMessages] pageInfo:', pageInfo, 'actualTotalPages:', actualTotalPages, 'hasMore:', hasMore.value)

			// 后端降序返回，需要反转后显示（早的在上，新的在下）
			const reversedList = [...msgRes.dataList].reverse()
			messages.splice(0, messages.length, ...reversedList)
			console.log('[loadMessages] 加载完成, 消息数:', messages.length)

			// 加载完第一页后滚动到底部，需要等待 DOM 完全渲染
			if (currentPage.value === 1) {
				// 使用 setTimeout 确保 DOM 完全渲染后再滚动
				nextTick(() => {
					setTimeout(() => {
						scrollToBottom()
					}, 300)
				})
			} else {
				nextTick(() => scrollToBottom())
			}
		}
	} catch (e) {
		console.error('加载消息列表失败:', e)
	}
}

// 加载更多历史消息（滚动到顶部触发，加载下一页更早的消息）
async function loadMoreMessages() {
	console.log('[loadMoreMessages] 触发, roomId:', roomId.value, 'loadingMore:', loadingMore.value, 'hasMore:', hasMore.value, 'currentPage:', currentPage.value)
	if (!roomId.value || loadingMore.value || !hasMore.value) {
		console.log('[loadMoreMessages] 跳过加载 - roomId:', !roomId.value, 'loadingMore:', loadingMore.value, '!hasMore:', !hasMore.value)
		return
	}
	
	// 加载下一页（更早的消息）
	const nextPage = currentPage.value + 1
	console.log('[loadMoreMessages] 准备加载页:', nextPage)
	
	loadingMore.value = true
	try {
		const msgRes = await workcaseChatAPI.getChatMessagePage({
			filter: { roomId: roomId.value },
			pageParam: { page: nextPage, pageSize: PAGE_SIZE }
		})
		console.log('[loadMoreMessages] 响应:', msgRes)
		if (msgRes.success && msgRes.dataList && msgRes.dataList.length > 0) {
			const pageInfo = msgRes.pageDomain?.pageParam
			const actualTotalPages = pageInfo?.totalPages || 1
			hasMore.value = actualTotalPages > currentPage.value
			console.log('[loadMoreMessages] pageInfo:', pageInfo, 'actualTotalPages:', actualTotalPages, 'hasMore:', hasMore.value)
			
			currentPage.value = nextPage
			// 后端降序返回，反转后插入到列表前面
			const reversedList = [...msgRes.dataList].reverse()
			messages.unshift(...reversedList)
			console.log('[loadMoreMessages] 加载完成, 消息数:', messages.length)
		} else {
			console.log('[loadMoreMessages] 没有更多数据')
			hasMore.value = false
		}
	} catch (e) {
		console.error('加载更多消息失败:', e)
	} finally {
		loadingMore.value = false
	}
}

// 格式化时间（兼容 iOS）
function formatTime(time?: string): string {
	if (!time) return ''
	// iOS 不支持 "yyyy-MM-dd HH:mm:ss" 格式，需要转换为 "yyyy-MM-ddTHH:mm:ss" 或 "yyyy/MM/dd HH:mm:ss"
	const iosCompatibleTime = time.replace(' ', 'T')
	const date = new Date(iosCompatibleTime)
	if (isNaN(date.getTime())) return ''
	return `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`
}

// 获取会议数据（将contentExtra转换为VideoMeetingVO）
// 从消息extra中提取meetingId
function getMeetingId(contentExtra: Record<string, any> | undefined): string {
	if (!contentExtra || !contentExtra.meetingId) {
		console.warn('[chatRoom] contentExtra中没有meetingId:', contentExtra)
		return ''
	}
	return contentExtra.meetingId as string
}

// Markdown渲染函数（返回富文本HTML）
function renderMarkdown(text: string): string {
	if (!text) return ''

	// 转义HTML特殊字符
	let html = text
		.replace(/&/g, '&amp;')
		.replace(/</g, '&lt;')
		.replace(/>/g, '&gt;')

	// 处理粗体（**语法）
	html = html.replace(/\*\*([^\*]+)\*\*/g, '<strong>$1</strong>')

	// 处理斜体（*语法，但要避免和粗体冲突）
	html = html.replace(/(?<!\*)\*([^\*]+)\*(?!\*)/g, '<em>$1</em>')

	// 处理行内代码（`语法）
	html = html.replace(/`([^`]+)`/g, '<code style="background-color:#f5f5f5;padding:2px 6px;border-radius:3px;font-family:monospace;color:#e53e3e;word-break:break-all;">$1</code>')

	// 处理链接（[text](url)语法）
	html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" style="color:#0055AA;text-decoration:underline;word-break:break-all;">$1</a>')

	// 处理标题（# ## ###等）
	html = html.replace(/^### (.+)$/gm, '<div style="font-size:16px;font-weight:600;margin:8px 0 4px;">$1</div>')
	html = html.replace(/^## (.+)$/gm, '<div style="font-size:18px;font-weight:600;margin:10px 0 6px;">$1</div>')
	html = html.replace(/^# (.+)$/gm, '<div style="font-size:20px;font-weight:700;margin:12px 0 8px;">$1</div>')

	// 处理无序列表（- 或 * 开头）
	html = html.replace(/^[*-] (.+)$/gm, '<div style="margin-left:16px;">• $1</div>')

	// 处理换行
	html = html.replace(/\n/g, '<br/>')

	// 包裹在带有换行样式的容器中
	return `<div style="word-break:break-all;overflow-wrap:break-word;white-space:pre-wrap;">${html}</div>`
}

// 发送消息
async function sendMessage() {
	const text = inputText.value.trim()
	if ((!text && selectedFiles.value.length === 0) || sending.value || isUploading.value) return

	sending.value = true
	const tempId = Date.now().toString()
	
	// 先添加临时消息到界面
	const tempMsg: ChatRoomMessageVO = {
		messageId: tempId,
		roomId: roomId.value,
		senderId: currentUserId.value,
		senderType: 'guest',
		senderName: currentUserName.value,
		content: text,
		sendTime: new Date().toISOString(),
		status: 'sending',
		files: []
	}
	messages.push(tempMsg)
	inputText.value = ''
	nextTick(() => scrollToBottom())

	try {
		// 上传文件
		const fileIds = await uploadFiles()
		
		// 调用API发送消息
		const msgDTO: TbChatRoomMessageDTO = {
			roomId: roomId.value,
			senderId: currentUserId.value,
			senderType: 'guest',
			senderName: currentUserName.value,
			messageType: 'text',
			content: text,
			files: fileIds
		}
		const res = await workcaseChatAPI.sendMessage(msgDTO)
		if (res.success && res.data) {
			// 更新临时消息为真实消息
			const idx = messages.findIndex(m => m.messageId === tempId)
			if (idx !== -1) {
				messages[idx] = { ...res.data, status: 'sent' }
			}
		} else {
			// 发送失败，标记状态
			const idx = messages.findIndex(m => m.messageId === tempId)
			if (idx !== -1) {
				messages[idx].status = 'failed'
			}
			uni.showToast({ title: res.message || '发送失败', icon: 'none' })
		}
	} catch (e) {
		console.error('发送消息失败:', e)
		const idx = messages.findIndex(m => m.messageId === tempId)
		if (idx !== -1) {
			messages[idx].status = 'failed'
		}
		uni.showToast({ title: '发送失败', icon: 'none' })
	} finally {
		sending.value = false
	}
}

// 滚动到底部
function scrollToBottom() {
	// uni-app 的 scroll-view 需要 scroll-top 值发生变化才会触发滚动
	// 先重置为 0
	scrollTop.value = 0
	// 使用 setTimeout 确保重置生效
	setTimeout(() => {
		// 使用一个足够大的值确保滚动到底部
		scrollTop.value = 999999
	}, 50)
}

// 处理工单操作
function handleWorkcaseAction() {
	console.log('[handleWorkcaseAction] 开始执行')
	console.log('[handleWorkcaseAction] workcaseId:', workcaseId.value)
	console.log('[handleWorkcaseAction] roomId:', roomId.value)
	
	if (workcaseId.value) {
		const url = `/pages/workcase/workcaseDetail/workcaseDetail?workcaseId=${workcaseId.value}`
		console.log('[handleWorkcaseAction] 查看工单，跳转URL:', url)
		uni.navigateTo({
			url: url,
			success: () => {
				console.log('[handleWorkcaseAction] 跳转成功')
			},
			fail: (err) => {
				console.error('[handleWorkcaseAction] 跳转失败:', err)
			}
		})
	} else {
		// 跳转到创建工单页面，携带 deviceCode
		const url = `/pages/workcase/workcaseDetail/workcaseDetail?mode=create&roomId=${roomId.value}&deviceCode=${encodeURIComponent(deviceCode.value || '')}`
		console.log('[handleWorkcaseAction] 创建工单，跳转URL:', url)
		uni.navigateTo({
			url: url,
			success: () => {
				console.log('[handleWorkcaseAction] 跳转成功')
			},
			fail: (err) => {
				console.error('[handleWorkcaseAction] 跳转失败:', err)
			}
		})
	}
}

// 发起会议 - 跳转到会议创建页面
function startMeeting() {
	// 跳转到会议创建页面
	const url = `/pages/meeting/meetingCreate/MeetingCreate?roomId=${roomId.value}${workcaseId.value ? '&workcaseId=' + workcaseId.value : ''}`
	console.log('[chatRoom] 跳转会议创建页面:', url)
	uni.navigateTo({
		url: url,
		fail: (err) => {
			console.error('[chatRoom] 跳转会议创建页面失败:', err)
			uni.showToast({
				title: '跳转失败',
				icon: 'none'
			})
		}
	})
}

// 加入会议（从MeetingCard点击加入）
async function handleJoinMeeting(meetingId: string) {
	console.log('[handleJoinMeeting] 开始加入会议, meetingId:', meetingId)
	try {
		// 调用加入会议接口获取会议页面URL
		const joinRes = await workcaseChatAPI.joinMeeting(meetingId)
		console.log('[handleJoinMeeting] API响应:', JSON.stringify(joinRes))

		// 兼容两种判断方式：success 字段或 code === 200
		const isSuccess = joinRes.success || joinRes.code === 200 || joinRes.code === 0
		const meetingData = joinRes.data

		if (isSuccess && meetingData && meetingData.iframeUrl) {
			const meetingPageUrl = meetingData.iframeUrl
			const meetingName = meetingData.meetingName || '视频会议'
			console.log('[handleJoinMeeting] 获取到会议页面URL:', meetingPageUrl, '会议名称:', meetingName)

			// 小程序环境：直接使用固定的HTTPS域名
			const protocol = 'https:'
			const host = 'org.xyzh.yslg'
			// 如果meetingPageUrl不包含/workcase，需要加上
			const fullPath = meetingPageUrl.startsWith('/workcase')
				? meetingPageUrl
				: '/workcase' + meetingPageUrl
			// 附加roomId参数，用于离开会议后返回聊天室
			const fullMeetingUrl = `${protocol}//${host}${fullPath}&roomId=${roomId.value}`

			console.log('[handleJoinMeeting] 完整会议URL:', fullMeetingUrl)

			// 小程序环境：显示提示，引导用户复制链接在浏览器打开
			uni.showModal({
				title: '视频会议',
				content: '微信小程序暂不支持视频会议，请复制链接在浏览器中打开',
				confirmText: '复制链接',
				cancelText: '取消',
				success: (res) => {
					if (res.confirm) {
						// 复制链接到剪贴板
						uni.setClipboardData({
							data: fullMeetingUrl,
							success: () => {
								uni.showToast({
									title: '链接已复制，请在浏览器中打开',
									icon: 'none',
									duration: 3000
								})
							},
							fail: () => {
								uni.showToast({
									title: '复制失败，请手动复制',
									icon: 'none'
								})
							}
						})
					}
				}
			})
		} else {
			console.error('[handleJoinMeeting] 加入会议失败, isSuccess:', isSuccess, 'data:', meetingData)
			uni.showToast({
				title: joinRes.message || '加入会议失败：未获取到会议地址',
				icon: 'none'
			})
		}
	} catch (error) {
		console.error('[handleJoinMeeting] 加入会议异常:', error)
		uni.showToast({
			title: '加入会议失败',
			icon: 'none'
		})
	}
}

// 处理评分提交
async function handleCommentSubmit(rating: number) {
	console.log('[handleCommentSubmit] 提交评分:', rating)
	try {
		const result = await workcaseChatAPI.submitComment(roomId.value, rating)
		if (result.success) {
			uni.showToast({
				title: '感谢您的评分！',
				icon: 'success'
			})
		} else {
			uni.showToast({
				title: result.message || '评分提交失败',
				icon: 'none'
			})
		}
	} catch (error) {
		console.error('[handleCommentSubmit] 评分提交失败:', error)
		uni.showToast({
			title: '评分提交失败，请稍后重试',
			icon: 'none'
		})
	}
}

// 文件操作相关函数

// 选择文件
async function chooseFile() {
	try {
		const res = await uni.chooseMessageFile({
			count: 9, // 最多选择9个文件
			type: 'file',
			ext: ['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'pdf', 'txt', 'jpg', 'jpeg', 'png', 'gif']
		})
		
		if (res.tempFiles && res.tempFiles.length > 0) {
			// 添加到选中文件列表
			selectedFiles.value = [...selectedFiles.value, ...res.tempFiles]
		}
	} catch (error) {
		console.error('选择文件失败:', error)
		uni.showToast({ title: '选择文件失败', icon: 'none' })
	}
}

// 删除选中的文件
function removeFile(index: number) {
	selectedFiles.value.splice(index, 1)
}

// 格式化文件大小
function formatFileSize(size: number): string {
	if (size < 1024) {
		return size + ' B'
	} else if (size < 1024 * 1024) {
		return (size / 1024).toFixed(1) + ' KB'
	} else {
		return (size / (1024 * 1024)).toFixed(1) + ' MB'
	}
}

// 批量上传文件
async function uploadFiles(): Promise<string[]> {
	const fileIds: string[] = []
	if (selectedFiles.value.length === 0) return fileIds
	
	isUploading.value = true
	uni.showLoading({ title: '上传中...' })
	try {
		// 获取文件路径数组
		const filePaths = selectedFiles.value.map(file => file.path)
		// 使用fileAPI的批量上传方法
		const result = await fileAPI.batchUploadFiles(filePaths, {
			module: 'chatroom'
		})
		
		if (result.success && result.dataList) {
			// 提取fileId数组
			fileIds.push(...result.dataList.map(file => file.fileId!))
		} else {
			throw new Error(result.message || '文件上传失败')
		}
		
		return fileIds
	} catch (error) {
		console.error('文件上传失败:', error)
		uni.showToast({ title: '文件上传失败', icon: 'none' })
		throw error
	} finally {
		isUploading.value = false
		uni.hideLoading()
		selectedFiles.value = [] // 清空选中文件列表
	}
}

// 文件下载和预览功能

// 从fileId中提取文件名
function getFileNameFromId(fileId: string): string {
	// 简化实现，实际项目中可以从fileId解析或通过API获取文件名
	return fileId.split('/').pop() || fileId
}

// 下载文件
async function downloadFile(fileId: string) {
	try {
		// 使用fileAPI获取正确的文件下载URL
		const downloadUrl = fileAPI.getDownloadUrl(fileId)
		
		// 发起下载请求
		uni.downloadFile({
			url: downloadUrl,
			header: {
				Authorization: `Bearer ${uni.getStorageSync('token') || ''}`
			},
			success: (res) => {
				if (res.statusCode === 200) {
					// 保存文件到本地
					uni.saveFile({
						filePath: res.tempFilePath,
						success: (saveRes) => {
							uni.showToast({
								title: '文件已保存',
								icon: 'success'
							})
							// 打开文件
							uni.openDocument({
								filePath: saveRes.savedFilePath,
								success: () => {
									console.log('文件打开成功')
								}
							})
						}
					})
				} else {
					uni.showToast({
						title: '文件下载失败',
						icon: 'none'
					})
				}
			},
			fail: (error) => {
				console.error('文件下载失败:', error)
				uni.showToast({
					title: '文件下载失败',
					icon: 'none'
				})
			}
		})
	} catch (error) {
		console.error('文件下载异常:', error)
		uni.showToast({
			title: '文件下载失败',
			icon: 'none'
		})
	}
}

// 返回上一页
function goBack() {
	uni.navigateBack()
}

// ==================== WebSocket连接管理 ====================

// 初始化WebSocket连接
async function initWebSocket() {
	try {
		const token = uni.getStorageSync('token') || ''
		if (!token) {
			console.warn('[chatRoom] 未找到token，跳过WebSocket连接')
			return
		}
		
		// 构建WebSocket URL
		// 开发环境：ws://localhost:8180 或 ws://192.168.x.x:8180
		// 生产环境：wss://your-domain.com
		const protocol = 'wss:' // 开发环境使用ws，生产环境改为wss
		// 小程序使用原生WebSocket端点（不是SockJS端点）
		const wsUrl = `${protocol}//${WS_HOST}/urban-lifeline/workcase/ws/chat?token=${encodeURIComponent(token)}`
		
		console.log('[chatRoom] 开始连接WebSocket')
		await wsClient.connect(wsUrl, token)
		
		// 订阅当前聊天室消息频道
		if (roomId.value) {
			wsClient.subscribe(`/topic/chat/${roomId.value}`, handleNewMessage)
			console.log('[chatRoom] WebSocket连接成功，已订阅聊天室:', roomId.value)
		}
	} catch (error) {
		console.error('[chatRoom] WebSocket连接失败:', error)
	}
}

// 断开WebSocket连接
function disconnectWebSocket() {
	try {
		if (roomId.value) {
			wsClient.unsubscribe(`/topic/chat/${roomId.value}`)
		}
		wsClient.disconnect()
		console.log('[chatRoom] WebSocket已断开')
	} catch (error) {
		console.error('[chatRoom] 断开WebSocket失败:', error)
	}
}

// 处理接收到的新消息
function handleNewMessage(message: ChatRoomMessageVO) {
	console.log('[chatRoom] 收到新消息:', message)

	// 避免重复添加自己发送的普通消息（自己发送的消息已经通过sendMessage添加到列表）
	// 但会议消息（meet类型）始终添加，因为它是系统生成的通知
	if (message.messageType !== 'meet' && message.senderId === currentUserId.value) {
		console.log('[chatRoom] 跳过自己发送的普通消息')
		return
	}

	// 检查消息是否已存在（避免重复）
	const exists = messages.some(m => m.messageId === message.messageId)
	if (exists) {
		console.log('[chatRoom] 消息已存在，跳过')
		return
	}

	// 会议消息延时处理，等待数据库事务提交
	if (message.messageType === 'meet') {
		console.log('[chatRoom] 收到会议消息，延时1秒后刷新')
		setTimeout(async () => {
			// 重新加载最新消息，确保获取到完整的会议消息数据
			await loadMessages()
		}, 1000)
		return
	}

	// 添加新消息到列表
	messages.push(message)
	nextTick(() => scrollToBottom())

	// 可以添加消息提示音或震动
	// uni.vibrateShort()
}
</script>

<style lang="scss" scoped>
@import "./chatRoom.scss";

// 文件上传相关样式
.file-preview-container {
	padding: 10px;
	background-color: #f8f8f8;
	border-radius: 8px;
	margin-bottom: 10px;
}

.file-preview-item {
	display: flex;
	flex-direction: row;
	justify-content: space-between;
	align-items: center;
	padding: 8px 12px;
	background-color: white;
	border-radius: 6px;
	margin-bottom: 8px;
	border: 1px solid #e8e8e8;
	
	&:last-child {
		margin-bottom: 0;
	}
}

.file-info {
	flex: 1;
    overflow: hidden;
    display: flex;
    flex-direction: row;
}

.file-name {
	font-size: 14px;
	color: #333;
	margin-right: 10px;
	word-break: break-all;
}

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

.file-actions {
	margin-left: 10px;
}

.file-delete {
	font-size: 12px;
	color: #ff4d4f;
	cursor: pointer;
	padding: 4px 8px;
	border-radius: 4px;
	
	&:hover {
		background-color: rgba(255, 77, 79, 0.1);
	}
}

// 输入区操作按钮
.input-row {
	display: flex;
	align-items: center;
	gap: 10px;
}

.input-actions {
	display: flex;
	gap: 10px;
}

.action-btn {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	padding: 8px;
	cursor: pointer;
	border-radius: 8px;
	
	&:hover {
		background-color: #f0f0f0;
	}
}

.action-icon {
	font-size: 20px;
	margin-bottom: 2px;
}

.action-text {
	font-size: 12px;
	color: #666;
}

// 发送按钮状态
.send-btn.disabled {
	opacity: 0.5;
	cursor: not-allowed;
}

// 消息中的文件列表
.message-files {
	margin-top: 8px;
	display: flex;
	flex-direction: row;
	gap: 8px;
}

.message-file-item {
	display: flex;
    flex-direction: row;
	align-items: center;
	padding: 8px 12px;
	background-color: rgba(255, 255, 255, 0.8);
	border-radius: 6px;
	cursor: pointer;
	transition: all 0.2s;
	
	&:hover {
		background-color: rgba(255, 255, 255, 1);
		transform: translateY(-1px);
	}
}

.message-file-item .file-icon {
	font-size: 16px;
	margin-right: 8px;
}

.message-file-item .file-name {
	font-size: 13px;
	color: #1890ff;
	word-break: break-all;
}

// 适配自己消息的文件样式
.self .message-files {
	align-items: flex-end;
}

.self .message-file-item {
	background-color: rgba(24, 144, 255, 0.1);
	
	&:hover {
		background-color: rgba(24, 144, 255, 0.2);
	}
}

// 适配对方消息的文件样式
.other .message-files {
	align-items: flex-start;
}

.other .message-file-item {
	background-color: rgba(255, 255, 255, 0.8);
	
	&:hover {
		background-color: rgba(255, 255, 255, 1);
	}
}
</style>