<script setup>
/**
 * 聊天页面
 */
// 腾讯云聊天
import TencentCloudChat from '@tencentcloud/chat';
import {
	ref,
	reactive,
	nextTick,
	onUnmounted,
	onMounted,
	computed,
	getCurrentInstance,
	watch,
} from 'vue'
// api
import api from '@/api/index.js'
// 工具库
import util from '@/common/js/util.js'
import {
	onLoad,
	onReady,
	onPageScroll,
	onUnload
} from "@dcloudio/uni-app"

// 单条消息
import newsTemplate from './components/news-temp'
// 表情
import emoji from './emoji.vue'
// 语音条
import JyVoice from './jy-voice.vue'
// 加号菜单
import JyPlus from './jy-plus.vue'

import {
	useStore
} from 'vuex'
const {
	proxy
} = getCurrentInstance()
const store = useStore()

// 聊天对象
const msg = reactive({
	// 聊天对象
	id: '',
	// 聊天类型 C2C单聊 GROUP群聊
	type: '',
	// 群人数 
	num: '',
	// 是否客服聊天
	isCustomer: false,
})
// 输入的内容
const content = ref('')
// 加载
const loading = ref(false)
// 用户信息
const userinfo = computed(() => {
	let result = store.state.userinfo
	return result
})
// 列表数据
const list = reactive({
	// 列表条数
	limit: 20,
	//显示的数据
	data: [],
	// 
	total: 0,
})
// 滚动条位置
const top = ref(0)
// 工具条的高度
const toolHeight = ref(0)
// 当前操作的元素
const messageItem = ref({})
// 工具栏状态 voice录音 input输入框 emoji表情 plus加号菜单
const toolStatus = ref('input')
// video路径
const videoUrl = ref('')
// 视频上下文
const videoContext = ref(null)
// 红包对象
const redPacket = reactive({})

onLoad(option => {
	// 标题
	let title = ''
	// 聊天类型
	if (option.type) msg.type = option.type
	// 标题
	if (option.name) title = option.name
	// 用户id
	if (option.msgId) msg.id = option.msgId
	// 如果是群组
	if (option.type == 'GROUP') {
		msg.num = option.num
		title = `(${option.num})${option.name}`
	}
	// 标题
	if (title) uni.setNavigationBarTitle({
		title,
	})
	// 是否客服
	if (option.isCustomer) msg.isCustomer = option.isCustomer

	// 开启消息监听
	addListener()
	// 获取历史消息
	getHistory({
		callback: scrollToBottom
	})
	// #ifdef APP
	uni.onKeyboardHeightChange((rs) => {
		ghostBox.value.height = rs.height + 'px'
		nextTick(() => {
			scrollToBottom()
		})
	})
	// #endif
})

onReady(() => {
	uni.createSelectorQuery().in(proxy).select('#tool').boundingClientRect((rect) => {
		toolHeight.value = rect.height
	}).exec();
	// 
	videoContext.value = uni.createVideoContext('video')
})

onPageScroll((ev) => {
	onContentScroll(ev)
})

onUnload(() => {
	// #ifdef APP
	uni.offKeyboardHeightChange(() => { })
	// #endif
	videoContext.value.stop()
})

// 开启监听消息
function addListener() {
	let onMessageReceived = function (event) {
		console.log('TencentCloudChat.EVENT.MESSAGE_RECEIVED', event)
		setTimeout(() => {
			// 获取历史记录
			getHistory({
				msgId: '',
				limit: 1,
			})
		}, 200)
	}

	// #ifdef APP
	uni.$chat.on(TencentCloudChat.EVENT.MESSAGE_RECEIVED, onMessageReceived);
	// #endif
}

// 监听内容滚动
function onContentScroll(ev) {
	if (ev.scrollTop == 50) getMoreHistroy()
	debounce(() => {
		top.value = ev.detail.scrollTop
	})
}

// 点击发送
function handleSend() {
	// 发送消息
	sendMsg({
		query: {
			formId: userinfo.value.id,
			toUserId: msg.id,
			msgType: TencentCloudChat.TYPES.MSG_TEXT,
		},
		data: {
			text: content.value
		},
		success: () => {
			// 清空已发送的消息
			content.value = ''
		}
	})
}

/**
 * 加号菜单发送
 * @param {Object} message 消息对象
 */
function handlePlusSend(message) {
	sendMsg(message)
}

/**
 * 发送消息
 * @param {Object} param
 */
