<template>
	<view class="camera-page" @touchstart="resetTimer">
		<PageHeader @back="handleBack">{{status == 'rendering' ? '作品生成中' : '作品已生成'}}</PageHeader>
		<text class="time" v-if="status == 'rendering' && countdownSeconds > 0">预计还需 {{countdownSeconds}} 秒</text>
		<text class="time" v-else-if="status == 'rendering' && countdownSeconds <= 0">正在完成最后处理…</text>
		<view class="card">
			<view class="image-container">
				<!-- 原图片 - 始终显示作为底层 -->
				<image class="card-image old-image" :src="imageSrc" mode="widthFix">
				</image>

				<!-- 新图片 - 从上往下逐渐显示 -->
				<view v-if="status == 'success'" class="new-image-wrapper" :style="{ height: newImageHeight + '%' }">
					<image class="card-image new-image" :src="renderImageSrc" mode="widthFix"
						@load="handleNewImageLoad">
					</image>
				</view>

				<!-- 扫描线 - 持续上下往返扫描（渲染中） -->
				<image v-if="status == 'rendering'" class="scan-line"
					:style="{ top: scanLineTop + '%', opacity: scanLineOpacity }" src="/static/scanning_line.png"
					mode="scaleToFill"></image>

				<!-- 过渡扫描线 - 跟随过渡进度（接口返回后立即显示） -->
				<image v-if="status == 'success' && transitionScanLineTop < 100" class="transition-scan-line"
					:style="{ top: transitionScanLineTop + '%', opacity: 1 }" src="/static/scanning_line.png"
					mode="scaleToFill"></image>
			</view>
		</view>
		<view v-if="status == 'success'" class="take-photo-btn" hover-class="hover_btn" @click="handlePrint">
			<image class="take-photo-icon" src="/static/icon_print.png" /><text class="take-photo-text">打印</text>
		</view>
	</view>
	<PopupConfirm :visible="showPopup" :title="popupTitle" :content="popupContent" :showCancel="popupShowCancel"
		:confirmText="popupConfirmText" :cancelText="popupCancelText" @confirm="onPopupConfirm"
		@cancel="onPopupCancel" />
	<CategorySelector :visible="showCategorySelector" @close="handleCategorySelectorClose" @select="handleCategoryProductSelect" />
