<template>
	<view v-if="props.visible" class="share-modal-overlay" @tap.self="handleClose">
		<view class="share-modal" @tap.stop>
			<view class="header">
				<text class="title">分享藏品</text>
				<view class="close" @tap="handleClose">✕</view>
			</view>

			<view v-if="!isLoggedIn" class="login-gate">
				<text class="lock-icon">🔒</text>
				<text class="lock-text">登录后才能分享</text>
				<view class="login-actions">
					<button class="btn-secondary" @tap="handleClose">再看看</button>
					<button class="btn-primary" @tap="goLogin">去登录</button>
				</view>
			</view>

			<template v-else>
				<SharePreviewCard :coverUrl="coverUrl" :avatarUrl="avatarUrl" :qrcodeUrl="qrcodeUrl"
					:nickname="nickname" :slogan="currentSlogan" />

				<view v-if="state === 'composing'" class="overlay">
					<view class="spinner" />
					<text>正在生成图片...</text>
				</view>

				<ShareActionBar @pick="pick" />

				<view class="degrade-link" @tap="copyLink">
					<text class="degrade-icon">🔗</text>
					<text class="degrade-text">复制链接，分享到更多平台</text>
				</view>
			</template>
		</view>

		<!-- canvas 必须放 page 级(app-plus 组件内 canvas 不被 createCanvasContext 识别)
		     如果父页面有传 externalCanvasId,这里就不挂 canvas,否则兜底挂一个(可能仍不工作)
		     ⚠️ width/height 是 HTML 属性(决定 native canvas 绘图表面尺寸),不是 CSS。
		     CSS 设的尺寸 + display:none 会让 surface 尺寸 = 0,触发 'InvalidStateError: width or height of 0' -->
		<canvas
			v-if="!externalCanvasId"
			canvas-id="shareCanvas"
			id="shareCanvas"
			:width="750"
			:height="1334"
			class="share-canvas"
		/>
	</view>
</template>

<script setup>
import { ref, computed, watch, getCurrentInstance } from 'vue';
import SharePreviewCard from './SharePreviewCard.vue';
import ShareActionBar from './ShareActionBar.vue';
import { useShare } from '@/composables/useShare.js';
import { useAliveGuard } from '@/composables/useAliveGuard.js';
import { LANDING_BASE, SHARE_TARGETS } from '@/utils/constants.js';
import { trackShareApi } from '@/utils/api.js';

const props = defineProps({
	visible: { type: Boolean, default: false },
	coverUrl: { type: String, required: true },
	qrcodeUrl: { type: String, default: '' },
	avatarUrl: { type: String, default: '' },
	nickname: { type: String, default: '' },
	assetId: { type: [Number, String], required: true },
	// 链上哈希(由父组件 asset-detail 提供,转发给 useShare → image-compositor)
	displayTxHash: { type: String, default: '' },
	// 可选:外部 page 级 canvasId(uni-app 组件内 canvas 跨端不稳,推荐父页面提供)
	externalCanvasId: { type: String, default: '' }
});
console.log('[ShareModal] setup props:', { visible: props.visible, coverUrl: props.coverUrl, qrcodeUrl: props.qrcodeUrl, avatarUrl: props.avatarUrl, assetId: props.assetId });
const emit = defineEmits(['close']);

const visibleLocal = ref(props.visible);
watch(() => props.visible, (v) => { visibleLocal.value = v; });
const isLoggedIn = computed(() => {
	try { return !!JSON.parse(uni.getStorageSync('user') || '{}').uid; } catch { return false; }
});

const { state, pick, currentSlogan, systemType } = useShare({
	// 关键:用 getter functions 读 props,避免 setup snapshot 问题
	// (useShare 在 setup 时调用一次,如果直接传 props.coverUrl 会拿到空字符串)
	getCoverUrl:  () => props.coverUrl,
	getQrcodeUrl: () => props.qrcodeUrl,
	getAvatarUrl: () => props.avatarUrl,
	getNickname:  () => props.nickname,
	getAssetId:   () => props.assetId,
	getDisplayTxHash: () => props.displayTxHash,
	// app-plus canvas API 第二个参数需要页面级 vm,getCurrentPages() 当前页是最稳的
	vm: (() => {
		try {
			const pages = getCurrentPages();
			return pages[pages.length - 1];
		} catch { return null; }
	})(),
	canvasId: props.externalCanvasId || 'shareCanvas'
});

// ShareModal 自己的异步回调(uni.setClipboardData)也需要守卫
// useShare 内部已自带守卫,这里只覆盖 ShareModal 自己的路径
const { guard } = useAliveGuard();

watch(() => props.visible, (v) => { visibleLocal.value = v; });