function sendMsg(param) {
	// 
	let request = api.news.sendUserMsg
	// 
	if (msg.type == 'GROUP') request = api.news.sendGroupMsg
	// if (msg.isCustomer) request = api.news.sendCusomterService

	// 发送消息
	request({
		query: param.query,
		data: param.data,
	}).then((rs) => {
		if (rs.code == 200) {
			getHistory({
				msgId: '',
				limit: 1,
			})
			param.success ? param.success() : ''
			return
		}
		util.alert({
			content: rs.msg,
			showCancel: false,
		})
	}).catch((rs) => {
		console.log('sendMsg error:', rs);
	})
}

/**
 * 打开红包详情
 * @param {Object} ev
 */
function handleRedPacket(ev) {
	messageItem.value = ev
	api.news.getRedPacketInfo({
		query: {
			// 红包id
			redPacketId: ev.callbackData.callback_json[0].businessId
		}
	}).then(rs => {
		if (rs.code == 200) {
			proxy.$refs.RedPacketRef.open()
			Object.assign(redPacket, rs.data)
			return
		}
		util.alert({
			content: rs.msg,
			showCancel: false,
		})
	})
}

// 领取红包
function handleOpenReadPacket() {
	// 如果不能领取
	if (redPacket.redStatus == false) return
	// 红包过期
	// if (redPacket.isStale == 1) return


	// 抢红包
	api.news.getRedPacket({
		query: {
			// 红包id
			redPacketId: redPacket.id,
			// 领取人id
			userId: userinfo.value.id,
			// 群聊类型
			sendType: {
				'C2C': '1',
				'GROUP': '2',
			}[msg.type],
		}
	}).then(rs => {
		if (rs.code == 200) {
			// 修改领取状态
			redPacket.redStatus = false
			// 获取金额
			redPacket.amount = rs.data
			return
		}
		util.alert({
			content: rs.msg,
			showCancel: false,
		})
	})
}

// 选择的emoji
function emojiTap(val) {
	content.value = content.value + val
}

// 点击工具栏
function handleTool(val) {
	if (toolStatus.value === val) {
		toolStatus.value = 'input'
		return
	}
}

// 获取更多消息记录
function getMoreHistroy() {
	// 获取第一条消息记录
	if (list.total <= list.data.length) return
	getHistory({
		msgId: list.data[0].id
	})
}

/**
 * 获取历史记录
 * @param {Object} param
 */
function getHistory(param = {}) {
	// 验证sdk是否准备完毕
	// #ifdef APP
	let isReady = uni.$chat.isReady();
	if (!isReady && userinfo.value.id) {
		setTimeout(function () {
			getHistory()
		}, 200);
		return
	}
	// #endif 
	loading.value = true

	// 获取单聊聊天记录
	let request = api.news.getUserMsgHistory
	// 如果是群聊 获取群聊聊天记录
	if (msg.type == 'GROUP') request = api.news.getGroupMsgHistory

	// 获取历史记录
	request({
		query: {
			msgId: param.msgId || '',
			fromId: userinfo.value.id,
			toId: msg.id,
			groupId: msg.id,
			limit: param.limit || list.limit,
		},
	}).then(res => {
		if (res.code === 200) {
			// 结果
			const result = res.data
			// 头像路径
			list.faceUrl = result.faceUrl

			// 如果是最新消息
			if (param.limit == 1) {
				list.data.push(...result.list.map(item => {
					item.callbackData = JSON.parse(item.callbackJson)
					return item
				}))
			} else {
				// 追加
				list.data.unshift(...result.list.map(item => {
					item.callbackData = JSON.parse(item.callbackJson)
					return item
				}))
			}
			console.log('getHostory', list.data)
			// 总数
			list.total = result.total
			nextTick(() => {
				param.callback && param.callback()
			})
			return
		}
		util.alert({
			content: res.msg,
			showCancel: false,
		})
	}).catch(rs => {
		console.log('err', rs)
	}).finally(() => {
		loading.value = false
	})
}

// 滚动至底部
function scrollToBottom() {
	uni.createSelectorQuery().in(proxy).select('#scroll-content').boundingClientRect((res) => {
		top.value = res.height

		uni.pageScrollTo({
			scrollTop: top.value,
			duration: 0
		})
		// console.log('top.value', top.value)
	}).exec();
}

// 防抖
function debounce(func, wait = 500) {
	let timeout = null;
	return function (...args) {
		clearTimeout(timeout)
		timeout = setTimeout(() => {
			func.apply(this, args)
		}, wait);
	}
}

// 输入框聚焦
function onFocus() {
	handleTool('input')
}

// 输入语音
function voiceSend(message) {
	console.log('handlePlusSend', message)
	sendMsg({
		message,
	})
}

