<template>
	<view class="h5-camera-container">
		<!-- 视频流显示 -->
		<view v-if="!capturedImage" class="video-wrapper" v-html="videoHtml"></view>

		<!-- Canvas用于捕获照片 -->
		<canvas class="camera-canvas" id="photoCanvas"></canvas>

		<!-- 已拍摄的照片 -->
		<image v-if="capturedImage" class="captured-image" :src="capturedImage" mode="aspectFill"></image>

		<!-- 重拍按钮 -->
		<view v-if="capturedImage" class="refresh-host" @click="retake">
			<image class="refresh-icon" src="/static/icon_refresh.png" mode="scaleToFill"></image>
		</view>

		<!-- 人像预览框 -->
		<image class="preview-frame" src="/static/silhouette.png" mode="scaleToFill"></image>

		<!-- 倒计时显示 -->
		<view v-if="countdownVisible" class="countdown-overlay">
			<text class="countdown-number">{{ countdownNumber }}</text>
		</view>
	</view>
</template>

<script setup lang="uts">
	import { ref, onMounted, onUnmounted } from 'vue'

	const capturedImage = ref<string>('')
	const countdownVisible = ref<boolean>(false)
	const countdownNumber = ref<number>(5)
	let countdownTimerId : number | null = null
	let mediaStream : any = null
	const videoHtml = ref<string>('<video class="camera-video" autoplay playsinline muted webkit-playsinline x5-playsinline style="width:100%;height:100%;object-fit:cover;transform:scaleX(-1);"></video>')

	// 定义 props
	const props = defineProps<{
		imageSrc ?: string
	}>()

	// 定义 emits
	const emit = defineEmits<{
		captured : [imageSrc: string]
		retake : []
	}>()

	onMounted(() => {
		// 如果传入了 imageSrc，直接显示
		if (props.imageSrc) {
			capturedImage.value = props.imageSrc
		} else {
			// 延迟启动摄像头，确保 DOM 已渲染
			setTimeout(() => {
				startCamera()
			}, 300)
		}
	})

	onUnmounted(() => {
		stopCamera()
		if (countdownTimerId != null) {
			clearInterval(countdownTimerId as number)
			countdownTimerId = null
		}
	})

	// 启动摄像头
	const startCamera = () => {
		// #ifdef H5
		if (typeof navigator === 'undefined' || !navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
			uni.showToast({
				title: '浏览器不支持摄像头',
				icon: 'none'
			})
			return
		}

		navigator.mediaDevices.getUserMedia({
			video: {
				facingMode: 'environment', // 后置摄像头
				width: { ideal: 480 },
				height: { ideal: 640 }
			},
			audio: false
		})
			.then((stream) => {
				mediaStream = stream
				// 使用原生 DOM 操作
				const videoElement = document.querySelector('.camera-video') as HTMLVideoElement
				if (videoElement) {
					videoElement.srcObject = stream
					// 设置视频属性
					videoElement.setAttribute('autoplay', 'true')
					videoElement.setAttribute('playsinline', 'true')
					videoElement.setAttribute('muted', 'true')

					// 尝试播放
					const playPromise = videoElement.play()
					if (playPromise !== undefined) {
						playPromise.catch((err) => {
							console.error('视频播放失败:', err)
						})
					}
				} else {
					console.error('未找到 video 元素')
				}
			})
			.catch((error) => {
				console.error('无法访问摄像头:', error)
				let errorMsg = '无法访问摄像头'
				if (error.name === 'NotAllowedError') {
					errorMsg = '摄像头权限被拒绝'
				} else if (error.name === 'NotFoundError') {
					errorMsg = '未找到摄像头设备'
				}
				uni.showToast({
					title: errorMsg,
					icon: 'none'
				})
			})
		// #endif
	}

	// 停止摄像头
	const stopCamera = () => {
		// #ifdef H5
		if (mediaStream) {
			const tracks = mediaStream.getTracks()
			tracks.forEach((track : any) => {
				track.stop()
			})
			mediaStream = null
		}
		// #endif
	}

	// 拍照
	const takePhoto = () => {
		// #ifdef H5
		const videoElement = document.querySelector('.camera-video') as HTMLVideoElement
		const canvasElement = document.getElementById('photoCanvas') as HTMLCanvasElement

		if (!videoElement || !canvasElement) {
			console.error('未找到 video 或 canvas 元素')
			uni.showToast({
				title: '拍照失败',
				icon: 'none'
			})
			return
		}

		// 检查视频是否准备好
		if (videoElement.readyState !== videoElement.HAVE_ENOUGH_DATA) {
			console.error('视频未准备好')
			uni.showToast({
				title: '请稍候再试',
				icon: 'none'
			})
			return
		}

		const context = canvasElement.getContext('2d')
		if (!context) {
			console.error('无法获取 canvas context')
			return
		}

		// 设置 canvas 尺寸与视频一致
		const width = videoElement.videoWidth || 480
		const height = videoElement.videoHeight || 640
		canvasElement.width = width
		canvasElement.height = height

		// 水平翻转画布（修复镜像问题）
		context.translate(width, 0)
		context.scale(-1, 1)

		// 绘制当前视频帧到 canvas
		context.drawImage(videoElement, 0, 0, width, height)

		// 重置变换
		context.setTransform(1, 0, 0, 1, 0, 0)

		// 将 canvas 转换为图片
		const dataUrl = canvasElement.toDataURL('image/jpeg', 0.9)
		capturedImage.value = dataUrl


		emit('captured', dataUrl)
		stopCamera()
		// #endif
	}

	// 重拍
	const retake = () => {
		capturedImage.value = ''
		emit('retake')
		// 延迟启动摄像头
		setTimeout(() => {
			startCamera()
		}, 100)
	}

	// 开始倒计时拍照
	const startCountdown = () => {
		if (countdownVisible.value || capturedImage.value) {
			return
		}

		countdownNumber.value = 5
		countdownVisible.value = true

		if (countdownTimerId != null) {
			clearInterval(countdownTimerId as number)
			countdownTimerId = null
		}

		countdownTimerId = setInterval(() => {
			if (countdownNumber.value > 1) {
				countdownNumber.value = countdownNumber.value - 1
			} else {
				if (countdownTimerId != null) {
					clearInterval(countdownTimerId as number)
					countdownTimerId = null
				}
				countdownVisible.value = false
				takePhoto()
			}
		}, 1000) as number
	}

	// 获取已拍摄的图片
	const getCapturedImage = () : string => {
		return capturedImage.value
	}

	// 暴露方法给父组件
	defineExpose({
		startCountdown,
		getCapturedImage,
		retake
	})
