<template>
	<view class="generation-result">
		<!-- 背景图 -->
		<image class="background-image" src="/static/background/exhibitionSuccess.png" mode="aspectFill" />

		<!-- 星星装饰 -->
		<view class="stars-container">
			<view v-for="i in 20" :key="i" class="star" :style="getStarStyle(i)"></view>
		</view>

		<!-- 顶部奖励提示 -->
		<!-- <view class="reward-tips">
			<view class="reward-item">
				<text class="reward-text">恭喜您获得水晶</text>
				<image class="reward-icon" src="/static/icon/crystal.png" mode="aspectFit" />
				<text class="reward-text">X 32</text>
			</view>
			<view class="reward-item">
				<text class="reward-text">恭喜您获小卡碎片</text>
				<image class="reward-icon" src="/static/starcity/xiaoka.png" mode="aspectFit" />
				<text class="reward-text">X 2</text>
			</view>
		</view> -->

		<!-- 光栅卡：单张工作台预览（陀螺仪） -->
		<view class="lenticular-result-wrap" :class="{ 'cards-visible': isGiftOpened }">
			<view class="lenticular-result-card">
				<view class="card-wrapper craft-card-wrapper">
					<image class="card-frame" src="/static/square/gerenzhongxincangpinkuang.png" mode="aspectFit" />
					<view class="craft-lenticular-slot">
						<LenticularCard v-if="lenticularLayers.length > 0" class="craft-lenticular-card"
							:layers="lenticularLayers" :transforms="layerTransforms" :gyro-source="gyroSourceLabel"
							:skip-built-in-touch="true" tilt-hint-text="晃动查看" :shimmer-mid-opacity="0.16"
							@simulate="simulate" />
					</view>
				</view>
			</view>
		</view>

		<!-- 礼盒 -->
		<view class="gift-box" :class="{ 'gift-opened': isGiftOpened }">
			<image v-if="!isGiftOpened" class="gift-image" src="/static/nft/lihe.png" mode="aspectFit" />
			<image v-else class="gift-image gift-image-opened" src="/static/nft/lihe_kaiqi.png" mode="aspectFit" />
		</view>

		<!-- 底部按钮 -->
		<view class="bottom-action" :class="{ 'bottom-action--row': isCraftDetailFlow }">
			<view v-if="isCraftDetailFlow" class="action-button action-button--secondary" @tap="handleRegenerate">
				<text class="button-text">重新生成</text>
			</view>
			<view class="action-button" @tap="selectAsset">
				<text class="button-text">开始铸造</text>
			</view>
		</view>

		<!-- 铸造确认弹窗 -->
		<ConfirmModal v-if="showConfirmModal" :visible="showConfirmModal" :cost-crystal="confirmCostInfo.costCrystal"
			:current-balance="confirmCostInfo.currentBalance" :mint-count="confirmCostInfo.mintCount"
			:next-tier-cost="confirmCostInfo.nextTierCost" @confirm="handleConfirmMint" @cancel="handleCancelMint" />
	</view>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted } from 'vue';
import { onShow, onHide } from '@dcloudio/uni-app';
import { getOssSignatureApi, createMintOrderApi, estimateMintCostApi } from '@/utils/api.js';
import { resolveH5OssPostUrl } from '@/utils/h5OssPostUrl.js';
import LenticularCard from '@/components/lenticular/LenticularCard.vue';
import ConfirmModal from '@/components/ConfirmModal.vue';
import { useLenticularCraftTiltPreview } from '@/composables/useLenticularCraftTiltPreview.js';
import {
	buildLenticularLayersTwo,
	LENTICULAR_STUDIO_STORAGE_KEY,
} from '@/utils/castloveMintForm.js';
import {
	CASTLOVE_FORM_KEY,
	GENERATED_IMAGES_KEY,
	GENERATION_RESULT_META_KEY,
	completeSelectionAndOpenDetail,
	isDetailAfterSelect,
	STUDIO_LENTICULAR,
} from '@/utils/castloveGenerationFlow.js';
import { submitCraftMintFromPath } from '@/utils/craftMintSubmit.js';

const generatedImages = ref([]);
const selectedIndex = ref(-1);
const isUploading = ref(false);
const currentOrderId = ref('');
const isGiftOpened = ref(false);
const craftFormData = ref(null);
const resultMeta = ref('lenticular');

// 确认铸造弹窗
const showConfirmModal = ref(false);
const confirmCostInfo = ref({
	costCrystal: 0,
	currentBalance: 0,
	mintCount: 0,
	nextTierCost: 0,
});

const lenticularLayers = ref([]);
const {
	layerTransforms,
	simulate,
	gyroSourceLabel,
	scheduleTiltStart,
	stopTiltPreview,
} = useLenticularCraftTiltPreview(lenticularLayers);