// 监听滚动
const handleScroll = (e) => {
	if (e.detail.scrollTop === 0) {
		getHistory()
	}
}

// 撑起键盘的高度 打开该元素
const showGhost = ref(false)
// 给元素加高度
const ghostBox = ref({
	height: '0px',
	duration: '0.25s'
})

// 监听键盘高度变化 
function keyboardheightchange(res) {
	ghostBox.value = res.detail
	nextTick(() => {
		showGhost.value = res.detail.height > 0 ? true : false
	})
}

/**
 * 看视频
 * @param {Object} item 聊天消息对象
 */
function handleViewVideo(item) {
	videoUrl.value = item.payload.videoUrl
	// 进入全屏
	videoContext.value.requestFullScreen()
}

// 监听视频是否全屏
function onScreenChange(ev) {
	console.log('onScreenChange', ev)
	if (!ev.fullScreen) videoContext.value.pause()
}
</script>

<template>
	<view class="app">
		<scroll-view class="scroll-view" scroll-y :scroll-with-animation="true" :scroll-top="top"
			@scroll="onContentScroll" @scrolltoupper="getMoreHistroy">
			<view id="scroll-content" style="padding: 30rpx 30rpx">
				<view v-for="(item, index) in list.data" :key="index">
					<!-- 普通消息 -->
					<view class="message"
						:class="[(item.From_Account || item.fromId) == userinfo.id ? 'self' : 'friend']">
						<template v-if="msg.type == 'C2C'">
							<!-- 如果是我自己 -->
							<template v-if="(item.From_Account || item.fromId) == userinfo.id">
								<image :src="userinfo.avatar" class="avatar wh80" mode="aspectFill" />
							</template>
							<template v-else>
								<image :src="list.faceUrl" class="avatar wh80" mode="aspectFill" />
							</template>
						</template>
						<template v-else>
							<image :src="item.fromFaceUrl" class="avatar wh80" mode="aspectFill" />
						</template>

						<view class="df fdc mlr20">
							<!-- 昵称 -->
							<view class="df fdc" v-if="item.from != userinfo.userId">
								<view class="name">{{ item.callbackData.from_name }}</view>
							</view>
							<!-- 消息 -->
							<newsTemplate :item="item" :msg="msg" @openRedBag="handleRedPacket"
								@viewVideo="handleViewVideo" />
						</view>
					</view>
				</view>
				<view v-if="showGhost" :style="{ height: `${ghostBox.height}px`, transition: `${ghostBox.duration}s` }">
				</view>
				<view class="ghost" :style="{ height: toolHeight + 'px' }"></view>
			</view>
		</scroll-view>
	</view>

	<view class="tool" id="tool">
		<view class="tool-group" style="background: #F6F6F6;">
			<!-- 语音 -->
			<image src="/static/news-voice.png" mode="widthFix" class="thumb" @click="handleTool('voice')"></image>
			<!-- 摁住说话 -->
			<template v-if="toolStatus == 'voice'">
				<JyVoice @send="voiceSend" :msg="msg" />
			</template>
			<!-- 输入框 -->
			<template v-if="toolStatus != 'voice'">
				<uni-easyinput @focus="onFocus" type="text" v-model="content" :clearable="false" class="input"
					:adjust-position="false" @keyboardheightchange="keyboardheightchange" placeholder="请输入你的问题"
					confirmType="发送" />
			</template>
			<!-- 表情 -->
			<image src="/static/news-emoji.png" mode="widthFix" class="thumb" @click="handleTool('emoji')"></image>
			<!-- 加号 -->
			<template v-if="!content">
				<image src="/static/news-plus.png" mode="widthFix" class="thumb" @click="handleTool('plus')" />
			</template>
			<!-- 文本发送按钮 -->
			<template v-else>
				<view class="send" @click="handleSend">发送</view>
			</template>
		</view>
		<view v-if="showGhost" :style="{ height: `${ghostBox.height}px`, transition: `${ghostBox.duration}s` }"></view>
		<!-- 表情 -->
		<template v-if="toolStatus == 'emoji'">
			<emoji @setEmoj="emojiTap"></emoji>
		</template>
		<!-- 加号 -->
		<template v-if="toolStatus == 'plus'">
			<JyPlus @send="handlePlusSend" :msg="msg"></JyPlus>
		</template>
	</view>

	<!-- 视频 -->
	<video :src="videoUrl" id="video" @fullscreenchange="onScreenChange" />

	<!-- 红包封面 -->
	<uni-popup ref="RedPacketRef" type="center">
		<view class="red-bag br20" @touchmove.stop.prevent="">
			<view class="rbag_top">
				<view class="user fmid">
					<view class="avatar">
						<image class="wh80 cir" :src="redPacket.fromUrl" mode="scaleToFill" />
					</view>
					<view class="ml15 f32">{{ redPacket.fromName }}的红包</view>
				</view>
				<view class="app_name mt15 mlr30 tac f40">{{ redPacket.blessing }}</view>
				<!--  -->
				<view class="cfff f32 tac mt50" v-if="redPacket.isStale == 1">红包已过期</view>
				<view class="cfff f32 tac mt50" v-else-if="redPacket.remainingCount == 0">来晚啦，红包已被抢完</view>

				<!-- redPacket.redStatus true可以领取 false不可领取 -->
				<view class="amount f32" v-if="!redPacket.redStatus">
					<text class="">已领取</text>
					<text class="value">{{ redPacket.amount }}</text>
					<text class="unit" v-if="redPacket.payType == 1">余额</text>
					<text class="unit" v-else-if="redPacket.payType == 2">积分</text>
				</view>
			</view>

			<view class="open_rbag_btn pr fmid" @click="handleOpenReadPacket">
				<text v-if="redPacket.amount">已</text>
				<text>开</text>
			</view>
		</view>

		<view class="tac mt35" @click.stop="$refs.RedPacketRef.close()">
			<uni-icons type="close" color="#fbd977" size="32" />
		</view>
	</uni-popup>
