<template>
	<view class="chat-container">
		<u-navbar title="聊天" id="navBarId" :background="{background: 'transparent' }" :border-bottom="false"
			back-icon-color="#000" title-color="#000">
			<template v-slot:right>
				<image class="collection" src="/static/icon/Bookmark.png" mode=""></image>
			</template>
		</u-navbar>

		<view class="bottom-view" id="bottomId">
			<!-- 麦克风/文本切换 -->
			<view class="icon u-m-r-10" @click="handleChangeMic">
				<image src="/static/icon/Mic.png" mode="" style="width: 100%;height: 100%;"></image>
			</view>
			<textarea v-if="!showMic" name="" v-model="text" class="text" maxlength="3000"></textarea>
			<u-button v-else class="btn-mic" @click="handleSay">点击说话</u-button>
			<!-- 表情包 -->
			<view v-show="text==null || text==''" class="icon u-m-r-10 u-m-l-10">
				<image src="/static/icon/expression.png" mode="" style="width: 100%;height: 100%;"></image>
			</view>
			<!-- 文本域展开 -->
			<view v-show="text!=null && text!=''" class="icon u-m-r-10 u-m-l-10" @click="handleMagnify">
				<image src="/static/icon/big.png" mode="" style="width: 100%;height: 100%;"></image>
			</view>
			<!-- 相机 -->
			<view v-show="text==null || text==''" class="icon" @click="handleCamera">
				<image src="/static/icon/Camera.png" mode="" style="width: 100%;height: 100%;"></image>
			</view>
			<!-- 文本发送 -->
			<view v-show="text!=null && text!=''" class="icon u-m-r-10 u-m-l-10" @click="handleSendText">
				<image src="/static/icon/send.png" mode="" style="width: 100%;height: 100%;"></image>
			</view>
		</view>
		<scroll-view :style="'height:'+scrollHeight+'px'" scroll-y="true" class="scroll-main" :scroll-top="scrollTop"
			:scroll-with-animation="true">
			<view id="scroll-main">
				<view v-for="(item, index) in dataList">
					<view v-if="item.createId==userId" class="my-message">
						<view class="msg-main">
							<view class="msg-content" v-if="item.type=='text'">
								<view class="text">
									{{item.content}}
								</view>
							</view>
							<view class="mp3-content" v-if="item.type=='mp3'">
								<view class="mp3" @click="handlePlayMp3(item.content)">
									<view class="mp3-icon">
										<image style="width: 100%;height: 100%;" src="/static/icon/listen.png" mode="">
										</image>
									</view>
									点击播放
								</view>
							</view>
							<view class="img-content" v-if="item.type=='img'">
								<u-image @click="handlePreView(item.content)" height="100%" :src="item.content"
									:lazy-load="true" mode="heightFix"></u-image>
							</view>
							<!-- 头像 -->
							<view class="msg-avatar">
								<image style="width: 100%;height: 100%;" :src="getImageUrl(item.userInfo.avatar)"
									mode="">
								</image>
							</view>
						</view>
					</view>
					<view v-else class="other-message">
						<view class="msg-main">
							<view class="msg-avatar">
								<image style="width: 100%;height: 100%;" :src="getImageUrl(item.userInfo.avatar)"
									mode="">
								</image>
							</view>
							<view class="msg-content">
								<view class="text">
									{{item.content}}
								</view>
							</view>
						</view>
					</view>
				</view>
			</view>
		</scroll-view>
		<u-popup v-model="showLongText" mode="bottom" height="80%">
			<view class="long-text">
				<u-input v-model="text" type="textarea" maxlength="3000" />
			</view>
		</u-popup>


		<u-mask :show="showMask" @click="handleStopMic" blur="10">
			<view class="mask-warp">
				<view class="mask-text">
					<template v-if="!showMaskBtn">
						正在说话...点击结束
					</template>
					<template v-else>
						<u-image :fade="false" width="50" height="50"
							:src="isPlayRecord?'/static/icon/record_ing.png':'/static/icon/record_play.png'"
							:show-loading="false"></u-image>{{isPlayRecord?'播放中...':'点击播放录音'}}
					</template>
				</view>
				<view v-if="showMaskBtn" class="mask-btn">
					<u-button class="btn" @click.stop="handleCancel">取消</u-button>
					<u-button class="btn" @click.stop="handleSendMp3">发送</u-button>
				</view>
			</view>
		</u-mask>


		<u-mask :show="showPreMask" @click="showPreMask=false" blur="10">
			<u-image width="100%" class="mask-pre-img" :src="preImg" :lazy-load="true" mode="aspectFit"></u-image>
		</u-mask>

		<u-toast ref="msgToast" duration="6000" />

	</view>