// 光栅卡详情确认流程
const isCraftDetailFlow = computed(() => isDetailAfterSelect(craftFormData.value));
// 光栅展示模式：结果显示为光栅 或 表单数据为光栅类型
const isLenticularDisplay = computed(
	() => resultMeta.value?.displayMode === STUDIO_LENTICULAR || craftFormData.value?.studio_kind === STUDIO_LENTICULAR
);

// const primaryActionLabel = computed(() =>
// 	isCraftDetailFlow.value ? '选择作品' : '选择您的藏品'
// );

const handleRegenerate = () => {
	uni.navigateBack({ delta: 2 });
};

// 更新本地存储的余额
function updateLocalBalance(newBalance) {
	try {
		const userStr = uni.getStorageSync('user')
		if (userStr) {
			const user = typeof userStr === 'string' ? JSON.parse(userStr) : { ...userStr }
			user.crystal_balance = Number(newBalance) || 0
			uni.setStorageSync('user', JSON.stringify(user))
			uni.$emit('balanceUpdated', { crystal_balance: user.crystal_balance })
		}
	} catch (e) {
		console.warn('[lenticular-result] 更新本地余额失败:', e)
	}
}

// 获取星星样式
const getStarStyle = (index) => {
	const left = Math.random() * 100;
	const top = Math.random() * 100;
	const size = Math.random() * 3 + 1;
	const delay = Math.random() * 3;

	return {
		left: `${left}%`,
		top: `${top}%`,
		width: `${size}rpx`,
		height: `${size}rpx`,
		animationDelay: `${delay}s`
	};
};


// 将base64转换为Blob
const base64ToBlob = (base64Data) => {
	const parts = base64Data.split(';base64,');
	const contentType = parts[0].split(':')[1];
	const raw = atob(parts[1]);
	const rawLength = raw.length;
	const uInt8Array = new Uint8Array(rawLength);

	for (let i = 0; i < rawLength; i++) {
		uInt8Array[i] = raw.charCodeAt(i);
	}

	return new Blob([uInt8Array], { type: contentType });
};

