<template>
	<view class="page">
		<view v-if="loading && !qrToken" class="state">加载中…</view>
		<view v-else-if="loadError" class="state error">{{ loadError }}</view>
		<template v-else>
			<view class="canvas-wrap">
				<canvas
					canvas-id="identityQr"
					class="qr-canvas"
					:style="canvasStyle"
					:width="canvasPx"
					:height="canvasPx"
				/>
			</view>
			<text class="expire-line">{{ expireHint }}</text>
			<text class="tip">请让核验端扫描此码。码内为加密身份令牌，请勿自行解析。</text>
			<view class="btn-refresh" @click="refreshQr">刷新二维码</view>
		</template>
	</view>
</template>

<script>
	import UQRCode from 'uqrcodejs'
	import { getToken, getIdentityQrPayload } from '../../utils/api'

	const CANVAS_PX = 300

	export default {
		data() {
			return {
				loading: false,
				loadError: '',
				qrToken: '',
				expireAtMs: 0,
				nowMs: Date.now(),
				canvasPx: CANVAS_PX,
				canvasReady: false,
				countdownTimer: null,
				refreshTimer: null
			}
		},
		computed: {
			canvasStyle() {
				const n = this.canvasPx
				return `width:${n}px;height:${n}px;`
			},
			expireHint() {
				if (!this.expireAtMs) return ''
				const left = Math.max(0, Math.floor((this.expireAtMs - this.nowMs) / 1000))
				if (left <= 0) return '已过期，请刷新'
				return `剩余有效时间约 ${left} 秒`
			}
		},
		onReady() {
			this.canvasReady = true
			this.tryDrawQr()
		},
		onShow() {
			this.fetchQr()
		},
		onUnload() {
			this.clearTimers()
		},
		methods: {
			clearTimers() {
				if (this.countdownTimer) {
					clearInterval(this.countdownTimer)
					this.countdownTimer = null
				}
				if (this.refreshTimer) {
					clearTimeout(this.refreshTimer)
					this.refreshTimer = null
				}
			},
			scheduleRefreshBeforeExpire() {
				if (this.refreshTimer) {
					clearTimeout(this.refreshTimer)
					this.refreshTimer = null
				}
				if (!this.expireAtMs) return
				const ms = this.expireAtMs - Date.now() - 5000
				if (ms < 200) return
				this.refreshTimer = setTimeout(() => {
					this.refreshTimer = null
					if (getToken()) this.fetchQr(true)
				}, ms)
			},
			startCountdown() {
				if (this.countdownTimer) clearInterval(this.countdownTimer)
				this.nowMs = Date.now()
				this.countdownTimer = setInterval(() => {
					this.nowMs = Date.now()
				}, 1000)
			},
			normalizePayload(raw) {
				if (!raw || typeof raw !== 'object') return null
				const o =
					raw.data != null && typeof raw.data === 'object' && !raw.token
						? raw.data
						: raw
				const token = o.token
				const expiresAt = o.expires_at != null ? o.expires_at : o.expiresAt
				if (!token || typeof token !== 'string') return null
				return { token, expiresAt }
			},
			async fetchQr(isRefresh) {
				const token = getToken()
				if (!token) {
					this.loadError = '请先登录'
					return
				}
				if (!isRefresh) this.loadError = ''
				this.loading = true
				try {
					const raw = await getIdentityQrPayload(token)
					const parsed = this.normalizePayload(raw)
					if (!parsed) {
						throw new Error('接口返回无效')
					}
					this.qrToken = parsed.token
					this.expireAtMs = parsed.expiresAt ? new Date(parsed.expiresAt).getTime() : 0
					this.clearTimers()
					this.startCountdown()
					this.scheduleRefreshBeforeExpire()
					this.$nextTick(() => this.tryDrawQr())
				} catch (e) {
					this.qrToken = ''
					this.expireAtMs = 0
					this.loadError = (e && e.message) || '获取失败'
				} finally {
					this.loading = false
				}
			},
			refreshQr() {
				this.fetchQr(true)
			},
			tryDrawQr() {
				if (!this.canvasReady || !this.qrToken) return
				this.drawQr()
			},
			drawQr() {
				const text = this.qrToken
				const size = this.canvasPx
				try {
					const qr = new UQRCode()
					qr.data = text
					qr.size = size
					qr.errorCorrectLevel = UQRCode.errorCorrectLevel.L
					qr.margin = 4
					qr.make()
					const ctx = uni.createCanvasContext('identityQr', this)
					qr.canvasContext = ctx
					qr.drawCanvas().catch(() => {
						uni.showToast({ title: '二维码绘制失败', icon: 'none' })
					})
				} catch (e) {
					uni.showToast({ title: '二维码生成失败', icon: 'none' })
				}
			}
		}
	}
</script>

<style scoped>
	.page {
		min-height: 100vh;
		background: #f5f5f5;
		padding: 48rpx 32rpx 80rpx;
		box-sizing: border-box;
		display: flex;
		flex-direction: column;
		align-items: center;
	}
	.state {
		font-size: 28rpx;
		color: #666;
		margin-top: 120rpx;
	}
	.state.error {
		color: #e54d42;
		padding: 0 32rpx;
		text-align: center;
		line-height: 1.6;
	}
	.canvas-wrap {
		background: #fff;
		padding: 24rpx;
		border-radius: 16rpx;
		box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.06);
		margin-bottom: 32rpx;
	}
	.qr-canvas {
		display: block;
	}
	.expire-line {
		font-size: 28rpx;
		color: #259653;
		margin-bottom: 24rpx;
	}
	.tip {
		display: block;
		font-size: 24rpx;
		color: #999;
		line-height: 1.6;
		text-align: center;
		padding: 0 16rpx;
		margin-bottom: 48rpx;
	}
	.btn-refresh {
		background: #fff;
		color: #259653;
		font-size: 30rpx;
		padding: 24rpx 56rpx;
		border-radius: 12rpx;
		border: 1rpx solid #259653;
	}
</style>
