<template>
	<view class="detail-page">
		<view v-if="pageLoading" class="detail-loading">
			<u-loading-icon mode="circle" text="加载中" />
		</view>
		<view v-else-if="loadFailed" class="detail-loading">
			<u-empty mode="data" text="商品不存在或已失效" icon-size="80" />
		</view>
		<template v-else-if="detail">
			<scroll-view class="detail-scroll" scroll-y :style="{ height: scrollHeight }">
				<!-- 图片轮播 -->
				<swiper
					class="pic-swiper"
					:indicator-dots="detail.pics.length > 1"
					indicator-color="rgba(255,255,255,0.5)"
					indicator-active-color="#fff"
					:circular="detail.pics.length > 1"
				>
					<swiper-item v-for="(pic, idx) in detail.pics" :key="idx">
						<image class="pic-swiper__img" :src="pic" mode="aspectFill" @click="previewPics(idx)" />
					</swiper-item>
				</swiper>

				<!-- 状态提示 -->
				<view v-if="statusTip" class="status-tip">
					<text>{{ statusTip }}</text>
				</view>

				<!-- 基本信息 -->
				<view class="card price-card">
					<view class="price-row">
						<text class="price-symbol">¥</text>
						<text class="price-num">{{ detail.priceText }}</text>
					</view>
					<text class="goods-name">{{ detail.goodsName }}</text>
					<text v-if="detail.goodsBrief" class="goods-brief">{{ detail.goodsBrief }}</text>
					<view class="meta-row">
						<text v-if="detail.categoryPath" class="meta-item">{{ detail.categoryPath }}</text>
						<text class="meta-item">库存 {{ detail.stock }}</text>
						<text class="meta-item">销量 {{ detail.salesCount != null ? detail.salesCount : '—' }}</text>
					</view>
				</view>

				<!-- 数量选择（v1 统一规格） -->
				<view class="card cell-row" @click="openQtyPopup">
					<text class="cell-label">数量</text>
					<text class="cell-value">{{ quantity }} 件</text>
					<u-icon name="arrow-right" color="#ccc" size="14" />
				</view>

				<!-- 商品参数 -->
				<view v-if="detail.attributes.length" class="card section-card">
					<view class="section-title">商品参数</view>
					<view v-for="(attr, i) in detail.attributes" :key="i" class="attr-row">
						<text class="attr-name">{{ attr.itemName }}</text>
						<text class="attr-val">{{ formatAttrValues(attr.values) }}</text>
					</view>
				</view>

				<!-- 展示规格（只读，v1 不参与 SKU） -->
				<view v-if="detail.specDisplay.length" class="card section-card">
					<view class="section-title">规格信息</view>
					<view v-for="(spec, i) in detail.specDisplay" :key="'s' + i" class="attr-row">
						<text class="attr-name">{{ spec.itemName }}</text>
						<text class="attr-val">{{ formatAttrValues(spec.values) }}</text>
					</view>
				</view>

				<!-- 物流说明 -->
				<view v-if="hasLogistics" class="card section-card">
					<view class="section-title">物流说明</view>
					<view v-if="detail.logistics.shipPromise" class="info-line">
						<text class="info-label">发货承诺</text>
						<text>{{ detail.logistics.shipPromise }}</text>
					</view>
					<view v-if="detail.logistics.freightDesc" class="info-line">
						<text class="info-label">运费</text>
						<text>{{ detail.logistics.freightDesc }}</text>
					</view>
					<view v-if="detail.logistics.shipCity" class="info-line">
						<text class="info-label">发货地</text>
						<text>{{ detail.logistics.shipCity }}</text>
					</view>
				</view>

				<!-- 服务说明 -->
				<view v-if="detail.services.length" class="card section-card">
					<view class="section-title">服务说明</view>
					<view v-for="svc in detail.services" :key="svc.serviceId" class="service-item">
						<image v-if="svc.serviceIcon" class="service-icon" :src="svc.serviceIcon" mode="aspectFit" />
						<view class="service-body">
							<text class="service-name">{{ svc.serviceName }}</text>
							<text v-if="svc.serviceIntro" class="service-intro">{{ svc.serviceIntro }}</text>
						</view>
					</view>
				</view>

				<!-- 评价摘要 -->
				<view class="card section-card">
					<view class="section-head">
						<text class="section-title">商品评价</text>
						<text v-if="reviewTotal > 0" class="section-more" @click="goAllReviews">查看全部 ></text>
					</view>
					<view v-if="reviewLoading" class="review-loading">
						<u-loading-icon mode="circle" size="18" />
					</view>
					<template v-else-if="reviewPreview.length">
						<review-card v-for="r in reviewPreview" :key="r.reviewId" :item="r" />
					</template>
					<text v-else class="empty-text">暂无评价</text>
				</view>

				<!-- 售后服务 -->
				<view class="card section-card">
					<view class="section-title">售后服务</view>
					<text class="after-sale-text">{{ afterSaleText }}</text>
				</view>

				<!-- 图文详情 -->
				<view class="card section-card">
					<view class="section-title">图文详情</view>
					<view v-if="detail.detailContent" class="rich-wrap">
						<rich-text :nodes="detail.detailContent" />
					</view>
					<text v-else class="empty-text">暂无详情</text>
				</view>

				<!-- 店铺入口 -->
				<view class="card shop-card" @click="onEnterShop">
					<image class="shop-avatar" :src="detail.shop.shopAvatar" mode="aspectFill" />
					<view class="shop-info">
						<text class="shop-name">{{ detail.shop.shopName || '—' }}</text>
						<text class="shop-enter">进店逛逛 ></text>
					</view>
				</view>

				<view class="scroll-bottom-gap" />
			</scroll-view>

			<detail-bottom-bar
				:disabled="!canOperate"
				:busy="tradeLocked"
				@shop="onEnterShop"
				@cart="onAddCart"
				@buy="onBuyNow"
			/>
		</template>

		<!-- 数量弹层 -->
		<u-popup :show="qtyPopupShow" mode="bottom" round="16" @close="qtyPopupShow = false">
			<view class="qty-popup">
				<view class="qty-popup__head">
					<image class="qty-popup__pic" :src="detail?.pics?.[0]" mode="aspectFill" />
					<view>
						<text class="qty-popup__price">¥ {{ detail?.priceText }}</text>
						<text class="qty-popup__stock">库存 {{ detail?.stock }}</text>
					</view>
				</view>
				<view class="qty-popup__row">
					<text>购买数量</text>
					<u-number-box
						v-model="quantity"
						:min="1"
						:max="maxQuantity"
						integer
					/>
				</view>
				<button class="qty-popup__btn" :disabled="tradeLocked" @click="confirmQty">确定</button>
			</view>
		</u-popup>
	</view>