// 上传图片到OSS
const uploadImageToOss = async (base64Image) => {
	console.log('[GenerationResult] uploadImageToOss 开始');
	isUploading.value = true;

	try {
		uni.showLoading({ title: '上传中...', mask: true });

		// 1. 获取OSS签名
		const signRes = await getOssSignatureApi('asset');
		console.log('[GenerationResult] 获取签名结果:', signRes);

		if (signRes.code !== 0) {
			throw new Error(signRes.message || '获取签名失败');
		}

		// 保存order_id
		currentOrderId.value = signRes.data.order_id || '';
		console.log('[GenerationResult] order_id:', currentOrderId.value);

		// 2. 生成文件名
		const timestamp = Date.now();
		const randomStr = Math.random().toString(36).substring(2, 8);
		const fileName = `ai_generated_${timestamp}_${randomStr}.png`;

		let imageUrl;

		// #ifdef H5
		// H5环境：使用FormData + Blob
		console.log('[GenerationResult] H5环境，使用Blob上传');
		const blob = base64ToBlob(base64Image);
		console.log('[GenerationResult] Blob创建成功，大小:', blob.size);

		const formData = new FormData();
		formData.append('key', signRes.data.dir + fileName);
		formData.append('policy', signRes.data.policy);
		formData.append('success_action_status', '200');
		formData.append('x-oss-credential', signRes.data.x_oss_credential);
		formData.append('x-oss-date', signRes.data.x_oss_date);
		formData.append('x-oss-security-token', signRes.data.security_token);
		formData.append('x-oss-signature', signRes.data.signature);
		formData.append('x-oss-signature-version', signRes.data.x_oss_signature_version);
		formData.append('file', blob, fileName);

		const response = await fetch(signRes.data.host, {
			method: 'POST',
			body: formData
		});

		console.log('[GenerationResult] OSS响应状态:', response.status);

		if (response.ok || response.status === 204) {
			imageUrl = `${signRes.data.host}/${signRes.data.dir}${fileName}`;
		} else {
			throw new Error(`上传失败，状态码: ${response.status}`);
		}
		// #endif

		// #ifndef H5
		// App/小程序环境：使用uni.uploadFile
		console.log('[GenerationResult] 非H5环境，使用uni.uploadFile');

		let tempFilePath; // 声明临时文件路径变量

		// #ifdef APP-PLUS
		// App环境：直接使用base64上传（通过临时文件）
		console.log('[GenerationResult] App环境，使用base64临时文件');

		// 使用uni.saveFile保存base64为临时文件
		const base64Data = base64Image.replace(/^data:image\/\w+;base64,/, '');

		// 先转换为临时文件路径
		tempFilePath = await new Promise((resolve, reject) => {
			// 使用uni的base64ToTempFilePath（如果可用）
			if (uni.base64ToTempFilePath) {
				uni.base64ToTempFilePath({
					base64Data: base64Image,
					success: (res) => {
						console.log('[GenerationResult] base64转临时文件成功:', res.tempFilePath);
						resolve(res.tempFilePath);
					},
					fail: (error) => {
						console.error('[GenerationResult] base64转临时文件失败:', error);
						reject(new Error('base64转临时文件失败'));
					}
				});
			} else {
				// 降级方案：使用plus.io
				console.log('[GenerationResult] 使用plus.io方案');
				const bitmap = new plus.nativeObj.Bitmap('temp');
				bitmap.loadBase64Data(base64Image, () => {
					const tempPath = '_doc/' + fileName;
					bitmap.save(tempPath, {}, () => {
						console.log('[GenerationResult] 图片保存成功:', tempPath);
						bitmap.clear();
						resolve(tempPath);
					}, (error) => {
						console.error('[GenerationResult] 图片保存失败:', error);
						bitmap.clear();
						reject(new Error('图片保存失败'));
					});
				}, (error) => {
					console.error('[GenerationResult] 加载base64失败:', error);
					bitmap.clear();
					reject(new Error('加载base64失败'));
				});
			}
		});
		// #endif

		// #ifdef MP-WEIXIN || MP-ALIPAY || MP-BAIDU || MP-TOUTIAO || MP-QQ
		// 小程序环境：使用FileSystemManager
		console.log('[GenerationResult] 小程序环境');
		const base64Data = base64Image.replace(/^data:image\/\w+;base64,/, '');

		// #ifdef MP-WEIXIN
		tempFilePath = `${wx.env.USER_DATA_PATH}/${fileName}`;
		// #endif
		// #ifdef MP-ALIPAY || MP-BAIDU || MP-TOUTIAO || MP-QQ
		tempFilePath = `${uni.env.USER_DATA_PATH}/${fileName}`;
		// #endif

		console.log('[GenerationResult] 临时文件路径:', tempFilePath);

		const fs = uni.getFileSystemManager();
		await new Promise((resolve, reject) => {
			fs.writeFile({
				filePath: tempFilePath,
				data: base64Data,
				encoding: 'base64',
				success: () => {
					console.log('[GenerationResult] 文件写入成功');
					resolve();
				},
				fail: (error) => {
					console.error('[GenerationResult] 文件写入失败:', error);
					reject(new Error('保存临时文件失败'));
				}
			});
		});
		// #endif

		console.log('[GenerationResult] 开始上传到OSS，文件路径:', tempFilePath);

		// 上传到OSS
		imageUrl = await new Promise((resolve, reject) => {
			uni.uploadFile({
				url: signRes.data.host,
				filePath: tempFilePath,
				name: 'file',
				formData: {
					key: signRes.data.dir + fileName,
					policy: signRes.data.policy,
					success_action_status: '200',
					'x-oss-credential': signRes.data.x_oss_credential,
					'x-oss-date': signRes.data.x_oss_date,
					'x-oss-security-token': signRes.data.security_token,
					'x-oss-signature': signRes.data.signature,
					'x-oss-signature-version': signRes.data.x_oss_signature_version
				},
				success: (uploadRes) => {
					console.log('[GenerationResult] OSS上传响应:', uploadRes.statusCode);
					console.log('[GenerationResult] OSS上传完整响应:', uploadRes);

					if (uploadRes.statusCode === 200 || uploadRes.statusCode === 204) {
						const url = `${signRes.data.host}/${signRes.data.dir}${fileName}`;
						console.log('[GenerationResult] 上传成功，URL:', url);
						resolve(url);
					} else {
						reject(new Error(`上传失败，状态码: ${uploadRes.statusCode}`));
					}
				},
				fail: (error) => {
					console.error('[GenerationResult] OSS上传失败:', error);
					reject(error);
				}
			});
		});
		// #endif

		console.log('[GenerationResult] 上传成功，URL:', imageUrl);
		uni.hideLoading();
		uni.showToast({
			title: '上传成功',
			icon: 'success',
			duration: 1500
		});
		isUploading.value = false;
		return imageUrl;

	} catch (error) {
		console.error('[GenerationResult] 上传失败:', error);
		uni.hideLoading();
		uni.showToast({
			title: error.message || '上传失败',
			icon: 'none',
			duration: 2000
		});
		isUploading.value = false;
		throw error;
	}
};