</template>
<script setup lang="uts">
	import { ref } from 'vue'
	import PageHeader from '../../components/Common/PageHeader.uvue'
	import CategorySelector from '../../components/Common/CategorySelector.uvue'
	import { ossUpload, uploadurl, queryRenderResult, cancel, type ResponseData } from '../../utils/reques.uts'

	let inactivityTimer : number = 0
	const INACTIVITY_TIMEOUT = 6 * 60 * 1000 // 6分钟

	const imageSrc = ref('')
	const status = ref('rendering')
	const url = ref('')
	const renderImageSrc = ref('')
	// 弹窗相关
	const showPopup = ref(false)
	const popupTitle = ref('提示')
	const popupContent = ref('')
	const popupShowCancel = ref(false)
	const popupConfirmText = ref('确定')
	const popupCancelText = ref('取消')
	const popupType = ref('') // 用于区分弹窗类型：'back' 或 'error'
	// 保存当前任务的 prompt_id，便于取消
	const currentPromptId = ref<string>('')
	// 分类选择器显示控制
	const showCategorySelector = ref(false)
	let pollTimer : number | null = null
	const countdownSeconds = ref(30) // 倒计时秒数，从30秒开始
	let countdownTimer : number | null = null // 倒计时定时器
	let pollStartTime : number = 0 // 轮询开始时间
	const maxPollDuration = 180000 // 最大轮询时长：3分钟（180秒 = 180000毫秒）
	let isRenderSuccess = false // 标记渲染是否已成功

	// 新图过渡动画相关
	const newImageHeight = ref(0) // 新图显示高度 0-100
	const transitionDuration = 5000 // 过渡动画持续时间（毫秒）
	let transitionTimer : number | null = null
	const isNewImageLoaded = ref(false) // 新图是否加载完成
	const transitionScanLineTop = ref(0) // 过渡扫描线位置 0-100

	// 扫描线动画相关
	const scanLineTop = ref(0) // 扫描线位置 0-100
	const scanLineOpacity = ref(0) // 扫描线透明度 0-1
	let scanLineTimer : number | null = null
	const scanLineDuration = 10000 // 扫描线往返一次的时间（毫秒）

	// 重置定时器 - 提前声明，供其他函数调用
	const resetTimer = () => {
		// 清除现有定时器
		if (inactivityTimer > 0) {
			clearTimeout(inactivityTimer)
			inactivityTimer = 0
		}
		// 启动新的定时器
		inactivityTimer = setTimeout(() => {
			// 6分钟无操作，跳转到首页
			uni.reLaunch({
				url: '/pages/index/index'
			})
		}, INACTIVITY_TIMEOUT)
	}

	// 停止倒计时
	const stopCountdown = () => {
		if (countdownTimer != null) {
			clearInterval(countdownTimer as number)
			countdownTimer = null
		}
	}

	// 开始倒计时
	const startCountdown = () => {
		countdownSeconds.value = 30
		countdownTimer = setInterval(() => {
			if (countdownSeconds.value > 0) {
				countdownSeconds.value--
			} else {
				stopCountdown()
			}
		}, 1000) as number
	}

	// 停止扫描线动画
	const stopScanLineAnimation = () => {
		if (scanLineTimer != null) {
			clearInterval(scanLineTimer as number)
			scanLineTimer = null
		}
	}

	// 开始扫描线动画 - 使用简化的往返逻辑
	const startScanLineAnimation = () => {
		stopScanLineAnimation()

		scanLineTop.value = 0
		scanLineOpacity.value = 0
		let direction = 1 // 1: 向下, -1: 向上
		const step = 2 // 每次移动2%
		const interval = 20 // 20ms更新一次

		scanLineTimer = setInterval(() => {
			// 更新位置
			scanLineTop.value += direction * step

			// 计算透明度（顶部和底部渐变）
			const pos = scanLineTop.value
			if (pos < 5) {
				scanLineOpacity.value = pos / 5
			} else if (pos > 95) {
				scanLineOpacity.value = (100 - pos) / 5
			} else {
				scanLineOpacity.value = 1
			}

			// 到达边界时反向
			if (scanLineTop.value >= 100) {
				scanLineTop.value = 100
				direction = -1
			} else if (scanLineTop.value <= 0) {
				scanLineTop.value = 0
				direction = 1
			}
		}, interval) as number
	}

	// 新图加载完成的处理
	const handleNewImageLoad = () => {
		isNewImageLoaded.value = true
	}

	// 开始新图过渡动画 - 从上往下显示
	const startTransitionAnimation = () => {
		// 停止扫描线动画
		stopScanLineAnimation()

		newImageHeight.value = 0
		transitionScanLineTop.value = 0
		isNewImageLoaded.value = false
		status.value = 'success'

		const interval = 20 // 20ms更新一次
		const totalSteps = transitionDuration / interval
		const stepProgress = 100 / totalSteps
		let currentStep = 0

		transitionTimer = setInterval(() => {
			currentStep++
			const progress = Math.min(100, currentStep * stepProgress)

			// 扫描线始终跟随进度
			transitionScanLineTop.value = progress - 2

			// 如果图片已加载，新图也跟随显示
			if (isNewImageLoaded.value) {
				newImageHeight.value = progress
			}

			if (currentStep >= totalSteps) {
				if (transitionTimer != null) {
					clearInterval(transitionTimer as number)
					transitionTimer = null
				}
				transitionScanLineTop.value = 100
				newImageHeight.value = 100
			}
		}, interval) as number
	}

	// 停止过渡动画
	const stopTransitionAnimation = () => {
		if (transitionTimer != null) {
			clearInterval(transitionTimer as number)
			transitionTimer = null
		}
		stopScanLineAnimation()
	}


	// 停止轮询
	const stopPolling = () => {
		if (pollTimer != null) {
			clearInterval(pollTimer as number)
			pollTimer = null
		}
	}

	// 清理所有定时器
	const cleanupAllTimers = () => {
		stopPolling()
		stopCountdown()
		stopTransitionAnimation()
		uni.hideLoading()
	}

	// 显示错误弹窗
	const showErrorPopup = (content : string) => {
		// 如果已经成功，不显示错误弹窗
		if (isRenderSuccess) {
			console.log('已成功，不显示错误弹窗');
			return
		}
		
		console.log('显示错误弹窗：' + content);
		stopPolling()
		stopCountdown()
		stopScanLineAnimation()
		uni.hideLoading()
		popupType.value = 'error'
		popupTitle.value = '提示'
		popupContent.value = content
		popupShowCancel.value = false
		popupConfirmText.value = '确定'
		showPopup.value = true
	}

	const startPolling = (promptId : string) => {
		pollStartTime = Date.now()
		isRenderSuccess = false
		// 扫描线动画和倒计时已在 ossUpload 成功后启动，这里不再重复启动

		const check = async () : Promise<void> => {
			// 如果已经成功，不再执行检查
			if (isRenderSuccess) {
				console.log('已成功，跳过检查');
				return
			}

			// 检查是否超过3分钟
			const elapsedTime = Date.now() - pollStartTime
			console.log('轮询检查，已用时：' + Math.floor(elapsedTime / 1000) + '秒');

			if (elapsedTime >= maxPollDuration) {
				console.log('超过3分钟，显示错误弹窗');
				showErrorPopup('抱歉，当前相片与风格无法匹配，请返回重试')
				return
			}

			try {
				const res = await queryRenderResult(promptId) as ResponseData
				
				// 接口返回后再次检查是否已成功，避免竞态条件
				if (isRenderSuccess) {
					return
				}
				
				if (res.code == 0) {
					const dataJson = res.data as UTSJSONObject
					const statusObj = dataJson['status_value'] as UTSJSONObject | null
					const value : string = statusObj != null ? (statusObj.getString('value') ?? '') : ''

					if (value == 'rendering') {
						status.value = 'rendering'
						if (scanLineTimer == null) {
							startScanLineAnimation()
						}
					} else if (value == 'success') {
						console.log('渲染成功，停止轮询');
						isRenderSuccess = true // 标记为成功
						stopPolling()
						stopCountdown()
						const renderImage : string = dataJson.getString('render_image') ?? ''
						url.value = renderImage
						renderImageSrc.value = renderImage
						startTransitionAnimation()
					} else {
						showErrorPopup('抱歉，当前相片与风格无法匹配，请返回重试')
					}
				} else {
					stopPolling()
					stopCountdown()
					uni.hideLoading()
				}
			} catch (err) {
				// 捕获异常后也检查是否已成功
				if (!isRenderSuccess) {
					showErrorPopup('图片生成失败，请联系管理员')
				}
			}
		}

		check()
		pollTimer = (setInterval(() : void => { check() }, 3000) as number)
	}


	const postrender = async (ai_model_id : number,) => {
		const imagePath = imageSrc.value ?? ''
		// 判断是否为网络地址
		const isNetworkUrl = imagePath.startsWith('http://') || imagePath.startsWith('https://')
		let imageUrl = imagePath
		let imageName = ''

		if (!isNetworkUrl) {
			// 本地图片，先上传到 OSS
			try {
				const ossRes = await ossUpload(imagePath) as ResponseData
				if (ossRes.code == 0) {
					const ossData = ossRes.data as UTSJSONObject
					const fileObj = ossData.getJSON('file')
					if (fileObj != null) {
						imageUrl = fileObj.getString('url') ?? ''
						imageName = fileObj.getString('origin_name') ?? ''

						// OSS上传成功后立即开始扫描线动画和倒计时
						startScanLineAnimation()
						startCountdown()

					} else {
						showErrorPopup('图片上传失败，请重试')
						return
					}
				} else {
					showErrorPopup(ossRes.message)
					return
				}
			} catch (error) {
				uni.hideLoading()
				showErrorPopup('图片上传失败，请重试')
				return
			}
		} else {
			// 从URL中提取文件名（最后一个/后面的全部内容）
			const lastSlashIndex = imagePath.lastIndexOf('/')
			if (lastSlashIndex != -1 && lastSlashIndex < imagePath.length - 1) {
				imageName = imagePath.substring(lastSlashIndex + 1)
			}

			// 网络图片也立即开始扫描线动画和倒计时
			startScanLineAnimation()
			startCountdown()
		}

		// 使用 uploadurl 接口进行渲染
		const params = {
			ai_model_id: ai_model_id,
			image: imageUrl,
			image_name: imageName
		}
		try {
			const res = await uploadurl(params) as ResponseData
			if (res.code == 0) {
				const dataJson = res.data as UTSJSONObject
				const promptId : string = dataJson.getString('prompt_id') ?? ''
				if (promptId.length > 0) {
					// 记录 prompt_id，供取消接口使用
					currentPromptId.value = promptId
					status.value = 'rendering'
					startPolling(promptId)
				}
			} else {
				showErrorPopup(res.message)
			}
		} catch (error) {
			console.log('error',error)
			showErrorPopup('抱歉，当前相片与风格无法匹配，请返回重试')
		}
	}

	const handlePrint = () => {
		// 打开分类选择器
		showCategorySelector.value = true
	}

	// 关闭分类选择器
	const handleCategorySelectorClose = () => {
		showCategorySelector.value = false
	}

	// 处理分类选择器中的商品选择
	const handleCategoryProductSelect = (product : any) => {
		console.log('[gener] 选中商品:', product)
		showCategorySelector.value = false
		
		// 跳转到其他页面前清除定时器
		if (inactivityTimer > 0) {
			clearTimeout(inactivityTimer)
			inactivityTimer = 0
		}
		
		// 使用生成后的图片 URL（renderImageSrc）
		const uploadedUrl = url.value
		
		// 将商品数据通过 URL 参数传递到打印页面
		const productData = encodeURIComponent(JSON.stringify(product))
		uni.navigateTo({
			url: '/pages/print/index?imageSrc=' + encodeURIComponent(uploadedUrl) + '&productData=' + productData
		})
	}

	onLoad((event : OnLoadOptions) => {
		// 对接收到的 imageSrc 进行 URL 解码
		const rawImageSrc = event["imageSrc"] ?? ''
		const decoded = rawImageSrc.length > 0 ? decodeURIComponent(rawImageSrc) : ''
		imageSrc.value = decoded != null ? decoded : ''
		const selectedObj = uni.getStorageSync('selectedItem') as UTSJSONObject
		const ai_model_id : number = selectedObj.getNumber('id') ?? 0
		postrender(ai_model_id,)

		// 启动无操作定时器
		resetTimer()
	})

	const handleBack = () => {
		popupType.value = 'back'
		popupTitle.value = '温馨提示'
		popupContent.value = '作品生成消耗算力,确认退出吗？'
		popupShowCancel.value = true
		popupConfirmText.value = '确定'
		popupCancelText.value = '取消'
		showPopup.value = true
	}

	// 弹窗确认处理
	const onPopupConfirm = async () => {
		showPopup.value = false

		if (popupType.value == 'back') {
			cleanupAllTimers()
			if (inactivityTimer > 0) {
				clearTimeout(inactivityTimer)
				inactivityTimer = 0
			}
			uni.reLaunch({ url: '/pages/list/index' })
		} else if (popupType.value == 'error') {
			cleanupAllTimers()
			if (inactivityTimer > 0) {
				clearTimeout(inactivityTimer)
				inactivityTimer = 0
			}
			uni.reLaunch({ url: '/pages/index/index' })
		}
	}

	// 弹窗取消处理
	const onPopupCancel = () => {
		showPopup.value = false

		if (popupType.value == 'error') {
			cleanupAllTimers()
			if (inactivityTimer > 0) {
				clearTimeout(inactivityTimer)
				inactivityTimer = 0
			}
			uni.reLaunch({ url: '/pages/index/index' })
		}
	}

	onUnload(() => {
		cleanupAllTimers()
		// 清除无操作定时器
		if (inactivityTimer > 0) {
			clearTimeout(inactivityTimer)
			inactivityTimer = 0
		}
	})
