<template>
	<scroll-view scroll-y="true" class="scan-wrapper" v-if="isShowPage">
		<view class="scan-code-points" :style="{ backgroundImage: 'url(' + imgInfo.scanBackgroundImg + ')' }">
			<view class="button-box" v-if="!isShowCameraDelayed">
				<!-- 开始扫码按钮 -->
				<button  class="begin-btn" @click="handleBeginScan">扫一扫</button>
				<!-- 手动输入积分码 -->
				<view class="write-btn" @click="setCodePop(true)">手动输入积分码</view>
			</view>
			<!-- 左上角返回首页 -->
			<image v-if="!isShowCameraDelayed" :src="imgInfo.scanHomeImg" class="close-scan-code"  :style="{ top: (heightPool.statusTip + 10) + 'PX' }" @click="goHome"/>
			<image v-else :src="imgInfo.scanCloseImg" class="close-scan-code"  :style="{ top: (heightPool.statusTip + 10) + 'PX' }" @click="closeScanCode"/>
			<!-- 摄像头组件 -->
			<camera v-if="isShowCamera"
				class="scan-code-camera" 
				frame-size="medium" 
				mode="scanCode" 
				resolution="low" 
				device-position="back" 
				@error="errorHandle" 
				@scancode="scancodeHandle" 
				@initdone="initdone"
			/>
			<!-- 扫码帮助区域 -->
			<view class="camera-group" v-if="isShowCameraDelayed" >
				<view class="tip-bottom"  :style="{ 'height': applyEntrance ? '520rpx' : '420rpx' }">
					<view class="title">无法扫码？可尝试下列几种方法！</view>
					<view class="img-group">
						<image :src="imgInfo.scanCodeOneImg" class="img" />
						<image :src="imgInfo.scanCodeTwoImg" class="img" />
						<image :src="imgInfo.scanCodeThreeImg" class="img" />
						<image :src="imgInfo.scanCodeFourImg" class="img" />
					</view>
					<!-- 申请入口 -->
					<view class="apply" v-if="applyEntrance">
						<view>二维码无法识别？可申请数字积分码！</view>
						<view class="apply-button" @click="handleApply">立即申请</view>
					</view>
				</view>
			</view>
			<!-- 隐藏画布用于图片处理 -->
			<canvas id="myCanvas" canvas-id="myCanvas" class="my-canvas"></canvas>
			<!-- 手动输入弹窗 -->
			<view class="point-mask" v-if="showCodePop">
				<view class="mask-box" :class="{'modal-enter': showCodePop}">
					<input id="integral_number" v-model="pointCode" maxlength="20" placeholder="请输入需要添加的积分码，20位纯数字" type="number">
					<span class="integral_search" @click="enterRewardCode">查询</span>
					<image :src="imgInfo.scanCloseImg" class="close" @click="setCodePop(false)"/>
				</view>
			</view>
		</view>
	</scroll-view>
</template>