function handleClose() { emit('close'); visibleLocal.value = false; }
function goLogin() { emit('close'); visibleLocal.value = false; uni.navigateTo({ url: '/pages/login/login' }); }
function copyLink() {
	// 兜底:系统类型未就绪时给个 'other'(与后端 QR 接口校验一致)
	const os = systemType.value || 'other';
	// 当前用户 uid(分享归因 from 参数),从本地存储读取;未登录则不附带
	let from = '';
	let uid = 0;
	try {
		const userStr = uni.getStorageSync('user');
		if (userStr) {
			const userInfo = JSON.parse(userStr);
			const rawUid = userInfo?.uid || userInfo?.user_id;
			from = String(rawUid || '');
			uid = Number(rawUid) || 0;
		}
	} catch (e) {
		console.warn('[ShareModal] parse current user for copyLink failed:', e);
	}

	// URL 格式与后端 QR 码接口(spec § 3)保持一致:
	//   {LANDING_BASE}/asset/{id}?from={uid}&s={system}
	// 这样扫描二维码 / 复制链接命中同一落地页规则,后端归因、路由解析都走一套
	const params = [`s=${encodeURIComponent(os)}`];
	if (from) params.push(`from=${encodeURIComponent(from)}`);
	// share_target 用枚举常量(后端已接收 copy_link,见 share_service.validShareTargets)
	params.push(`share_target=${SHARE_TARGETS.COPY_LINK}`);
	const url = `${LANDING_BASE}/asset/${encodeURIComponent(props.assetId)}?${params.join('&')}`;

	uni.setClipboardData({
		data: url,
		success: guard(() => {
			uni.showToast({ title: '链接已复制' });
			// 上报埋点:让"复制链接"与图形分享走同一统计通道
			// 失败不阻塞用户(已成功复制,埋点只是辅助)
			const assetIdNum = Number(props.assetId) || 0;
			if (assetIdNum > 0 && uid > 0) {
				trackShareApi({
					asset_id: assetIdNum,
					sharer_user_id: uid,
					system_type: os,
					share_target: SHARE_TARGETS.COPY_LINK,
					result: 'success',
					client_ts: Date.now()
				}).catch((e) => {
					console.warn('[ShareModal] trackShare(copy_link) failed:', e);
				});
			}
		}),
		fail: guard(() => {
			uni.showToast({ title: '复制失败', icon: 'none' });
		})
	});
}
</script>

<style lang="scss" scoped>
.share-modal-overlay {
	position: fixed;
	inset: 0;
	background: rgba(0, 0, 0, .55);
	z-index: 999;
	display: flex;
	align-items: flex-end;
	justify-content: center;
}

.share-modal {
	width: 100%;
	background: #fff;
	border-radius: 24rpx 24rpx 0 0;
	padding: 32rpx 24rpx;
	position: relative;
	inset: 0;
	min-height: 700rpx;
	max-height: 90vh;
	overflow-y: auto;
}

.header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin-bottom: 24rpx;
}

.title {
	font-size: 32rpx;
	font-weight: 600;
}

.close {
	font-size: 36rpx;
	padding: 8rpx 16rpx;
}

.login-gate {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 24rpx;
	padding: 80rpx 0;
}

.lock-icon {
	font-size: 80rpx;
}

.lock-text {
	font-size: 28rpx;
	color: #666;
}

.login-actions {
	display: flex;
	gap: 24rpx;
}

.btn-secondary,
.btn-primary {
	font-size: 28rpx;
	padding: 16rpx 48rpx;
	border-radius: 48rpx;
}

.btn-secondary {
	background: #f5f5f5;
	color: #333;
}

.btn-primary {
	background: #07C160;
	color: #fff;
}

.overlay {
	position: absolute;
	inset: 0;
	background: rgba(255, 255, 255, .85);
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 16rpx;
}

.spinner {
	width: 64rpx;
	height: 64rpx;
	border: 6rpx solid #ddd;
	border-top-color: #07C160;
	border-radius: 50%;
	animation: spin 1s linear infinite;
}

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

.degrade-link {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 12rpx;
	padding: 24rpx 0;
	margin-top: 8rpx;
}

.degrade-icon {
	font-size: 32rpx;
	line-height: 1;
}

.degrade-text {
	font-size: 28rpx;
	color: #576b95;
	text-decoration: underline;
}

/* 离屏 canvas — 不能用 display:none(会让 layout 尺寸=0,native canvas surface 跟着=0),
   用 position:fixed + 负坐标推到视口外,layout 尺寸保留,canvas surface 正常 */
.share-canvas {
	position: fixed;
	left: -9999px;
	top: -9999px;
	width: 750px;
	height: 1334px;
	pointer-events: none;
}
</style>