</template>


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

// 
#video {
	position: fixed;
	top: 100%;
	left: 0;
}

// 
.red-bag {
	position: relative;
	width: 528rpx;
	height: 60vh;
	color: #ECCD97;
	background-color: #e0534a;
	box-shadow: 0 0 20rpx #00000033;

	.rbag_top {
		padding-top: 60rpx;
		height: 70%;
		background-color: #e0534a;
		border-radius: 0 0 500rpx 500rpx / 0 0 200rpx 200rpx;
		box-shadow: 0 5rpx 5rpx rgba(0, 0, 0, 0.2);

		.amount {
			margin-top: 120rpx;
			text-align: center;
			letter-spacing: 1rpx;

			.value {
				font-size: 60rpx;
				font-weight: bold;
			}
		}
	}

	.open_rbag_btn {
		width: 180rpx;
		height: 180rpx;
		margin: -90rpx auto 0;
		color: #fef5e8;
		font-size: 74rpx;
		font-weight: bold;
		background-color: #ffd287;
		box-shadow: 2rpx 2rpx 6rpx rgba(0, 0, 0, 0.2);
		border-radius: 50%;
		z-index: 1;
	}

	// 打开红包
	.open_rbag_model {
		position: fixed;
		top: 0;
		left: 0;
		width: 100%;
		height: 100vh;
		background-color: rgba(0, 0, 0, 0.3);
		z-index: 1000;

		.rbag_conbg {
			position: absolute;
			top: 0;
			left: 0;
			right: 0;
			bottom: 0;
			width: 80%;
			height: 840rpx;
			margin: auto;
			z-index: 1001;
		}

		.open_rbag_con {
			z-index: 1002;

			.open_title {
				height: 120rpx;
				line-height: 120rpx;
				text-align: center;
				font-size: 38rpx;
				letter-spacing: 2rpx;
				color: #e46965;
			}

			.rbag_detail {
				margin-top: 90rpx;

				.open_money {
					text-align: center;
					font-size: 80rpx;
					color: #c95948;
					font-weight: bold;
					display: flex;
					justify-content: center;

					.danwei {
						font-size: 30rpx;
						margin-left: 16rpx;
						margin-top: 24rpx;
					}
				}

				.open_tips {
					text-align: center;
					font-size: 30rpx;
					color: #d26762;
					margin-top: 30rpx;
				}
			}

			.lookbag_box {
				margin-top: 300rpx;
				display: flex;
				justify-content: center;

				.lookbag_btn {
					width: 70%;
					height: 90rpx;
					line-height: 90rpx;
					text-align: center;
					font-size: 32rpx;
					color: #c95948;
					letter-spacing: 2rpx;
					background-color: #ffd356;
					border-radius: 50rpx;
					box-shadow: 0rpx 0rpx 4rpx rgba(0, 0, 0, 0.2);
				}
			}

			.hide_btn {
				position: absolute;
				bottom: -110rpx;
				left: 0;
				right: 0;
				width: 80rpx;
				height: 80rpx;
				line-height: 80rpx;
				text-align: center;
				margin: 0 auto;
			}
		}
	}
}
</style>