<script setup>
	import { ref, computed, onMounted, watch, onUnmounted } from 'vue'
	import { onLoad, onShow, onUnload } from '@dcloudio/uni-app'
	import { handleError } from '../utils/handleError.js'
	import throttled from '../utils/throttle.js'
	import { getParams } from '../utils/common.js'
	import { heightPool } from '../utils/headerCustomer.js'
	import { checkLogin } from '@/utils/checkLogin.js'
	import { getItem } from '../utils/storage/index'
	import { getPageImgInfo, getScanPicNum, getScanCode } from "@/api/xmhActivity/index.js"

	import { useCameraManager } from './composables/useCameraManager'
	import { useImageProcessor } from './composables/useImageProcessor'
	
	//最大变焦倍数
	let setMaxZoom = 3

	// 页面数据
	const isShowPage = ref(false)
	const loginStatus = ref(0) // 登录状态 0未登录 1 已登录
	const isShowLoading = ref(false) // 是否显示加载状态
	const applyEntrance = ref(false) // 是否显示申诉入口
	const qrcodeUrl = ref('') // 扫码得到的二维码结果
	const timer = ref(0) // 定时器 
	const imgInfo = ref({}) //页面图片集合
	const channel = ref(null)  //扫码渠道 1扫码 2手动熟人
	const showCodePop = ref(false)
	const pointCode = ref('') //积分码
	const heightPools = ref(heightPool) //导航栏头部高度
	const complianceUrlList = ref([]) //合法域名数组
	
	const {
		isShowCamera, // 是否打开摄像头
		isShowCameraDelayed, // 是否非摄像头样式
		cameraContext, // Camera摄像头实例
		cameraListener, // 摄像头监听对象
		startCamera, // 启动摄像头
		stopCamera, // 停止摄像头
		zoomTimer, //变焦定时器
		cleanupCamera, 
		setIsShowCamera
	} = useCameraManager()

	const {
		photos, // 照片集合
		farmsNumber, // 帧数计数器
		isBegin, //  是否处在扫码中状态
		processAndUploadImages, // 批量处理图片到oss
		resetScanData
	} = useImageProcessor()
	
	
	
	// 点击扫码-判断登录态
	const handleBeginScan = throttled( async ()=>{
		console.log('扫一扫')
		if (loginStatus.value === 0) {
			checkLogin()
			return
		}
		
		await beginScanCode()
	},1500)
	
	// 执行扫码逻辑
	async function beginScanCode() {
		
		applyEntrance.value = false;
		timer.value = 0; 
		channel.value = 1 //渠道为扫码

		console.log("开始扫码流程")

		// 启动摄像头
		startCamera()

		// 设置60秒后显示申诉入口
		timer.value = setTimeout(() => {
			applyEntrance.value = true;
			clearTimeout(timer.value); // 清除定时器
		}, 60000)

		// 获取扫码配置
		await getScanPicUrlData()
	}

	// 处理扫码配置数据
	async function getScanPicUrlData() {
		
		try {
			const result = await getScanPicNum()
			
			complianceUrlList.value = result.data.data.domain //合法域名
			initScanningCode(result.data.data.sacn) //上传图片数量
			
		} catch (error) {
			console.error("获取扫码配置信息失败:", error)
		}
	}

	// 初始化扫码功能
	function initScanningCode(imageIndexes) {
		if (!cameraContext.value) return;
		
		try {
			// 获取实时的摄像头帧数据
			const listener = cameraContext.value.onCameraFrame((res) => {
				console.log("实时摄像帧数据:",res)
				handleCameraFrame(res, imageIndexes)
			})
			cameraListener.value = listener

			// 重置摄像头变焦
			cameraContext.value.setZoom({
				zoom: 1
			})
		} catch (error) {
			console.error("初始化扫码功能失败:", error)
		}
	}

	// 处理摄像头帧数据
	function handleCameraFrame(frame, imageIndexes) {
		// 丢弃前几帧确保稳定
		if (farmsNumber.value < 10) {
			farmsNumber.value++
			return
		}

		// 收集有效帧数据
		if (frame.width) {
			photos.value.push(frame)
		}
		// 收集足够数量后处理
		if (photos.value.length > imageIndexes) {
			setTimeout(() => {
				cameraListener.value?.stop()
				handleScanCodeImg(imageIndexes)
			})
		}
	}

	// 进入扫码图片处理
	async function handleScanCodeImg(imageIndexes) {		
		loading(true)
		
		// 重置摄像头倍数
		cameraContext.value?.setZoom({
			zoom: 1
		}) 
		// 处理图片
		const processedImages = await processAndUploadImages(imageIndexes)
		
		console.log('oss图片:',processedImages)
		
		if (!processedImages || processedImages.length === 0) return;
		
		// 调扫码接口
		await sendScanRequest(processedImages)
	}

	// 处理扫码结果
	async function sendScanRequest(images, eptCode) {
		const { imeiId, userEncryption, miniChannel } = getParams();
		
		await getScanCode({
			picUrl:images,
			eptCode: eptCode,
			userEncryption,
			miniChannel,
			imeiId: imeiId,
			channel:channel.value,
			carryParameter:qrcodeUrl.value,
		}).then((scancodeResult) => {
			console.log("扫码结果:",scancodeResult);
			const { code, data, success, errMsg, message } = scancodeResult;
			
			// 清理变焦定时器
			if (zoomTimer.value) {
				clearTimeout(zoomTimer.value);
			}

			isBegin.value = false
			isShowCameraDelayed.value = false // 隐藏摄像头相关UI
			
			if (code === "000000" && success === true) {
				loading(false);
				// 扫码成功处理
				uni.navigateTo({
				    url: '/subPackages/xmhAactivity/webview/index?url=' + encodeURIComponent(data)
				});
				return;
			} else {
				loading(false);
				if(data){
					uni.navigateTo({
					    url: '/subPackages/xmhAactivity/webview/index?url=' + encodeURIComponent(data)
					});
				}else{
					showError(message || errMsg)
				}
				return;
			}
		}).catch(error => {
			loading(false);
			isBegin.value = false
			isShowCameraDelayed.value = false
			console.error('请求扫码接口失败:', error)
		})
	}

	// 扫码成功回调
	function scancodeHandle(res) {
		if (isBegin.value) return; //防止重复执行
		console.log("二维码扫描成功:",res);
		
		isBegin.value = true
		qrcodeUrl.value = res.detail.result //获取扫码结果
		
		if(!checkCodeDomain(qrcodeUrl.value)){
			showError('请扫描积分码')
			isBegin.value = false
			return;
		}
		setTimeout(() => {
			cameraListener.value?.start()
		})
	}
	
	// 校验合法域名
	function checkCodeDomain(qrcodeResult) {
	    const urlResultArray = qrcodeResult.split(".");
		
	    if (urlResultArray.length < 3) {
	      console.log("域名不合法,域名是：", qrcodeResult, urlResultArray);
	      return false;
	    }
	
	    const [urlFirst, urlSecond] = urlResultArray;
	
	    return complianceUrlList.value.some((item) => {
	      if (item.indexOf(urlFirst) > -1 && item.indexOf(urlSecond) > -1) {
	        return true;
	      }
	    });
	}
	
	// 相机初始化处理变焦
	function initdone(e) {
		const { maxZoom } = e.detail;
		console.log('最大变焦倍数:', maxZoom)
		
		if (maxZoom > 1) {
			setMaxZoom = maxZoom > 3 ? 3 : maxZoom
			setZoomNum();
		}
	}
	
	// 自动变焦
	function setZoomNum() {
	    let beginZoom = 1; // 起始变焦值
	    let time = 3000; // 变焦时间间隔
	    const setZoom = (zoom) => {
			cameraContext.value.setZoom({
				zoom: zoom,
				success: () => {
					if (beginZoom > setMaxZoom) {
						beginZoom = 1;
						time = 5000;
					} else if (beginZoom === 1) {
						beginZoom += 0.1;
						time = 3000;
					} else {
						beginZoom += 0.1;
						time = 40;
					}
					// 设置下一个变焦定时器
					const newZoomTimer = setTimeout(() => {
						setZoom(beginZoom);
						clearTimeout(zoomTimer.value);
					}, time);
					zoomTimer.value = newZoomTimer
				},fail: (err) => {
					console.log('缩放设置失败:', err);
				}
			});
	    };
	    setZoom(beginZoom); // 循环变焦
	  }
	
	// 摄像头错误处理
	function errorHandle(e) {
		console.error("摄像头错误:", e)
		showError(`请点击右上角的"…"按钮进入设置页面开启摄像头权限!`)
		resetScanData() //初始化相机数据
		stopCamera() //隐藏摄像头
	}
	
	// 控制页面loading 
	function loading(state) {
		if (state && !isShowLoading.value) {
			setIsShowCamera(false) // 隐藏摄像头
			uni.showLoading({
				title: "扫描成功正在处理",
				mask: true,
				success: () => {
					isShowLoading.value = true
				},
			});
			return;
		}
		if (!state) {
			uni.hideLoading({
				success: () => {
					isShowLoading.value = false
				},
			});
		}
	}
	
	// 打开积分输入弹窗
	function setCodePop(value){
		pointCode.value = '';
		showCodePop.value = value;
		
		//手动输入渠道
		if(value){ 
			channel.value = 2;
		};
	}
	
	// 手动积分码核销
	const enterRewardCode = throttled(()=>{
		const integral = pointCode.value;
		var reg = /^(\d{20})$/; //最大20位数字
		
		if(integral == ""  || !reg.test(integral)){
			showError("输入的积分码有误，请重新输入")
		}else{
		  sendScanRequest([], integral) //带入积分码核销
		}
	},1500)
	
	// 无法扫码-申诉
	const handleApply = throttled(()=>{
		const { crmId, latitude, longitude } = getParams();
		const XMH = 'https://mom.feihe.com'
		const XMH2 = 'https://momuat.feihe.com'
		const baseUrl = `${XMH}/member/internalCodeAppeal?crmId=${crmId}&latitude=${latitude}&longitude=${longitude}`
		 uni.navigateTo({
		     url: '/subPackages/xmhAactivity/webview/index?url=' + encodeURIComponent(baseUrl)
		 });
	},1500)

	// 显示错误信息
	function showError(message) {
		uni.showToast({
			icon: "none",
			title: message,
			duration: 2000
		})
	}

	// 显示成功信息
	function showSuccess(message) {
		uni.showToast({
			icon: "success",
			title: message,
			duration: 2000
		})
	}
	
	// 返回首页
	function goHome() {
		uni.reLaunch({
			url: '/pages/index/index'
		})
	}

	// 关闭扫码
	function closeScanCode() {
		stopCamera()
		clearTimeout(timer.value); // 重置定时器
	}

	// 页面初始化
	function initPage (){
		uni.showLoading()
		// 获取页面图片
		getPageImgInfo().then(res=>{
			const { code, success, data } = res
			if(code === '000000' && success === true){
				imgInfo.value = data
				uni.hideLoading({
					success: () => {
						isShowPage.value = true
					}
				});
			}else{
				uni.hideLoading({
					success: () => {
						isShowPage.value = false
						
					},
				});
				console.error('获取页面图片信息失败:', res)
			}
		})
	}
	
	onLoad(async ()=>{
		// 获取登录态
		loginStatus.value = getItem("loginStatus");
		console.log("用户登录状态:",loginStatus.value)
		
		await initPage()
	})
	onUnload(() => {
		resetScanData()
		cleanupCamera() //清空相机
		timer.value = 0
		isBegin.value = false
		pointCode.value = ''
		loginStatus.value = 0
		isShowPage.value = true
		applyEntrance.value = false
		showCodePop.value = false
		console.log('销毁')
	})
	onShow(() => {})
