<template>
	<view class="result-page">
		<view class="result-card">
			<view v-if="status === 'pending'" class="status-block">
				<view class="pending-icon">
					<text class="ri-loader-4-line pending-spinner"></text>
				</view>
				<view class="status-title">支付处理中</view>
				<view class="status-desc">正在确认支付结果，请稍候...</view>
				<view class="amount">¥ {{ amount }}</view>
			</view>

			<view v-else-if="status === 'success'" class="status-block">
				<view class="success-icon ri-checkbox-circle-fill"></view>
				<view class="status-title success-title">支付成功</view>
				<view class="amount">¥ {{ amount }}</view>
				<view v-if="showAccumulation" class="meta-row">
					<text class="meta-label">获得{{ scoreName }}</text>
					<text class="meta-value">¥ {{ accumulation }}</text>
				</view>
				<view class="meta-row">
					<text class="meta-label">收款商家</text>
					<text class="meta-value merchant">{{ merchantName }}</text>
				</view>
			</view>

			<view v-else class="status-block">
				<view class="fail-icon ri-close-circle-fill"></view>
				<view class="status-title fail-title">支付未完成</view>
				<view class="status-desc">{{ statusMessage }}</view>
				<view class="amount muted-amount">¥ {{ amount }}</view>
			</view>
		</view>

		<view v-if="status !== 'pending'" class="action-group">
			<button
				v-if="status === 'success'"
				class="action-btn primary"
				hover-class="button-hover"
				@tap="goMine"
			>
				个人中心
			</button>
			<button class="action-btn" :class="{ primary: status === 'failed' }" hover-class="button-hover-light" @tap="goCashier">
				{{ status === 'failed' ? '返回收银台' : '继续付款' }}
			</button>
		</view>
	</view>
</template>

<script setup lang="ts">
import { computed, onUnmounted, ref } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import { queryTrade } from '@/api/cashier';

const POLL_INTERVAL_MS = 1000;
const POLL_MAX_ATTEMPTS = 240;

type ResultStatus = 'pending' | 'success' | 'failed';

const amount = ref('0.00');
const accumulation = ref('0.00');
const merchantName = ref('');
const merchantUrl = ref('');
const scoreName = ref('物业公积金');
const tradeNo = ref('');
const status = ref<ResultStatus>('pending');
const statusMessage = ref('支付结果确认超时，请稍后在付款记录中查看');

let pollStopped = false;
let pollTimer: ReturnType<typeof setTimeout> | null = null;

const showAccumulation = computed(() => Number(accumulation.value) > 0);

const decodeOption = (value?: string) => {
	if (!value) return '';
	try {
		return decodeURIComponent(value);
	} catch (error) {
		return value;
	}
};

const sleep = (ms: number) => new Promise<void>((resolve) => {
	pollTimer = setTimeout(() => {
		pollTimer = null;
		resolve();
	}, ms);
});

const stopPolling = () => {
	pollStopped = true;
	if (pollTimer) {
		clearTimeout(pollTimer);
		pollTimer = null;
	}
};

const pollTradeStatus = async () => {
	if (!tradeNo.value) {
		status.value = 'failed';
		statusMessage.value = '缺少交易单号';
		return;
	}

	for (let attempt = 0; attempt < POLL_MAX_ATTEMPTS; attempt++) {
		if (pollStopped) return;

		try {
			const res = await queryTrade(tradeNo.value);
			if (Number(res?.code) === 200 && Number(res?.data?.pay_status) === 1) {
				status.value = 'success';
				return;
			}
		} catch (error) {
			console.log('trade query failed', error);
		}

		if (attempt < POLL_MAX_ATTEMPTS - 1) {
			await sleep(POLL_INTERVAL_MS);
		}
	}

	if (!pollStopped) {
		status.value = 'failed';
		statusMessage.value = '支付结果确认超时，请稍后在付款记录中查看';
	}
};

const goMine = () => {
	uni.navigateTo({
		url: '/pages/mine/index'
	});
};

const goCashier = () => {
	if (!merchantUrl.value) {
		uni.showToast({
			title: '请重新扫码进入收银台',
			icon: 'none'
		});
		return;
	}
	uni.reLaunch({
		url: `/pages/pay/pay?url=${encodeURIComponent(merchantUrl.value)}`
	});
};

onLoad((options: any) => {
	amount.value = options?.amount || '0.00';
	accumulation.value = options?.accumulation || '0.00';
	merchantName.value = decodeOption(options?.merchant_name || options?.merchantName);
	merchantUrl.value = decodeOption(options?.merchant_url || options?.url);
	scoreName.value = decodeOption(options?.score_name) || '物业公积金';
	tradeNo.value = decodeOption(options?.trade_no || options?.order_id || options?.orderId);
	pollTradeStatus();
});

onUnmounted(() => {
	stopPolling();
});
</script>

<style lang="scss" scoped>
.result-page {
	min-height: 100vh;
	padding: 48rpx 28rpx;
	background: #f4f6f8;
}

.result-card {
	padding: 72rpx 36rpx 48rpx;
	border-radius: 14rpx;
	background: #ffffff;
	box-shadow: 0 8rpx 22rpx rgba(17, 24, 39, 0.04);
	text-align: center;
}

.status-block {
	display: flex;
	flex-direction: column;
	align-items: center;
}

.pending-icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 108rpx;
	height: 108rpx;
	color: #1f5bd8;
	font-size: 88rpx;
	line-height: 1;
}

.pending-spinner {
	display: inline-block;
	animation: spin 1s linear infinite;
}

@keyframes spin {
	from {
		transform: rotate(0deg);
	}
	to {
		transform: rotate(360deg);
	}
}

.success-icon {
	color: #1f5bd8;
	font-size: 108rpx;
	line-height: 1;
}

.fail-icon {
	color: #ef4444;
	font-size: 108rpx;
	line-height: 1;
}

.status-title {
	margin-top: 28rpx;
	color: #111827;
	font-size: 40rpx;
	font-weight: 800;
}

.success-title {
	color: #111827;
}

.fail-title {
	color: #111827;
}

.status-desc {
	margin-top: 16rpx;
	padding: 0 12rpx;
	color: #8b929e;
	font-size: 26rpx;
	line-height: 1.5;
}

.amount {
	margin-top: 24rpx;
	color: #050505;
	font-size: 72rpx;
	font-weight: 800;
	line-height: 1.1;
}

.muted-amount {
	color: #6b7280;
}

.meta-row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	width: 100%;
	margin-top: 36rpx;
	padding-top: 28rpx;
	border-top: 1rpx solid #eef1f5;
}

.meta-label {
	color: #8b929e;
	font-size: 28rpx;
}

.meta-value {
	color: #1f2937;
	font-size: 28rpx;
	font-weight: 700;
}

.meta-value.merchant {
	max-width: 360rpx;
	text-align: right;
}

.action-group {
	margin-top: 48rpx;
}

.action-btn {
	display: flex;
	align-items: center;
	justify-content: center;
	height: 88rpx;
	margin-bottom: 24rpx;
	padding: 0;
	border-radius: 9rpx;
	background: #ffffff;
	color: #1f5bd8;
	font-size: 32rpx;
	font-weight: 800;
}

.action-btn::after {
	border: none;
}

.action-btn.primary {
	background: #1f5bd8;
	color: #ffffff;
}

.button-hover {
	background: #174dc1;
}

.button-hover-light {
	background: #f0f4ff;
}
</style>
