<template>
	<view class="generation-loading">
		<image class="background-image" src="/static/background/exhibitionSuccess.png" mode="aspectFill" />

		<view class="gift-box">
			<image class="gift-image" src="/static/nft/lihe.png" mode="aspectFit" />
		</view>

		<view class="progress-container">
			<view class="progress-bar-wrapper">
				<view class="progress-bar">
					<view class="progress-fill" :style="{ width: progress + '%' }"></view>
				</view>
				<view class="progress-icon" :style="{ left: progress + '%' }">
					<view class="icon-circle"></view>
				</view>
			</view>
			<text class="progress-text">{{ Math.round(progress) }}%</text>
			<text class="loading-text">Thinking</text>
		</view>

		<!-- 镭射批量导出（离屏） -->
		<canvas
			canvas-id="laserBatchCanvas"
			class="laser-batch-canvas"
			:style="{ width: laserCanvasW + 'px', height: laserCanvasH + 'px' }"
		/>
	</view>
</template>

<script setup>
import { ref, onMounted } from 'vue';
import { imageGenerationApi } from '@/utils/api.js';
import {
	consumeGenerationFlowPayload,
	FLOW_MODE_PREFILLED,
	FLOW_MODE_LENTICULAR,
	FLOW_MODE_LASER,
	GENERATED_IMAGES_KEY,
	GENERATION_REQUEST_KEY,
	CASTLOVE_FORM_KEY,
	persistLenticularPreviewMeta,
	persistLaserPreviewImages,
} from '@/utils/castloveGenerationFlow.js';
import {
	generateLaserVariantBatch,
	LASER_BATCH_CANVAS_SIZE,
} from '@/utils/laser-card/laserBatchExport.js';

const progress = ref(0);
const laserCanvasW = LASER_BATCH_CANVAS_SIZE.w;
const laserCanvasH = LASER_BATCH_CANVAS_SIZE.h;
let progressTimer = null;
let generationData = null;
let flowStartedAt = 0;

// 模拟进度增长
const simulateProgress = () => {
	progressTimer = setInterval(() => {
		if (progress.value < 90) {
			// 进度到90%前缓慢增长
			const increment = Math.random() * 5 + 2;
			progress.value = Math.min(90, progress.value + increment);
		}
	}, 500);
};

// 停止进度模拟
const stopProgress = () => {
	if (progressTimer) {
		clearInterval(progressTimer);
		progressTimer = null;
	}
};

// 完成进度
const completeProgress = () => {
	stopProgress();
	const finalInterval = setInterval(() => {
		if (progress.value < 100) {
			progress.value = Math.min(100, progress.value + 5);
		} else {
			clearInterval(finalInterval);
			// 进度完成后延迟跳转
			setTimeout(() => {
				handleSuccess();
			}, 500);
		}
	}, 50);
};

// 回退进度
const revertProgress = () => {
	stopProgress();
	const revertInterval = setInterval(() => {
		if (progress.value > 0) {
			progress.value = Math.max(0, progress.value - 10);
		} else {
			clearInterval(revertInterval);
			// 回退完成后返回上一页
			setTimeout(() => {
				uni.navigateBack();
			}, 500);
		}
	}, 100);
};

const waitMinDuration = async (minMs) => {
	if (!minMs || minMs <= 0) return;
	const elapsed = Date.now() - flowStartedAt;
	if (elapsed < minMs) {
		await new Promise((r) => setTimeout(r, minMs - elapsed));
	}
};

const handleSuccess = () => {
	uni.showToast({ title: '生成成功', icon: 'success', duration: 1200 });
	setTimeout(() => {
		uni.navigateTo({ url: '/pages/discover/generation-result' });
	}, 1200);
};

const runPrefilledFlow = async (flow) => {
	try {
		const images = flow.images || [];
		if (!images.length) throw new Error('无候选图');
		await waitMinDuration(flow.minDurationMs ?? 1400);
		uni.setStorageSync(GENERATED_IMAGES_KEY, JSON.stringify(images));
		completeProgress();
	} catch (err) {
		console.error('[GenerationLoading] prefilled', err);
		uni.showToast({ title: err.message || '加载失败', icon: 'none' });
		revertProgress();
	}
};

const runLenticularFlow = async (flow) => {
	try {
		const formStr = uni.getStorageSync(CASTLOVE_FORM_KEY);
		if (!formStr) throw new Error('缺少表单数据');
		const formData = JSON.parse(formStr);
		await waitMinDuration(flow.minDurationMs ?? 1600);
		persistLenticularPreviewMeta(formData);
		completeProgress();
	} catch (err) {
		console.error('[GenerationLoading] lenticular', err);
		uni.showToast({ title: err.message || '光栅预览失败', icon: 'none' });
		revertProgress();
	}
};

