<template>
	<view class="sign-page">
		<view class="canvas-wrap">
			<view class="hint-text">
				<text>请在此处手写签名</text>
				<text class="hint-sub">请横屏书写</text>
			</view>
			<canvas id="signCanvas" canvas-id="signCanvas" type="2d" class="sign-canvas" disable-scroll
				@touchstart="onTouchStart" @touchmove="onTouchMove" @touchend="onTouchEnd" />
		</view>
		<view class="bottom-btns">
			<view class="btn-clear" @click="handleClear">
				<text>清除</text>
			</view>
			<view class="btn-save" @click="handleSave">
				<text>保存</text>
			</view>
		</view>
	</view>
</template>

<script setup>
import { ref, nextTick } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { upload } from '@/utils/request.js'

let ctx = null
let canvasEl = null
let canvasWidth = 0
let canvasHeight = 0
const hasDrawn = ref(false)
const saving = ref(false)
let lastX = 0
let lastY = 0

onLoad(async () => {
	await nextTick()
	setTimeout(() => {
		const query = uni.createSelectorQuery()
		query.select('#signCanvas').fields({ node: true, size: true }).exec((res) => {
			if (!res[0]) return
			canvasEl = res[0].node
			const dpr = uni.getSystemInfoSync().pixelRatio
			canvasWidth = res[0].width
			canvasHeight = res[0].height
			canvasEl.width = canvasWidth * dpr
			canvasEl.height = canvasHeight * dpr
			ctx = canvasEl.getContext('2d')
			ctx.scale(dpr, dpr)
			ctx.lineCap = 'round'
			ctx.lineJoin = 'round'
			ctx.lineWidth = 4
			ctx.strokeStyle = '#333'
		})
	}, 300)
})

const getPos = (e) => {
	const touch = e.touches[0]
	return { x: touch.x, y: touch.y }
}

const onTouchStart = (e) => {
	if (!ctx) return
	hasDrawn.value = true
	const { x, y } = getPos(e)
	lastX = x
	lastY = y
	ctx.beginPath()
	ctx.moveTo(x, y)
}

const onTouchMove = (e) => {
	if (!ctx) return
	const { x, y } = getPos(e)
	ctx.beginPath()
	ctx.moveTo(lastX, lastY)
	ctx.lineTo(x, y)
	ctx.stroke()
	lastX = x
	lastY = y
}

const onTouchEnd = () => {}

const handleClear = () => {
	if (!ctx || !canvasEl) return
	ctx.clearRect(0, 0, canvasWidth, canvasHeight)
	hasDrawn.value = false
}

const handleSave = () => {
	if (!hasDrawn.value) {
		uni.showToast({ title: '请先签名', icon: 'none' })
		return
	}
	if (saving.value) return
	saving.value = true
	uni.showLoading({ title: '保存中...' })

	uni.canvasToTempFilePath({
		canvas: canvasEl,
		fileType: 'png',
		quality: 1,
		success: async (res) => {
			try {
				const dpr = uni.getSystemInfoSync().pixelRatio
				// 创建离屏 canvas 旋转签名（横屏→竖屏，逆时针90度）
				const offscreen = uni.createOffscreenCanvas({
					type: '2d',
					width: canvasHeight * dpr,
					height: canvasWidth * dpr
				})
				const offCtx = offscreen.getContext('2d')
				const img = offscreen.createImage()
				await new Promise((resolve, reject) => {
					img.onload = resolve
					img.onerror = reject
					img.src = res.tempFilePath
				})
				offCtx.translate(0, canvasWidth * dpr)
				offCtx.rotate(-Math.PI / 2)
				offCtx.drawImage(img, 0, 0)

				const rotatedRes = await new Promise((resolve, reject) => {
					uni.canvasToTempFilePath({
						canvas: offscreen,
						fileType: 'png',
						quality: 1,
						success: resolve,
						fail: reject
					})
				})

				// 上传签名图
				const uploadRes = await upload('/api/mp/upload', {
					filePath: rotatedRes.tempFilePath,
					name: 'file'
				})
				if (!uploadRes.data || !uploadRes.data.url) {
					throw { msg: '上传失败' }
				}

				uni.hideLoading()
				// 把签名图 URL 传回 sign 页面
				uni.$emit('signatureResult', { url: uploadRes.data.url })
				uni.navigateBack()
			} catch (err) {
				uni.hideLoading()
				uni.showToast({ title: err.msg || '上传失败，请重试', icon: 'none' })
			} finally {
				saving.value = false
			}
		},
		fail: () => {
			uni.hideLoading()
			uni.showToast({ title: '保存失败', icon: 'none' })
			saving.value = false
		}
	})
}
</script>

<style lang="scss" scoped>
.sign-page {
	display: flex;
	flex-direction: column;
	height: 100vh;
	background: #edf2fc;
}

.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;
		white-space: nowrap;
		z-index: 0;
		display: flex;
		flex-direction: column;
		align-items: center;
		gap: 16rpx;

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

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

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

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

	.btn-clear {
		flex: 1;
		display: flex;
		align-items: center;
		justify-content: center;
		background: #fff;

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

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

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