// H5环境上传
const uploadToOssH5 = async (base64Image, fileName, ossData) => {
	return new Promise((resolve, reject) => {
		try {
			// 将base64转换为Blob
			const blob = base64ToBlob(base64Image);

			// 构建FormData
			const formData = new FormData();
			formData.append('key', ossData.dir + fileName);
			formData.append('policy', ossData.policy);
			formData.append('success_action_status', '200');
			formData.append('x-oss-credential', ossData.x_oss_credential);
			formData.append('x-oss-date', ossData.x_oss_date);
			formData.append('x-oss-security-token', ossData.security_token);
			formData.append('x-oss-signature', ossData.signature);
			formData.append('x-oss-signature-version', ossData.x_oss_signature_version);
			formData.append('file', blob, fileName);

			// 使用fetch上传
			fetch(resolveH5OssPostUrl(ossData.host), {
				method: 'POST',
				body: formData
			})
				.then(response => {
					if (response.ok) {
						const imageUrl = `${ossData.host}/${ossData.dir}${fileName}`;
						uni.hideLoading();
						uni.showToast({
							title: '上传成功',
							icon: 'success',
							duration: 1500
						});
						isUploading.value = false;
						resolve(imageUrl); // 只返回URL
					} else {
						throw new Error(`上传失败，状态码: ${response.status}`);
					}
				})
				.catch(error => {
					uni.hideLoading();
					isUploading.value = false;
					reject(error);
				});
		} catch (error) {
			uni.hideLoading();
			isUploading.value = false;
			reject(error);
		}
	});
};

// App/小程序环境上传
const uploadToOssNative = async (base64Image, fileName, ossData) => {
	console.log('[GenerationResult] uploadToOssNative 开始');
	console.log('[GenerationResult] fileName:', fileName);

	return new Promise((resolve, reject) => {
		try {
			// 去掉base64前缀
			const base64Data = base64Image.replace(/^data:image\/\w+;base64,/, '');
			console.log('[GenerationResult] base64数据长度:', base64Data.length);

			// #ifdef MP-WEIXIN
			// 微信小程序环境
			console.log('[GenerationResult] 使用微信小程序环境');
			const fs = uni.getFileSystemManager();
			const tempFilePath = `${wx.env.USER_DATA_PATH}/${fileName}`;
			console.log('[GenerationResult] 临时文件路径:', tempFilePath);

			fs.writeFile({
				filePath: tempFilePath,
				data: base64Data,
				encoding: 'base64',
				success: () => {
					console.log('[GenerationResult] 文件写入成功');
					uploadFileToOss(tempFilePath, fileName, ossData, resolve, reject, fs);
				},
				fail: (error) => {
					console.error('[GenerationResult] 保存临时文件失败:', error);
					uni.hideLoading();
					isUploading.value = false;
					reject(new Error('保存临时文件失败'));
				}
			});
			// #endif

			// #ifdef APP-PLUS
			// App环境
			console.log('[GenerationResult] 使用App环境');
			const fs = plus.io.getFileSystemManager ? uni.getFileSystemManager() : null;
			console.log('[GenerationResult] FileSystemManager:', fs ? '可用' : '不可用');

			if (!fs) {
				// 使用plus.io API
				console.log('[GenerationResult] 使用plus.io API');
				const tempFilePath = `_doc/${fileName}`;
				console.log('[GenerationResult] 临时文件路径:', tempFilePath);

				plus.io.resolveLocalFileSystemURL('_doc', (entry) => {
					console.log('[GenerationResult] 获取文件系统成功');
					entry.getFile(fileName, { create: true }, (fileEntry) => {
						console.log('[GenerationResult] 创建文件成功');
						fileEntry.createWriter((writer) => {
							writer.onwrite = () => {
								console.log('[GenerationResult] 文件写入成功');
								uploadFileToOss(fileEntry.toLocalURL(), fileName, ossData, resolve, reject, null);
							};
							writer.onerror = (error) => {
								console.error('[GenerationResult] 写入文件失败:', error);
								uni.hideLoading();
								isUploading.value = false;
								reject(new Error('写入文件失败'));
							};
							// 将base64转换为Blob
							console.log('[GenerationResult] 开始转换base64为Blob');
							try {
								const blob = base64ToBlob(base64Image);
								console.log('[GenerationResult] Blob创建成功，大小:', blob.size);
								writer.write(blob);
							} catch (blobError) {
								console.error('[GenerationResult] Blob转换失败:', blobError);
								uni.hideLoading();
								isUploading.value = false;
								reject(new Error('Blob转换失败'));
							}
						});
					}, (fileError) => {
						console.error('[GenerationResult] 创建文件失败:', fileError);
						uni.hideLoading();
						isUploading.value = false;
						reject(new Error('创建文件失败'));
					});
				}, (error) => {
					console.error('[GenerationResult] 获取文件系统失败:', error);
					uni.hideLoading();
					isUploading.value = false;
					reject(new Error('获取文件系统失败'));
				});
			} else {
				// 使用FileSystemManager API
				console.log('[GenerationResult] 使用FileSystemManager API');
				const tempFilePath = `${plus.io.getStorageRootPath()}${fileName}`;
				console.log('[GenerationResult] 临时文件路径:', tempFilePath);

				fs.writeFile({
					filePath: tempFilePath,
					data: base64Data,
					encoding: 'base64',
					success: () => {
						console.log('[GenerationResult] 文件写入成功');
						uploadFileToOss(tempFilePath, fileName, ossData, resolve, reject, fs);
					},
					fail: (error) => {
						console.error('[GenerationResult] 保存临时文件失败:', error);
						uni.hideLoading();
						isUploading.value = false;
						reject(new Error('保存临时文件失败'));
					}
				});
			}
			// #endif

		} catch (error) {
			console.error('[GenerationResult] uploadToOssNative异常:', error);
			uni.hideLoading();
			isUploading.value = false;
			reject(error);
		}
	});
};