</template>

<script setup>
import { ref, computed } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { getGoodsDetail, getGoodsReviews } from '@/api/goods'
import {
	mapGoodsDetail,
	mapReviewList,
	buildAfterSaleText,
	formatSpecDisplayText
} from '@/utils/goodsDetail'
import { ensureCanPurchase } from '@/utils/purchaseAction'
import { addCartItem } from '@/api/cart'
import { PAGE_GOODS_REVIEWS, PAGE_CHECKOUT } from '@/utils/pageRoute'
import { goShopHome } from '@/utils/shopNav'
import ReviewCard from '@/components/goods/ReviewCard.vue'
import { useActionGuard } from '@/utils/actionGuard'
import DetailBottomBar from '@/components/goods/DetailBottomBar.vue'

/** locked 须解构为顶层 ref，模板里才能正确解包为 boolean（见 cart/index.vue） */
const { locked: tradeLocked, run: runTradeAction } = useActionGuard()

const goodsId = ref('')
const detail = ref(null)
const pageLoading = ref(true)
const loadFailed = ref(false)
const scrollHeight = ref('600px')
const quantity = ref(1)
const qtyPopupShow = ref(false)
const pendingAction = ref('')

const reviewPreview = ref([])
const reviewTotal = ref(0)
const reviewLoading = ref(false)

const maxQuantity = computed(() => {
	const s = detail.value?.stock
	return s > 0 ? s : 1
})

const afterSaleText = computed(() => {
	if (!detail.value) return ''
	return buildAfterSaleText(detail.value.afterSalePhone)
})

const hasLogistics = computed(() => {
	const l = detail.value?.logistics
	if (!l) return false
	return !!(l.shipPromise || l.freightDesc || l.shipCity)
})

const statusTip = computed(() => {
	if (!detail.value) return ''
	if (detail.value.isOffShelf) return '商品已下架'
	if (!detail.value.isOnSale) return detail.value.goodsStatusLabel || '商品不可购买'
	if (!detail.value.purchase.allowed && detail.value.purchase.reason) {
		return detail.value.purchase.reason
	}
	if (detail.value.stock <= 0) return '当前商品库存不足'
	return ''
})