</template>

<script setup lang="ts">
	import { onMounted, ref, getCurrentInstance, onBeforeMount, nextTick } from 'vue';
	import {
		onLoad, onLaunch
	} from "@dcloudio/uni-app";
	import io from '@hyoga/uni-socket.io';
	import { getImageUrl } from '../../util/common';
	import { permissionUtil } from '@/uni_modules/colorful-uni-perm';

	const navBarRef = ref()
	const instance = getCurrentInstance();
	const scrollHeight = ref(0)
	const loadHeight = () => {
		uni.getSystemInfo({
			success(res) {
				let screenHeight = res.screenHeight
				uni.createSelectorQuery().in(instance.proxy).select("#navBarId").boundingClientRect((data : any) => {
					scrollHeight.value = screenHeight - data.height
				}).exec()
				uni.createSelectorQuery().in(instance.proxy).select("#bottomId").boundingClientRect((data : any) => {
					scrollHeight.value = scrollHeight.value - data.height
				}).exec()
			}
		})
	}

	const dataList = ref([])

	const mockData = () => {
		for (var i = 0; i < 5; i++) {
			if (i % 2 == 0) {
				dataList.value.push({
					"createId": 3641,
					"groupId": "1",
					"content": "即使在没有空格的地方也	",
					"type": "text",
					"messageId": 44,
					"createTime": "2025-09-27T18:32:42.000Z",
					"userInfo": {
						"id": 9958,
						"username": "15867461647",
						"userType": "user",
						"isSystemAccount": 0,
						"avatar": "/uploads/documents/1753833656669_524106424.jpg"
					}
				})
			} else {
				dataList.value.push({
					"createId": 9955,
					"groupId": "1",
					"content": "2222",
					"type": "text",
					"messageId": 44,
					"createTime": "2025-09-27T18:32:42.000Z",
					"userInfo": {
						"id": 9958,
						"username": "15867461647",
						"userType": "user",
						"isSystemAccount": 0,
						"avatar": "/uploads/documents/1753833656669_524106424.jpg"
					}
				})
			}

			dataList.value.push(
				{
					"createId": 3641,
					"groupId": "5",
					"content": "http://114.55.111.44:9000/jurongquan/app_records/1759049412254.mp3",
					"type": "mp3",
					"messageId": 56,
					"createTime": "2025-09-28T00:50:16.000Z",
					"userInfo": {
						"id": 3641,
						"username": "15867461617",
						"userType": "agent",
						"isSystemAccount": 0,
						"avatar": "/uploads/documents/1753833656669_524106424.jpg"
					}
				})

			dataList.value.push(
				{
					"createId": 3641,
					"groupId": "5",
					"content": "http://114.55.111.44:9000/jurongquan/app_records/1759110192420_Screenshot_20250929_084636_com.bilibili.star.bili.jpg",
					"type": "img",
					"messageId": 62,
					"createTime": "2025-09-28T17:43:13.000Z",
					"userInfo": {
						"id": 3641,
						"username": "15867461617",
						"userType": "agent",
						"isSystemAccount": 0,
						"avatar": "/uploads/documents/1753833656669_524106424.jpg"
					}
				})
		}
	}

	// 发送消息
	const text = ref('')
	const showLongText = ref(false)

	const handleSendText = () => {
		uni.hideKeyboard()
		socket.value.emit('clientMsg', {
			createId: userId.value,
			groupId: groupId.value,
			content: text.value,
			type: "text"
		})
		text.value = ''
	}

	// 文本放大
	const handleMagnify = () => {
		showLongText.value = true
	}

	// 录音
	const showMic = ref(false)
	const showMask = ref(false)
	const showMaskBtn = ref(false)

	const msgToast = ref(null)

	const voicePath = ref('')

	const recorderManager = uni.getRecorderManager(); // 录音管理器
	const innerAudioContext = uni.createInnerAudioContext(); // 音频管理器
	const options = {
		duration: 60000, // 录音时长，单位为毫秒
		sampleRate: 44100, // 采样率
		numberOfChannels: 2, // 通道数
		format: 'mp3', // 音频格式
	};
	const isPlayRecord = ref(false)

	// 选择麦克风
	const handleChangeMic = () => {
		showMic.value = !showMic.value
	}

	// 开始录音
	const handleSay = () => {
		permissionUtil.requestAndroidPermission('android.permission.RECORD_AUDIO').then((status) => {
			// status 为 1 表示用户已授权，0 表示用户已拒绝， -1 表示用户永久拒绝
			console.log('权限申请结果：', status);
			if (status == -1) {
				msgErrorRcord()
			} else if (status == 1) {
				// start方法无法被及时调用的处理方法
				while (!showMask.value) {
					recorderManager.start(options);
					recorderManager.onStart(() => {
						console.log('录音开始');
						showMask.value = true
					});
				}
			} else if (status == 0) {
				msgErrorRcord()
			}
		});
	}

	const msgErrorRcord = () => {
		msgToast.value.show({
			title: '请确认您的麦克风权限是否开启',
			type: 'error'
		})
	}

	// 停止录音
	const handleStopMic = () => {
		showMaskBtn.value = true
		if (voicePath.value) {
			isPlayRecord.value = true
			innerAudioContext.src = voicePath.value
			innerAudioContext.play();
			innerAudioContext.onEnded(() => {
				isPlayRecord.value = false
			})
		} else {
			recorderManager.stop()
			// showMask.value = false
			recorderManager.onStop(function (res) {
				console.log('recorder stop' + JSON.stringify(res));
				voicePath.value = res.tempFilePath;
			});
		}
	}

	// 取消发送录音
	const handleCancel = () => {
		showMask.value = false
		showMaskBtn.value = false
		voicePath.value = ''
		innerAudioContext.stop()
	}

	// 发送录音文件
	const handleSendMp3 = () => {
		innerAudioContext.stop()
		const token = uni.getStorageSync("token")
		uni.uploadFile({
			// url: 'http://192.168.0.4:3005/upload',
			url: 'http://192.168.0.15:3007/upload/file',
			filePath: voicePath.value,
			header: {
				"Authorization": "Bearer " + token
			},
			name: "file",
			success: (uploadFileRes) => {
				let result = JSON.parse(uploadFileRes.data)
				if (result.data.fileUrl) {
					// 上传文件成功，添加消息记录
					socket.value.emit('clientMsg', {
						createId: userId.value,
						groupId: groupId.value,
						content: result.data.fileUrl,
						type: "mp3"
					})
					showMask.value = false
					showMaskBtn.value = false
					voicePath.value = ''
				}
			},
			fail: (res) => {
				console.log(JSON.stringify(res));
			}
		})
	}

	// 打开相册
	const handleCamera = () => {
		permissionUtil.requestAndroidPermission('android.permission.READ_EXTERNAL_STORAGE').then((status) => {
			console.log('相册权限申请结果：', status);
			if (status == -1) {
				// 弹窗提示开启权限
				msgToast.value.show({
					title: '您已关闭读取相册权限，请在设置开启应用相册权限',
					type: 'warning'
				})
			} else if (status == 1) {
				uni.chooseImage({
					count: 10, //默认9
					sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图，默认二者都有
					sourceType: ['album'], //从相册选择
					success: function (res) {
						uploadImages(res.tempFilePaths)
					}
				});
			}
		})
	}

	// 上传图片
	const uploadImages = (imgList : any) => {
		const token = uni.getStorageSync("token")
		imgList.forEach((item : string) => {
			uni.uploadFile({
				// url: 'http://192.168.0.4:3005/upload',
				url: 'http://192.168.0.15:3007/upload/file',
				filePath: item,
				header: {
					"Authorization": "Bearer " + token
				},
				name: "file",
				success: (uploadFileRes) => {
					let result = JSON.parse(uploadFileRes.data)
					if (result.data.fileUrl) {
						// 上传文件成功，添加消息记录
						socket.value.emit('clientMsg', {
							createId: userId.value,
							groupId: groupId.value,
							content: result.data.fileUrl,
							type: "img"
						})
					}
				},
				fail: (res) => {
					console.log(res);
				}
			})
		})
	}


	// 图片预览
	const showPreMask = ref(false)
	const preImg = ref('')

	const handlePreView = (value) => {
		preImg.value = value
		showPreMask.value = true
	}

	const playError = () => {
		msgToast.value.show({
			title: '音频错误，无法播放',
			type: 'error'
		})
	}

	// 播放录音
	const handlePlayMp3 = (value) => {
		innerAudioContext.src = value
		innerAudioContext.play()
		innerAudioContext.onPlay(() => {
			// 正在播放录音
		});
		innerAudioContext.onError((res) => {
			playError()
		});
	}

	const groupId = ref()
	const userId = ref()

	onLoad((val) => {
		groupId.value = val.groupId
	});

	const socket = ref()

	// 通信连接
	const connection = () => {
		socket.value = io('http://192.168.0.15:3007', {
			query: {},
			transports: ['websocket', 'polling'],
			timeout: 5000,
		});
		socket.value.on('connect', async () => {
			console.log("连接成功");
		})
		socket.value.emit('addGroup', {
			groupId: groupId.value,
		})
		socket.value.on('serverMsg', async (message:any) => {
			dataList.value.push(message)
			// console.log(dataList.value);
			setTimeout(()=>{
				scrollToBottom()
			}, 500)
		})
	}

	const scrollTop = ref(0)

	const scrollToBottom = () => {
		uni.createSelectorQuery().in(this).select("#scroll-main").boundingClientRect((res : any) => {
			let top = res.height - scrollHeight.value;
			if (top > 0) {
				scrollTop.value = top;
			}
		}).exec()
	}

	const loadData = () => {
		userId.value = uni.getStorageSync("user").id
	}

	onMounted(() => {
		// mockData()
		loadData()

		loadHeight()
		connection()
	})