const runLaserFlow = async (flow) => {
	try {
		const formStr = uni.getStorageSync(CASTLOVE_FORM_KEY);
		if (!formStr) throw new Error('缺少表单数据');
		const formData = JSON.parse(formStr);
		const imagePath = formData.image || formData.uploadedImage || '';
		if (!imagePath) throw new Error('缺少上传图片');
		const paths = await generateLaserVariantBatch(imagePath, 'laserBatchCanvas');
		await waitMinDuration(flow.minDurationMs ?? 1600);
		persistLaserPreviewImages(paths);
		completeProgress();
	} catch (err) {
		console.error('[GenerationLoading] laser', err);
		uni.showToast({ title: err.message || '镭射生成失败', icon: 'none' });
		revertProgress();
	}
};

const callImageGeneration = async () => {
	try {
		const res = await imageGenerationApi(generationData);
		if (res.data?.images?.length > 0) {
			uni.setStorageSync(GENERATED_IMAGES_KEY, JSON.stringify(res.data.images));
			completeProgress();
		} else {
			uni.showToast({ title: '未生成图片', icon: 'none' });
			revertProgress();
		}
	} catch (err) {
		console.error('[GenerationLoading] API', err);
		uni.showToast({ title: err.message || '生成失败', icon: 'none' });
		revertProgress();
	}
};

onMounted(() => {
	flowStartedAt = Date.now();
	simulateProgress();
	try {
		const flow = consumeGenerationFlowPayload();

		if (flow?.mode === FLOW_MODE_LENTICULAR) {
			runLenticularFlow(flow);
			return;
		}
		if (flow?.mode === FLOW_MODE_LASER) {
			runLaserFlow(flow);
			return;
		}
		if (flow?.mode === FLOW_MODE_PREFILLED) {
			runPrefilledFlow(flow);
			return;
		}

		const requestDataStr = uni.getStorageSync(GENERATION_REQUEST_KEY);
		if (!requestDataStr) {
			uni.showToast({ title: '数据错误', icon: 'none' });
			setTimeout(() => uni.navigateBack(), 1500);
			return;
		}
		generationData = JSON.parse(requestDataStr);
		const castloveDataStr = uni.getStorageSync(CASTLOVE_FORM_KEY);
		if (castloveDataStr) {
			const castloveData = JSON.parse(castloveDataStr);
			if (generationData.subject_reference?.[0]) {
				generationData.subject_reference[0].image_file =
					castloveData.imageBase64 ||
					castloveData.lenticularSubjectBase64 ||
					'';
			}
		}
		uni.removeStorageSync(GENERATION_REQUEST_KEY);
		callImageGeneration();
	} catch (e) {
		console.error('[GenerationLoading] mount', e);
		uni.showToast({ title: '数据错误', icon: 'none' });
		setTimeout(() => uni.navigateBack(), 1500);
	}
});
</script>

<style scoped>
.generation-loading {
	position: relative;
	width: 100%;
	height: 100vh;
	overflow: hidden;
	background: #000;
}

.laser-batch-canvas {
	position: fixed;
	left: -9999px;
	top: -9999px;
	opacity: 0;
	pointer-events: none;
}

.background-image {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	z-index: 1;
}

.gift-box {
	position: absolute;
	top: 25%;
	left: 50%;
	transform: translateX(-50%);
	width: 480rpx;
	height: 480rpx;
	z-index: 2;
	animation: float 3s ease-in-out infinite;
}

@keyframes float {
	0%,
	100% {
		transform: translateX(-50%) translateY(0) rotate(0deg);
	}
	50% {
		transform: translateX(-50%) translateY(-20rpx) rotate(2deg);
	}
}

.gift-image {
	width: 100%;
	height: 100%;
}

.progress-container {
	position: absolute;
	bottom: 25%;
	left: 50%;
	transform: translateX(-50%);
	width: 600rpx;
	display: flex;
	flex-direction: column;
	align-items: center;
	z-index: 3;
}

.progress-bar-wrapper {
	position: relative;
	width: 100%;
	height: 40rpx;
	margin-bottom: 20rpx;
}

.progress-bar {
	width: 100%;
	height: 40rpx;
	background: rgba(255, 255, 255, 0.3);
	border-radius: 20rpx;
	overflow: hidden;
	border: 2rpx solid rgba(255, 255, 255, 0.5);
}

.progress-fill {
	height: 100%;
	background: linear-gradient(90deg, #ff6b9d 0%, #ffa8c5 50%, #ffb6d9 100%);
	border-radius: 20rpx;
	transition: width 0.3s ease;
}

.progress-icon {
	position: absolute;
	top: 50%;
	transform: translate(-50%, -50%);
	width: 60rpx;
	height: 60rpx;
	transition: left 0.3s ease;
}

.icon-circle {
	width: 100%;
	height: 100%;
	background: linear-gradient(135deg, #ffb6d9 0%, #ff6b9d 100%);
	border-radius: 50%;
	border: 4rpx solid #ffffff;
	animation: pulse 1.5s ease-in-out infinite;
}

@keyframes pulse {
	0%,
	100% {
		transform: scale(1);
	}
	50% {
		transform: scale(1.1);
	}
}

.progress-text {
	font-size: 56rpx;
	font-weight: bold;
	color: #ffffff;
	margin-bottom: 10rpx;
}

.loading-text {
	font-size: 36rpx;
	color: #ffffff;
	letter-spacing: 6rpx;
	font-weight: 500;
}
</style>