const canOperate = computed(() => {
	if (!detail.value) return false
	if (!detail.value.isOnSale || detail.value.isOffShelf) return false
	if (detail.value.stock <= 0) return false
	if (!detail.value.purchase.allowed) return false
	return true
})

function calcScrollHeight() {
	try {
		const sys = uni.getSystemInfoSync()
		const h = sys.windowHeight || 600
		scrollHeight.value = `${h - 56}px`
	} catch (e) {
		scrollHeight.value = '600px'
	}
}

function formatAttrValues(values) {
	if (!values || !values.length) return '—'
	return values.join('、')
}

async function loadDetail() {
	pageLoading.value = true
	loadFailed.value = false
	try {
		const res = await getGoodsDetail(goodsId.value)
		detail.value = mapGoodsDetail(res.data)
		if (!detail.value) {
			loadFailed.value = true
		}
	} catch (e) {
		loadFailed.value = true
		detail.value = null
	} finally {
		pageLoading.value = false
	}
}

async function loadReviewPreview() {
	reviewLoading.value = true
	try {
		const res = await getGoodsReviews(goodsId.value, { pageNum: 1, pageSize: 2 })
		reviewPreview.value = mapReviewList(res.rows || [])
		reviewTotal.value = Number(res.total) || reviewPreview.value.length
	} catch (e) {
		reviewPreview.value = []
		reviewTotal.value = 0
	} finally {
		reviewLoading.value = false
	}
}

function previewPics(index) {
	const urls = detail.value?.pics || []
	uni.previewImage({ urls, current: urls[index] })
}

function openQtyPopup() {
	if (!detail.value) return
	qtyPopupShow.value = true
}

function confirmQty() {
	runTradeAction(async () => {
		qtyPopupShow.value = false
		const action = pendingAction.value
		pendingAction.value = ''
		if (action === 'cart') {
			await doAddCart()
		} else if (action === 'buy') {
			await doBuyNow()
		}
	})
}

async function onAddCart() {
	if (!canOperate.value) {
		showBlockReason()
		return
	}
	pendingAction.value = 'cart'
	if (quantity.value > 1) {
		openQtyPopup()
		return
	}
	runTradeAction(() => doAddCart())
}

async function doAddCart() {
	const ok = await ensureCanPurchase(goodsId.value, detail.value?.purchase?.reason)
	if (!ok) return
	const specText = formatSpecDisplayText(detail.value?.specDisplay)
	try {
		await addCartItem({
			goodsId: goodsId.value,
			quantity: quantity.value,
			specText
		})
		uni.showToast({ title: '已加入购物车', icon: 'success' })
	} catch (e) {
		// request 已 Toast
	}
}

async function onBuyNow() {
	if (!canOperate.value) {
		showBlockReason()
		return
	}
	pendingAction.value = 'buy'
	openQtyPopup()
}

async function doBuyNow() {
	const ok = await ensureCanPurchase(goodsId.value, detail.value?.purchase?.reason)
	if (!ok) return
	const spec = formatSpecDisplayText(detail.value?.specDisplay)
	const parts = [
		`goodsId=${goodsId.value}`,
		`quantity=${quantity.value}`
	]
	if (spec && spec !== '默认') {
		parts.push(`specText=${encodeURIComponent(spec)}`)
	}
	uni.navigateTo({
		url: `${PAGE_CHECKOUT}?${parts.join('&')}`
	})
}

function showBlockReason() {
	const msg =
		statusTip.value ||
		detail.value?.purchase?.reason ||
		'暂不可购买'
	uni.showToast({ title: msg, icon: 'none' })
}

function onEnterShop() {
	const sid = detail.value?.shop?.shopId
	if (sid) {
		goShopHome(sid)
	} else {
		uni.showToast({ title: '店铺信息不可用', icon: 'none' })
	}
}

function goAllReviews() {
	uni.navigateTo({
		url: `${PAGE_GOODS_REVIEWS}?goodsId=${goodsId.value}`
	})
}

onLoad((options) => {
	goodsId.value = options.goodsId || ''
	calcScrollHeight()
	if (!goodsId.value) {
		loadFailed.value = true
		pageLoading.value = false
		return
	}
	loadDetail().then(() => loadReviewPreview())
})
</script>