</script>

<style scoped lang="scss">
	.chat-container {
		width: 100%;
		height: 100vh;
		background: linear-gradient(180deg, #E3E8FF 0%, #FFFFFF 100%);
		background-blend-mode: lighten;


		.collection {
			width: 48rpx;
			height: 48rpx;
			margin-right: 24rpx;
		}

		.bottom-view {
			width: 100%;
			height: 100rpx;
			// background-color: #aaffff;
			position: absolute;
			bottom: 0;
			display: flex;
			align-items: center;
			padding: 10rpx;

			.icon {
				width: 60rpx;
				height: 60rpx;
			}

			.text {
				flex: 1;
				height: 96%;
				border: 2rpx solid #DEEFFF;
				border-radius: 10rpx;
				padding: 0 10rpx;
			}

			.btn-mic {
				flex: 1;
				width: 100%;
				height: 100%;
			}
		}

		.scroll-main {
			.my-message {
				text-align: right;
				margin-bottom: 20rpx;

				.msg-main {
					display: flex;
					justify-content: flex-end;
					padding: 0 10rpx;

					.msg-content {
						// background-color: #00ffff;
						padding: 2rpx;
						width: 70%;
						margin-right: 10rpx;
						// border: 1rpx solid #c7c7c7;
						box-sizing: content-box;

						.text {
							overflow-wrap: break-word;
							text-align: right;
						}
					}

					.mp3-content {
						padding: 2rpx;
						// width: 70%;
						margin-right: 10rpx;
						box-sizing: content-box;


						.mp3 {
							display: flex;
							// border: 1rpx solid #000;
							padding: 15rpx 10rpx;
							background-color: #55ff7f;
							justify-content: flex-end;
							align-items: center;

							.mp3-icon {
								margin: 0 10rpx;
								width: 25rpx;
								height: 25rpx;
							}
						}
					}

					.img-content {
						margin-right: 10rpx;
						height: 200rpx;
					}

					.msg-avatar {
						width: 80rpx;
						height: 80rpx;
					}
				}
			}

			.other-message {
				margin-bottom: 20rpx;

				.msg-main {
					display: flex;
					justify-content: flex-start;
					padding: 0 10rpx;

					.msg-content {
						// background-color: #00ffff;
						padding: 2rpx;
						width: 70%;
						// border: 1rpx solid #c7c7c7;
						box-sizing: content-box;

						.text {
							overflow-wrap: break-word;
							text-align: left;
						}
					}

					.msg-avatar {
						width: 80rpx;
						height: 80rpx;
						margin-right: 10rpx;
					}
				}
			}
		}

		.long-text {
			padding: 40rpx 20rpx;
		}

		.mask-warp {
			display: flex;
			align-items: center;
			justify-content: center;
			height: 100%;

			.mask-text {
				font-size: 36rpx;
				color: #fff;
				display: flex;
				align-items: center;
			}

			.mask-btn {
				position: absolute;
				bottom: 0;
				width: 100%;
				height: 80rpx;
				display: flex;

				.btn {
					width: 50%;
				}
			}
		}

		// 图片预览
		.mask-pre-img {
			position: absolute;
			top: 0;
			bottom: 0;
		}
	}
</style>