</script>

<style scoped>
	.h5-camera-container {
		position: relative;
		width: 100%;
		height: 100%;
		overflow: hidden;
	}

	.video-wrapper {
		position: absolute;
		left: 0;
		top: 0;
		width: 100%;
		height: 100%;
		overflow: hidden;
	}

	.camera-video {
		position: absolute;
		left: 0;
		top: 0;
		width: 100%;
		height: 100%;
		object-fit: cover;
	}

	.camera-canvas {
		position: absolute;
		left: -9999px;
		top: -9999px;
		visibility: hidden;
		pointer-events: none;
	}

	.captured-image {
		position: absolute;
		left: 0;
		top: 0;
		width: 100%;
		height: 100%;
		object-fit: cover;
	}

	.refresh-host {
		position: absolute;
		right: 10rpx;
		top: 10rpx;
		width: 52rpx;
		height: 52rpx;
		background: #FFFFFF;
		border-radius: 26rpx;
		display: flex;
		justify-content: center;
		align-items: center;
		z-index: 10;
	}

	.refresh-icon {
		width: 26rpx;
		height: 26rpx;
	}

	.preview-frame {
		position: absolute;
		left: 50%;
		top: 50%;
		transform: translate(-50%, -50%);
		width: 506rpx;
		height: 560rpx;
		pointer-events: none;
		z-index: 5;
	}

	.countdown-overlay {
		position: absolute;
		left: 0;
		top: 0;
		width: 100%;
		height: 100%;
		display: flex;
		justify-content: center;
		align-items: center;
		z-index: 20;
	}

	.countdown-number {
		font-weight: bold;
		font-size: 180rpx;
		color: #FFFFFF;
		text-shadow: 0 0 20rpx rgba(0, 0, 0, 0.5);
	}
</style>