<style lang="scss" scoped>
.detail-page {
	min-height: 100vh;
	background: #f5f6f8;
}
.detail-loading {
	min-height: 60vh;
	display: flex;
	align-items: center;
	justify-content: center;
}
.pic-swiper {
	height: 750rpx;
	background: #fff;
}
.pic-swiper__img {
	width: 100%;
	height: 750rpx;
}
.status-tip {
	padding: 16rpx 24rpx;
	background: #fff3e0;
	color: #e65100;
	font-size: 26rpx;
}
.card {
	margin: 16rpx 24rpx;
	padding: 24rpx;
	background: #fff;
	border-radius: 16rpx;
}
.price-card .price-row {
	color: #e53935;
	font-weight: 700;
}
.price-symbol {
	font-size: 28rpx;
}
.price-num {
	font-size: 48rpx;
}
.goods-name {
	display: block;
	margin-top: 16rpx;
	font-size: 32rpx;
	font-weight: 600;
	color: #222;
	line-height: 1.4;
}
.goods-brief {
	display: block;
	margin-top: 12rpx;
	font-size: 26rpx;
	color: #888;
}
.meta-row {
	display: flex;
	flex-wrap: wrap;
	margin-top: 16rpx;
	gap: 16rpx;
}
.meta-item {
	font-size: 24rpx;
	color: #999;
}
.cell-row {
	display: flex;
	align-items: center;
}
.cell-label {
	font-size: 28rpx;
	color: #333;
}
.cell-value {
	flex: 1;
	text-align: right;
	margin-right: 8rpx;
	font-size: 28rpx;
	color: #666;
}
.section-title {
	font-size: 30rpx;
	font-weight: 600;
	color: #222;
	margin-bottom: 16rpx;
}
.section-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	margin-bottom: 8rpx;
}
.section-more {
	font-size: 24rpx;
	color: #2e7d32;
}
.attr-row {
	display: flex;
	padding: 12rpx 0;
	font-size: 26rpx;
	border-bottom: 1rpx solid #f5f5f5;
}
.attr-name {
	width: 180rpx;
	color: #999;
	flex-shrink: 0;
}
.attr-val {
	flex: 1;
	color: #333;
}
.info-line {
	display: flex;
	padding: 10rpx 0;
	font-size: 26rpx;
	color: #444;
}
.info-label {
	width: 140rpx;
	color: #999;
	flex-shrink: 0;
}
.service-item {
	display: flex;
	padding: 16rpx 0;
	border-bottom: 1rpx solid #f5f5f5;
}
.service-icon {
	width: 48rpx;
	height: 48rpx;
	margin-right: 16rpx;
}
.service-name {
	font-size: 28rpx;
	color: #333;
}
.service-intro {
	display: block;
	margin-top: 6rpx;
	font-size: 24rpx;
	color: #999;
}
.after-sale-text {
	font-size: 26rpx;
	color: #666;
	line-height: 1.6;
}
.rich-wrap {
	font-size: 28rpx;
	color: #444;
	overflow: hidden;
}
.empty-text {
	font-size: 26rpx;
	color: #999;
}
.shop-card {
	display: flex;
	align-items: center;
}
.shop-avatar {
	width: 88rpx;
	height: 88rpx;
	border-radius: 50%;
	background: #eee;
}
.shop-info {
	margin-left: 20rpx;
}
.shop-name {
	font-size: 30rpx;
	font-weight: 600;
	color: #333;
}
.shop-enter {
	display: block;
	margin-top: 8rpx;
	font-size: 24rpx;
	color: #2e7d32;
}
.review-loading {
	padding: 24rpx 0;
	display: flex;
	justify-content: center;
}
.scroll-bottom-gap {
	height: 140rpx;
}
.qty-popup {
	padding: 32rpx 24rpx 48rpx;
}
.qty-popup__head {
	display: flex;
	align-items: center;
	margin-bottom: 32rpx;
}
.qty-popup__pic {
	width: 160rpx;
	height: 160rpx;
	border-radius: 12rpx;
	margin-right: 20rpx;
	background: #f5f5f5;
}
.qty-popup__price {
	display: block;
	font-size: 36rpx;
	color: #e53935;
	font-weight: 600;
}
.qty-popup__stock {
	display: block;
	margin-top: 8rpx;
	font-size: 24rpx;
	color: #999;
}
.qty-popup__row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	margin-bottom: 32rpx;
	font-size: 28rpx;
}
.qty-popup__btn {
	height: 88rpx;
	line-height: 88rpx;
	background: #2e7d32;
	color: #fff;
	font-size: 30rpx;
	border-radius: 44rpx;
	border: none;
}
</style>