// 统一的文件上传逻辑
const uploadFileToOss = (tempFilePath, fileName, ossData, resolve, reject, fs) => {
	console.log('[GenerationResult] uploadFileToOss 开始');
	console.log('[GenerationResult] tempFilePath:', tempFilePath);
	console.log('[GenerationResult] OSS host:', ossData.host);

	uni.uploadFile({
		url: ossData.host,
		filePath: tempFilePath,
		name: 'file',
		formData: {
			key: ossData.dir + fileName,
			policy: ossData.policy,
			success_action_status: '200',
			'x-oss-credential': ossData.x_oss_credential,
			'x-oss-date': ossData.x_oss_date,
			'x-oss-security-token': ossData.security_token,
			'x-oss-signature': ossData.signature,
			'x-oss-signature-version': ossData.x_oss_signature_version
		},
		success: (uploadRes) => {
			console.log('[GenerationResult] OSS上传响应:', uploadRes);
			console.log('[GenerationResult] 状态码:', uploadRes.statusCode);

			if (uploadRes.statusCode === 200 || uploadRes.statusCode === 204) {
				const imageUrl = `${ossData.host}/${ossData.dir}${fileName}`;
				console.log('[GenerationResult] 上传成功，图片URL:', imageUrl);

				// 删除临时文件
				if (fs) {
					fs.unlink({
						filePath: tempFilePath,
						success: () => console.log('[GenerationResult] 临时文件已删除'),
						fail: (err) => console.error('[GenerationResult] 删除临时文件失败:', err)
					});
				}

				resolve(imageUrl);
			} else {
				console.error('[GenerationResult] 上传失败，状态码:', uploadRes.statusCode);
				reject(new Error(`上传失败，状态码: ${uploadRes.statusCode}`));
			}
		},
		fail: (error) => {
			console.error('[GenerationResult] OSS上传失败:', error);
			reject(error);
		}
	});
};

const getSelectedImageUrl = () => {
	if (isLenticularDisplay.value) {
		const mid = lenticularLayers.value.find((l) => l.id === 'mid');
		return mid?.src || craftFormData.value?.lenticularSubjectImage || '';
	}
	if (selectedIndex.value < 0) return '';
	return generatedImages.value[selectedIndex.value] || '';
};

// 选择藏品
const selectAsset = async () => {
	const imagePath =
		isLenticularDisplay.value
			? lenticularLayers.value.find((l) => l.id === 'mid')?.src || ''
			: '';
	const bgImagePath = isLenticularDisplay.value
		? lenticularLayers.value.find((l) => l.id === 'base')?.src || ''
		: undefined;

	console.log('[selectAsset] start', {
		isLenticularDisplay: isLenticularDisplay.value,
		imagePath: imagePath ? 'has' : 'empty',
		bgImagePath: bgImagePath ? 'has' : 'empty',
		lenticularLayers: lenticularLayers.value.map(l => ({ id: l.id, src: l.src ? l.src.substring(0, 50) : '' })),
	})

	if (!imagePath) {
		uni.showToast({ title: '缺少作品图', icon: 'none' });
		return;
	}

	// 获取铸造费用估算
	try {
		uni.showLoading({ title: '加载中…', mask: true });
		const costRes = await estimateMintCostApi();
		uni.hideLoading();

		if (costRes.code === 0 && costRes.data) {
			confirmCostInfo.value = {
				costCrystal: costRes.data.cost_crystal || 0,
				currentBalance: costRes.data.current_balance || 0,
				mintCount: costRes.data.mint_count || 0,
				nextTierCost: costRes.data.next_tier_cost || '',
			};

		} else {
			confirmCostInfo.value = {
				costCrystal: 100,
				currentBalance: 0,
				mintCount: 0,
				nextTierCost: 0,
			};
		}
	} catch (e) {
		uni.hideLoading();
		console.error('[selectAsset] 获取铸造费用失败:', e);
		confirmCostInfo.value = {
			costCrystal: 100,
			currentBalance: 0,
			mintCount: 0,
			nextTierCost: 0,
		};
	}

	// 显示确认弹窗
	showConfirmModal.value = true;
};

