<template>
	<view v-if="show" class="sign-page" @touchmove.stop.prevent>
		<view class="canvas-wrap">
			<view class="hint-text">
				<text>请在此处手写签名</text>
				<text class="hint-sub">请横屏书写</text>
			</view>
			<view id="signContainer" class="sign-container" />
		</view>
		<view class="bottom-btns">
			<view class="btn-close" @click="handleClose">
				<text>取消</text>
			</view>
			<view class="btn-clear" @click="handleClear">
				<text>清除</text>
			</view>
			<view class="btn-save" @click="handleSave">
				<text>{{ saving ? '上传中' : '保存' }}</text>
			</view>
		</view>
	</view>
</template>

<script setup>
import { ref, watch, nextTick } from 'vue'
import { upload } from '@/utils/request.js'

const props = defineProps({
	show: { type: Boolean, default: false }
})
const emit = defineEmits(['close', 'confirm'])

let signature = null
const hasDrawn = ref(false)
const saving = ref(false)
let scriptLoaded = false

const loadScript = () => {
	return new Promise((resolve, reject) => {
		if (window.SmoothSignature) { resolve(); return }
		if (scriptLoaded) {
			const check = setInterval(() => {
				if (window.SmoothSignature) { clearInterval(check); resolve() }
			}, 50)
			return
		}
		scriptLoaded = true
		const s = document.createElement('script')
		s.src = 'https://cdn.csybhelp.com/lib/smooth-signature.umd.min.js'
		s.onload = resolve
		s.onerror = reject
		document.head.appendChild(s)
	})
}

const initSignature = async () => {
	await loadScript()
	await nextTick()
	setTimeout(() => {
		const container = document.getElementById('signContainer')
		if (!container) return
		container.innerHTML = ''
		const canvas = document.createElement('canvas')
		canvas.style.width = '100%'
		canvas.style.height = '100%'
		container.appendChild(canvas)
		signature = new window.SmoothSignature(canvas, {
			width: container.offsetWidth,
			height: container.offsetHeight,
			minWidth: 2,
			maxWidth: 6,
			color: '#333',
			bgColor: 'transparent'
		})
		canvas.addEventListener('touchstart', () => { hasDrawn.value = true })
		canvas.addEventListener('mousedown', () => { hasDrawn.value = true })
	}, 200)
}

watch(() => props.show, async (val) => {
	if (val) {
		hasDrawn.value = false
		saving.value = false
		signature = null
		await initSignature()
	}
})

const handleClear = () => {
	if (signature) signature.clear()
	hasDrawn.value = false
}

const handleClose = () => { emit('close') }

const handleSave = async () => {
	if (!hasDrawn.value || !signature) {
		return uni.showToast({ title: '请先签名', icon: 'none' })
	}
	if (saving.value) return
	saving.value = true
	uni.showLoading({ title: '保存中...' })
	try {
		// 从 smooth-signature 获取 PNG DataURL
		const dataUrl = signature.getPNG()
		if (!dataUrl) throw { msg: '获取签名失败' }

		// 旋转签名（逆时针90度，横屏→竖屏，与小程序端保持一致）
		const rotatedDataUrl = await rotateImage(dataUrl, -90)
		const blob = dataURLtoBlob(rotatedDataUrl)
		const formData = new FormData()
		formData.append('file', blob, 'signature.png')

		// H5 下直接用 XMLHttpRequest 上传（uni.uploadFile 需要 filePath）
		const token = uni.getStorageSync('pap-cytx-token') || ''
		const baseUrl = uni.$u && uni.$u.http && uni.$u.http.config
			? uni.$u.http.config.baseURL
			: '/pro-api'
		const url = baseUrl + '/api/mp/upload'

		const result = await new Promise((resolve, reject) => {
			const xhr = new XMLHttpRequest()
			xhr.open('POST', url)
			if (token) xhr.setRequestHeader('Authorization', 'Bearer ' + token)
			xhr.onload = () => {
				try {
					const res = JSON.parse(xhr.responseText)
					if (res.code === 0 && res.data && res.data.url) resolve(res.data.url)
					else reject({ msg: res.msg || '上传失败' })
				} catch (e) { reject({ msg: '上传失败' }) }
			}
			xhr.onerror = () => reject({ msg: '网络错误' })
			xhr.send(formData)
		})

		uni.hideLoading()
		emit('confirm', { url: result })
	} catch (err) {
		uni.hideLoading()
		uni.showToast({ title: err.msg || '上传失败', icon: 'none' })
	} finally {
		saving.value = false
	}
}

