<template>
	<view class="shop-goods-block">
		<scroll-view
			class="shop-goods-block__scroll"
			scroll-y
			:scroll-top="listScrollTop"
			:style="{ height: scrollHeight }"
			@scrolltolower="onLoadMore"
		>
			<view v-if="loading && !goodsList.length" class="shop-goods-block__loading">
				<u-loading-icon mode="circle" />
			</view>
			<goods-grid v-else-if="goodsList.length" :list="goodsList" @item-click="onGoodsClick" />
			<view v-else class="shop-goods-block__empty">
				<u-empty mode="list" :text="emptyText" icon-size="80" />
				<text v-if="loadFailed" class="shop-goods-block__retry" @click="reloadGoods(true)">点击重试</text>
			</view>
			<view v-if="goodsList.length" class="shop-goods-block__footer">
				<text v-if="loadingMore">加载中...</text>
				<text v-else-if="finished">没有更多了</text>
			</view>
		</scroll-view>
	</view>
</template>

<script setup>
import { ref, watch } from 'vue'
import { getShopGoods } from '@/api/shop'
import { mapGoodsCardList } from '@/utils/goodsDisplay'
import { SHOP_GOODS_PAGE_SIZE } from '@/constants/shop'
import GoodsGrid from '@/components/mall/GoodsGrid.vue'

const props = defineProps({
	shopId: {
		type: [Number, String],
		default: ''
	},
	/** 本店二级分类 ID；空表示全店 */
	shopCategoryId: {
		type: [Number, String],
		default: ''
	},
	/** 店内搜索关键词；有值时忽略 shopCategoryId */
	keyword: {
		type: String,
		default: ''
	},
	scrollHeight: {
		type: String,
		default: '600px'
	},
	scrollTopKey: {
		type: Number,
		default: 0
	},
	pageSize: {
		type: Number,
		default: SHOP_GOODS_PAGE_SIZE
	},
	emptyText: {
		type: String,
		default: '暂无商品'
	},
	/** 为 false 时不拉取（如一级下无二级 Tab） */
	enabled: {
		type: Boolean,
		default: true
	}
})

const emit = defineEmits(['goods-click'])

const goodsList = ref([])
const loading = ref(false)
const loadingMore = ref(false)
const finished = ref(false)
const pageNum = ref(1)
const listScrollTop = ref(0)
const loadFailed = ref(false)

watch(
	() => [props.shopId, props.shopCategoryId, props.keyword, props.scrollTopKey, props.enabled],
	() => {
		if (!props.shopId || !props.enabled) {
			goodsList.value = []
			return
		}
		reloadGoods(true)
	},
	{ immediate: true }
)

function buildParams() {
	const params = {
		pageNum: pageNum.value,
		pageSize: props.pageSize
	}
	const kw = (props.keyword || '').trim()
	if (kw) {
		params.keyword = kw
	} else if (props.shopCategoryId) {
		params.shopCategoryId = props.shopCategoryId
	}
	return params
}

async function fetchPage(isReset) {
	if (!props.shopId || !props.enabled) return
	if (isReset) {
		loading.value = true
		loadFailed.value = false
		pageNum.value = 1
		finished.value = false
	} else {
		if (finished.value || loadingMore.value) return
		loadingMore.value = true
	}
	try {
		const res = await getShopGoods(props.shopId, buildParams())
		const rows = mapGoodsCardList(res.rows || [])
		const total = Number(res.total) || 0
		if (isReset) {
			goodsList.value = rows
		} else {
			goodsList.value = goodsList.value.concat(rows)
		}
		finished.value =
			rows.length < props.pageSize || (total > 0 && goodsList.value.length >= total)
		if (!finished.value) {
			pageNum.value += 1
		}
	} catch (e) {
		loadFailed.value = true
		if (isReset) {
			goodsList.value = []
		}
	} finally {
		loading.value = false
		loadingMore.value = false
	}
}

function reloadGoods(resetScroll) {
	if (resetScroll) {
		listScrollTop.value = listScrollTop.value === 0 ? 0.1 : 0
	}
	pageNum.value = 1
	fetchPage(true)
}

function onLoadMore() {
	if (!loading.value && !loadingMore.value && !finished.value) {
		fetchPage(false)
	}
}

function onGoodsClick(item) {
	emit('goods-click', item)
}

defineExpose({ reloadGoods })
</script>

<style lang="scss" scoped>
.shop-goods-block__scroll {
	width: 100%;
	box-sizing: border-box;
	padding: 10rpx;
}
.shop-goods-block__loading,
.shop-goods-block__empty {
	padding: 80rpx 0;
	display: flex;
	flex-direction: column;
	align-items: center;
}
.shop-goods-block__retry {
	margin-top: 24rpx;
	font-size: 28rpx;
	color: #2e7d32;
}
.shop-goods-block__footer {
	padding: 24rpx;
	text-align: center;
	font-size: 24rpx;
	color: #999;
}
</style>