// 确认铸造
const handleConfirmMint = async () => {
	showConfirmModal.value = false;

	// 检查余额是否充足
	if (confirmCostInfo.value.currentBalance < confirmCostInfo.value.costCrystal) {
		uni.showToast({ title: '水晶余额不足，无法铸造', icon: 'none' });
		return;
	}

	const imagePath =
		isLenticularDisplay.value
			? lenticularLayers.value.find((l) => l.id === 'mid')?.src || ''
			: '';
	const bgImagePath = isLenticularDisplay.value
		? lenticularLayers.value.find((l) => l.id === 'base')?.src || ''
		: undefined;

	uni.showLoading({ title: '铸造中…', mask: true });
	try {
		await submitCraftMintFromPath({ imagePath, bgImagePath, formData: craftFormData.value });
		// 只有铸造成功后才扣除本地余额
		updateLocalBalance(confirmCostInfo.value.balanceAfter);
		uni.hideLoading();
		uni.navigateTo({ url: '/pages/castlove/success' });
	} catch (e) {
		uni.hideLoading();
		uni.showToast({ title: e.message || '铸造失败', icon: 'none' });
	}
};

// 取消铸造
const handleCancelMint = () => {
	showConfirmModal.value = false;
};

const initLenticularPreview = () => {
	try {
		const raw = uni.getStorageSync(LENTICULAR_STUDIO_STORAGE_KEY);
		if (!raw) {
			return;
		}
		const p = typeof raw === 'string' ? JSON.parse(raw) : raw;
		const bgPath = p.bgPath || '';
		const subjectPath = p.subjectPath || '';
		lenticularLayers.value = buildLenticularLayersTwo(bgPath, subjectPath);
		selectedIndex.value = 0;
		scheduleTiltStart();
	} catch (e) {
		console.error('[GenerationResult] lenticular init', e);
	}
};

onMounted(() => {
	try {
		const formDataStr = uni.getStorageSync(CASTLOVE_FORM_KEY);
		if (formDataStr) {
			craftFormData.value = JSON.parse(formDataStr);
		}
		const metaStr = uni.getStorageSync(GENERATION_RESULT_META_KEY);
		if (metaStr) {
			resultMeta.value = JSON.parse(metaStr);
			uni.removeStorageSync(GENERATION_RESULT_META_KEY);
		}
	} catch (e) {
		console.error('[GenerationResult] 读取表单失败:', e);
	}

	try {
		const imagesData = uni.getStorageSync(GENERATED_IMAGES_KEY);
		if (!imagesData) {
			uni.showToast({ title: '未找到生成的图片', icon: 'none' });
			setTimeout(() => uni.navigateTo({
				url: '/pages/castlove/lenticular/lenticular-create'
			}), 1500);
			return;
		}
		const parsed = JSON.parse(imagesData);
		uni.removeStorageSync(GENERATED_IMAGES_KEY);

		if (isLenticularDisplay.value || (parsed[0] && parsed[0].type === 'lenticular')) {
			initLenticularPreview();
		} else {
			generatedImages.value = parsed;
			if (generatedImages.value.length > 0) {
				selectedIndex.value = 0;
			}
		}

		setTimeout(() => {
			isGiftOpened.value = true;
		}, 800);
	} catch (e) {
		console.error('[GenerationResult] 读取图片数据失败:', e);
		uni.showToast({ title: '数据错误', icon: 'none' });
		setTimeout(() => uni.navigateTo({
			url: '/pages/castlove/lenticular/lenticular-create'
		}), 1500);
	}
});

onShow(() => {
	if (isLenticularDisplay.value && lenticularLayers.value.length) {
		scheduleTiltStart();
	}
});

onHide(() => {
	stopTiltPreview();
});

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

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

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

.stars-container {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	z-index: 2;
	pointer-events: none;
}

.star {
	position: absolute;
	background: #FFFFFF;
	border-radius: 50%;
	animation: starTwinkle 2s ease-in-out infinite;
	box-shadow: 0 0 10rpx rgba(255, 255, 255, 0.8);
}

@keyframes starTwinkle {

	0%,
	100% {
		opacity: 0.3;
		transform: scale(1);
	}

	50% {
		opacity: 1;
		transform: scale(1.2);
	}
}