const dataURLtoBlob = (dataUrl) => {
	const arr = dataUrl.split(',')
	const mime = arr[0].match(/:(.*?);/)[1]
	const bstr = atob(arr[1])
	let n = bstr.length
	const u8arr = new Uint8Array(n)
	while (n--) u8arr[n] = bstr.charCodeAt(n)
	return new Blob([u8arr], { type: mime })
}

const rotateImage = (dataUrl, degrees) => {
	return new Promise((resolve) => {
		const img = new Image()
		img.onload = () => {
			const canvas = document.createElement('canvas')
			const rad = (degrees * Math.PI) / 180
			// 旋转 -90 度：宽高互换
			if (Math.abs(degrees) === 90) {
				canvas.width = img.height
				canvas.height = img.width
			} else {
				canvas.width = img.width
				canvas.height = img.height
			}
			const ctx = canvas.getContext('2d')
			ctx.translate(canvas.width / 2, canvas.height / 2)
			ctx.rotate(rad)
			ctx.drawImage(img, -img.width / 2, -img.height / 2)
			resolve(canvas.toDataURL('image/png'))
		}
		img.src = dataUrl
	})
}
</script>

<style lang="scss" scoped>
.sign-page {
	position: fixed;
	top: 30rpx;
	left: 30rpx;
	right: 30rpx;
	bottom: 30rpx;
	z-index: 9999;
	display: flex;
	flex-direction: column;
	background: #edf2fc;
	border-radius: 16rpx;
	overflow: hidden;
	box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.5);
}

.canvas-wrap {
	flex: 1;
	position: relative;
	overflow: hidden;

	.hint-text {
		position: absolute;
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%) rotate(90deg);
		pointer-events: none;
		z-index: 0;
		display: flex;
		flex-direction: column;
		align-items: center;
		gap: 16rpx;
		width: 80vh;

		text {
			font-size: 48rpx;
			color: #c0c8d8;
			font-weight: 300;
			letter-spacing: 16rpx;
			white-space: nowrap;
		}

		.hint-sub {
			font-size: 28rpx;
			letter-spacing: 8rpx;
		}
	}

	.sign-container {
		width: 100%;
		height: 100%;
		position: relative;
		z-index: 1;
	}
}

.bottom-btns {
	display: flex;
	height: calc(100rpx + env(safe-area-inset-bottom));
	flex-shrink: 0;
	gap: 12rpx;
	padding: 12rpx;
	padding-bottom: calc(12rpx + env(safe-area-inset-bottom));
	background: #edf2fc;

	.btn-close {
		flex: 1;
		display: flex;
		align-items: center;
		justify-content: center;
		background: #8c939d;
		border-radius: 12rpx;

		text {
			writing-mode: vertical-rl;
			transform: rotate(90deg);
			font-size: 32rpx;
			color: #fff;
			letter-spacing: 4rpx;
			height: 120rpx;
			text-align: center;
		}
	}

	.btn-clear {
		flex: 1;
		display: flex;
		align-items: center;
		justify-content: center;
		background: #ff4040;
		border-radius: 12rpx;

		text {
			writing-mode: vertical-rl;
			transform: rotate(90deg);
			font-size: 32rpx;
			color: #fff;
			letter-spacing: 4rpx;
			height: 120rpx;
			text-align: center;
		}
	}

	.btn-save {
		flex: 2;
		display: flex;
		align-items: center;
		justify-content: center;
		background: #0e63e3;
		border-radius: 12rpx;

		text {
			writing-mode: vertical-rl;
			transform: rotate(90deg);
			font-size: 32rpx;
			color: #fff;
			letter-spacing: 4rpx;
			height: 120rpx;
			text-align: center;
		}
	}
}
</style>