</script>

<style lang="less" scoped>
	.scan-wrapper{
		width: 100vw;
		height: 100vh;
		-webkit-overflow-scrolling: touch;
		overflow: hidden;
		background: #B78C65;
	}
	.scan-code-points {
		position: relative;
		width: 100%;
		height: 1600rpx;
		background-repeat: no-repeat;
		background-size: cover;
		
		.button-box{
			display: block;
			position: absolute;
			bottom: 87rpx;
			left: 50%;
			z-index: 10;
			transform: translateX(-50%);
		}
		
		.begin-btn {
			margin: 0 auto;
			width: 560rpx;
			height: 88rpx;
			line-height: 88rpx;
			font-weight: 800;
			font-size: 36rpx;
			color: #FFFFFF;
			background: #D2A356;
			border-radius: 100rpx;
			font-family: PingFang SC, PingFang SC;
		}
		.write-btn{
			margin: 0 auto;
			margin-top: 37rpx;
			width: 200rpx;
			height: 39rpx;
			font-weight: 500;
			font-size: 28rpx;
			color: #666666;
			text-align: center;
			font-family: PingFang SC, PingFang SC;
		}
		.scan-code-camera {
			position: fixed;
			z-index: 10;
			width: 100vw;
			height: 100vh;
		}

		.close-scan-code {
			position: fixed;
			z-index: 999;
			width: 48rpx;
			height: 48rpx;
			left: 18rpx;
			top: 80rpx;
		}

		.my-canvas {
			position: fixed;
			left: 100vw;
			top: 100vh;
			width: 100vw;
			height: 100vh;
			z-index: 0;
		}
		
		
		.camera-group {
			position: fixed;
			left: 0;
			bottom: 0;
			width: 100%;
			z-index: 20;
			animation: maskFadeIn 0.3s ease-out;
			
			@keyframes maskFadeIn {
				from { 
					opacity: 0; 
				}
				to { 
					opacity: 1;
				}
			}
	
			.title {
				font-family: MiSans, MiSans;
				font-weight: bold;
				font-size: 32rpx;
				color: #333333;
				line-height: 38rpx;
				text-align: center;
				margin-top: 37rpx;
			}

			.tip-bottom {
				z-index: 10;
				position: absolute;
				left: 0;
				bottom: 0;
				width: 100%;
				height: 500rpx;
				background: #FFFFFF;
				border-radius: 32rpx 32rpx 0 0;
				margin-top: 38rpx;
				animation: contentSlideUp 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);

				@keyframes contentSlideUp {
				  from {
				    transform: translateY(100%);
				    opacity: 0.6;
				  }
				  to {
				    transform: translateY(0);
				    opacity: 1;
				  }
				}

				.img-group {
					margin-top: 38rpx;
					display: flex;
					padding: 0 24rpx;
					justify-content: space-around;

					.img {
						width: 160rpx;
						height: 232rpx;
					}
				}
			}

			.apply {
				padding: 0 24rpx;
				justify-content: space-around;
				display: flex;
				margin-top: 26rpx;
				font-weight: 400;
				font-size: 28rpx;
				color: #666666;
				line-height: 62rpx;

				.apply-button {
					width: 160rpx;
					height: 58rpx;
					border-radius: 58rpx;
					border: 2rpx solid #D2A356;
					font-weight: 500;
					font-size: 26rpx;
					color: #D2A356;
					text-align: center;
					line-height: 58rpx;
					font-style: normal;
					text-transform: none;
				}
			}
		}
	}
	.point-mask {
		width: 100%;
		height: 100%;
		background: rgba(0,0,0,0.6);
		position: fixed;
		top: 0;
		left: 0;
		z-index: 99;
		animation: fadeIn 0.3s;
		.modal-enter {
			transform: scale(1);
			opacity: 1;
		}
		
		@keyframes fadeIn {
			from {
				opacity: 0;
			}
			to {
				opacity: 1;
			}
		}
		
		.mask-box{
			width:564rpx;
			height:508rpx;
			background:rgba(255,255,255,1);
			border-radius:16rpx;
			position: absolute;
			top: 50%;
			left: 0;right: 0%;
			transform: translateY(-50%);
			margin: auto;
			#integral_number{
				width: 468rpx;
				height: 92rpx;
				background: rgba(242,242,242,1);
				border-radius: 16rpx;
				border: 0;
				margin: 150rpx auto 100rpx;
				display: block;
				padding: 0 20rpx;
				font-size: 24rpx;
			}
			.integral_search{
				width:362rpx;
				background:linear-gradient(270deg,rgba(212,164,55,1) 0%,rgba(229,191,93,1) 100%);
				border-radius:46rpx;
				color: rgba(255,255,255,1);
				display: block;
				margin: 0 auto;
				padding: 26rpx 0;
				text-align: center;
				font-size: 40rpx;
				line-height: 1;
			}
			.close{
				width: 58rpx;
				height: 58rpx;
				position: absolute;
				bottom: -112rpx;
				left: 0;right: 0%;
				margin: auto;
			}
		}
	}
	
</style>