.reward-tips {
	position: absolute;
	top: 80rpx;
	left: 50%;
	transform: translateX(-50%);
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 16rpx;
	z-index: 11;
	padding: 0 40rpx;
}

.reward-item {
	background: transparent;
	white-space: nowrap;
	display: flex;
	align-items: center;
	gap: 12rpx;
}

.reward-icon {
	width: 40rpx;
	height: 40rpx;
	flex-shrink: 0;
}

.reward-text {
	font-size: 28rpx;
	color: #FFFFFF;
	font-weight: 600;
	text-shadow:
		0 2rpx 8rpx rgba(0, 0, 0, 0.6),
		0 0 20rpx rgba(255, 107, 157, 0.5);
	white-space: nowrap;
}

.cards-container {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	z-index: 10;
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.5s ease-in-out;
}

.cards-container.cards-visible {
	opacity: 1;
	pointer-events: auto;
}

.card-item {
	position: absolute;
	width: 200rpx;
	height: 260rpx;
	transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1);
	cursor: pointer;
	filter: drop-shadow(0 15rpx 40rpx rgba(0, 0, 0, 0.5));
	transform: scale(0) translateY(100rpx);
	opacity: 0;
}

.cards-visible .card-item {
	animation: cardAppear 0.8s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
	opacity: 1;
}

@keyframes cardAppear {
	0% {
		transform: scale(0) translateY(100rpx);
		opacity: 0;
	}

	100% {
		transform: scale(1) translateY(0);
		opacity: 1;
	}
}

.card-item:active:not(.card-selected) {
	opacity: 0.8;
}

.cards-visible .card-item:nth-child(1) {
	animation-delay: 0s, 0.8s;
}

.cards-visible .card-item:nth-child(2) {
	animation-delay: 0.15s, 0.95s;
}

.cards-visible .card-item:nth-child(3) {
	animation-delay: 0.3s, 1.1s;
}

.cards-visible .card-item:nth-child(4) {
	animation-delay: 0.45s, 1.25s;
}

.cards-visible .card-item:nth-child(5) {
	animation-delay: 0.6s, 1.4s;
}

@keyframes cardFloat {

	0%,
	100% {
		transform: translateY(0) rotate(var(--rotate, 0deg));
	}

	50% {
		transform: translateY(-20rpx) rotate(var(--rotate, 0deg));
	}
}

.card-frame {
	position: relative;
	width: 100%;
	height: 100%;
	overflow: visible;
}

.topfans-label {
	position: absolute;
	top: 15rpx;
	left: 15rpx;
	background: linear-gradient(135deg, #A855FF 0%, #D946EF 100%);
	padding: 8rpx 20rpx;
	border-radius: 30rpx;
	z-index: 10;
	box-shadow: 0 4rpx 15rpx rgba(168, 85, 255, 0.5);
}

.topfans-text {
	font-size: 22rpx;
	font-weight: bold;
	color: #FFFFFF;
	letter-spacing: 1rpx;
	text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.3);
}

.card-image {
	width: 100%;
	height: 100%;
	border-radius: 14rpx;
	display: block;
	position: relative;
	z-index: 1;
	object-fit: cover;
}

.card-shine {
	position: absolute;
	top: 0;
	left: -100%;
	width: 100%;
	height: 100%;
	background: linear-gradient(90deg,
			transparent 0%,
			rgba(255, 255, 255, 0.5) 50%,
			transparent 100%);
	animation: shine 3s ease-in-out infinite;
}

@keyframes shine {
	0% {
		left: -100%;
	}

	50%,
	100% {
		left: 100%;
	}
}

.topfans-badge {
	position: absolute;
	top: 20rpx;
	left: 20rpx;
	width: 80rpx;
	height: 80rpx;
	filter: drop-shadow(0 2rpx 8rpx rgba(255, 107, 157, 0.5));
}

.card-label {
	position: absolute;
	top: 24rpx;
	right: 20rpx;
	padding: 8rpx 16rpx;
	background: rgba(255, 107, 157, 0.9);
	border-radius: 20rpx;
}

.label-text {
	font-size: 20rpx;
	color: #FFFFFF;
	font-weight: bold;
}

.card-title {
	position: absolute;
	bottom: 20rpx;
	left: 20rpx;
	right: 20rpx;
	padding: 12rpx;
	background: rgba(0, 0, 0, 0.6);
	border-radius: 12rpx;
	backdrop-filter: blur(10rpx);
}

.title-text {
	font-size: 22rpx;
	color: #FFFFFF;
	font-weight: 600;
	text-align: center;
	display: block;
}

.heart-icon {
	position: absolute;
	top: 20rpx;
	right: 20rpx;
	width: 40rpx;
	height: 40rpx;
}