</script>

<style>
	.camera-page {
		height: 100%;
	}

	.time {
		position: absolute;
		top: 150rpx;
		left: 0;
		right: 0;
		text-align: center;
		align-items: center;
		font-weight: 400;
		font-size: 25rpx;
		color: #000000;
	}

	.card {
		position: absolute;
		top: 170rpx;
		bottom: 0;
		right: 0;
		background: #FFEAF5;
		margin-top: 30rpx;
		border-radius: 53rpx;
		z-index: 0;
		width: 657rpx;
		height: 854rpx;
		left: 50%;
		transform: translateX(-50%);
	}

	.image-container {
		position: relative;
		width: 100%;
		height: 100%;
		overflow: hidden;
		border-radius: 53rpx;
	}

	.card-image {
		width: 100%;
		height: 100%;
	}

	.old-image {
		position: absolute;
		top: 0;
		left: 0;
		z-index: 1;
	}

	/* 新图包裹层 - 从上往下逐渐显示 */
	.new-image-wrapper {
		position: absolute;
		top: 0;
		left: 0;
		right: 0;
		overflow: hidden;
		z-index: 2;
	}

	.new-image {
		position: absolute;
		top: 0;
		left: 0;
		width: 100%;
		height: 854rpx;
	}

	/* 扫描线 - 持续上下往返扫描 */
	.scan-line {
		position: absolute;
		left: 0;
		width: 100%;
		height: 40rpx;
		pointer-events: none;
		z-index: 10;
	}

	/* 过渡扫描线 - 跟随新图显示进度 */
	.transition-scan-line {
		position: absolute;
		left: 0;
		width: 100%;
		height: 30rpx;
		pointer-events: none;
		z-index: 3;
	}


	.card-host {
		margin-top: 20rpx;
		width: 181.25rpx;
		height: 9.03rpx;
	}

	.card-text {
		margin-top: 44rpx;
		font-weight: 400;
		font-size: 25rpx;
		color: #000000;
		align-items: center;
	}



	.take-photo-btn {

		width: 657rpx;
		height: 97rpx;
		background: #FD3DA0;
		border-radius: 14rpx;
		flex-direction: row;
		display: flex;
		align-items: center;
		justify-content: center;
		position: relative;
		margin: 0 auto;
		position: fixed;
		bottom: 120rpx;
		left: 50%;
		transform: translateX(-50%);
	}

	.take-photo-icon {
		margin-right: 20rpx;
		width: 29.86rpx;
		height: 27.08rpx;
	}

	.take-photo-text {
		font-weight: bold;
		font-size: 28rpx;
		color: #FFFFFF;
	}

	.actions {
		margin-top: 704rpx;
		display: flex;
		flex-direction: row;
		justify-content: center;
	}


	.btn {
		width: 180rpx;
		height: 80rpx;
		border-radius: 16rpx;
		font-size: 28rpx;
	}

	.primary {
		width: 181rpx;
		height: 83rpx;
		background: #FFFFFF;
		border-radius: 14rpx;
		border: 2rpx solid #FF86C3;
		font-weight: 400;
		font-size: 24rpx;
		color: #000000;
		margin-right: 20rpx;
		line-height: 83rpx;
	}
</style>