.selected-mark {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	width: 100rpx;
	height: 100rpx;
	background: linear-gradient(135deg, #00D4FF 0%, #0099FF 100%);
	border-radius: 50%;
	display: flex;
	align-items: center;
	justify-content: center;
	box-shadow:
		0 0 30rpx rgba(0, 212, 255, 0.8),
		0 8rpx 30rpx rgba(0, 0, 0, 0.4);
	animation: checkPop 0.3s ease-out;
	border: 4rpx solid rgba(255, 255, 255, 0.9);
	z-index: 10;
}

@keyframes checkPop {
	0% {
		transform: translate(-50%, -50%) scale(0);
	}

	50% {
		transform: translate(-50%, -50%) scale(1.2);
	}

	100% {
		transform: translate(-50%, -50%) scale(1);
	}
}

.check-icon {
	font-size: 70rpx;
	color: #FFFFFF;
	font-weight: bold;
	text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.3);
}

.card-selected {
	z-index: 100 !important;
}

.gift-box {
	position: absolute;
	bottom: 20%;
	left: 50%;
	transform: translateX(-50%);
	width: 480rpx;
	height: 480rpx;
	z-index: 3;
	animation: giftFloat 3s ease-in-out infinite;
	transition: all 0.8s cubic-bezier(0.4, 0, 0.2, 1);
}

.gift-box.gift-opened {
	width: 17rem;
	bottom: 15%;
	animation: none;
}

@keyframes giftFloat {

	0%,
	100% {
		transform: translateX(-50%) translateY(0);
	}

	50% {
		transform: translateX(-50%) translateY(-20rpx);
	}
}

.gift-image {
	width: 100%;
	height: 100%;
	transition: opacity 0.5s ease-in-out;
}

.gift-image-opened {
	width: 17rem;
	animation: giftOpenPop 0.5s ease-out;
}

@keyframes giftOpenPop {
	0% {
		transform: scale(0.8);
		opacity: 0;
	}

	50% {
		transform: scale(1.1);
	}

	100% {
		transform: scale(1);
		opacity: 1;
	}
}

.lenticular-result-wrap {
	position: absolute;
	top: 200rpx;
	left: 0;
	right: 0;
	display: flex;
	justify-content: center;
	z-index: 8;
	opacity: 0;
	transform: translateY(40rpx);
	transition: opacity 0.6s ease, transform 0.6s ease;
}

.lenticular-result-wrap.cards-visible {
	opacity: 1;
	transform: translateY(0);
}

.lenticular-result-card {
	display: flex;
	flex-direction: column;
	align-items: center;
}

.lenticular-result-card .card-wrapper {
	position: relative;
	width: 352rpx;
	height: 520rpx;
}

.lenticular-result-card .craft-card-wrapper {
	margin-bottom: 32rpx;
}

.lenticular-result-card .card-frame {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	z-index: 2;
	transform: rotate(-10deg);
}

.lenticular-result-card .craft-lenticular-slot {
	position: absolute;
	left: 50%;
	top: 50%;
	width: 87%;
	height: 96%;
	border-radius: 48rpx;
	transform: translate(-50%, -50%) rotate(-10deg);
	z-index: 2;
	overflow: hidden;
}

.lenticular-result-card .craft-lenticular-card {
	width: 100%;
	height: 100%;
}

.bottom-action {
	position: absolute;
	bottom: 80rpx;
	left: 50%;
	transform: translateX(-50%);
	display: flex;
	flex-direction: column;
	align-items: center;
	z-index: 11;
}

.bottom-action--row {
	flex-direction: row;
	gap: 24rpx;
	width: 90%;
	justify-content: center;
}

.action-button {
	padding: 24rpx 80rpx;
	background: linear-gradient(90deg, #FF6B9D 0%, #FFA8C5 100%);
	border-radius: 50rpx;
	box-shadow: 0 8rpx 24rpx rgba(255, 107, 157, 0.5);
	cursor: pointer;
	user-select: none;
	-webkit-user-select: none;
	-webkit-tap-highlight-color: transparent;
	display: flex;
	align-items: center;
	justify-content: center;
}

.action-button:active {
	transform: scale(1.05);
	opacity: 0.9;
}

.action-button--secondary {
	background: linear-gradient(90deg, #8e9eab 0%, #b8c6db 100%);
	box-shadow: 0 8rpx 24rpx rgba(120, 130, 150, 0.45);
}

.button-text {
	font-size: 32rpx;
	color: #FFFFFF;
	font-weight: bold;
	text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.2);
	white-space: nowrap;
	line-height: 1.2;
}

.hint-text {
	font-size: 24rpx;
	color: rgba(255, 255, 255, 0.7);
	text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.3);
}
</style>
