<template>
	<view class="page-shop">
		<view v-if="pageError" class="page-shop__error">
			<u-empty mode="page" :text="pageError" icon-size="80" />
			<u-button type="primary" text="重试" size="small" custom-style="margin-top:24rpx" @click="initPage" />
			<u-button plain text="返回" size="small" custom-style="margin-top:16rpx" @click="onBack" />
		</view>

		<template v-else>
			<view v-if="profileLoading" class="page-shop__loading">
				<u-loading-icon mode="circle" />
			</view>

			<template v-else-if="profile">
				<view class="shop-header">
					<image class="shop-header__avatar" :src="profile.shopAvatar" mode="aspectFill" />
					<view class="shop-header__main">
						<view class="shop-header__title-row">
							<text class="shop-header__name">{{ profile.shopName }}</text>
							<text v-if="profile.isClosed" class="shop-header__tag">{{ closedLabel }}</text>
						</view>
						<view v-if="profile.showRating || profile.showFans" class="shop-header__meta">
							<text v-if="profile.showRating" class="shop-header__meta-item">评分 {{ profile.ratingText }}</text>
							<text v-if="profile.showFans" class="shop-header__meta-item">粉丝 {{ profile.fansCount }}</text>
						</view>
						<text v-if="profile.shopDesc" class="shop-header__desc">{{ profile.shopDesc }}</text>
					</view>
					<view
						class="shop-header__follow"
						:class="{ 'shop-header__follow--on': profile.followed }"
						@click="onFollowTap"
					>
						<text>{{ profile.followed ? '已关注' : '+ 关注' }}</text>
					</view>
				</view>

				<view class="shop-search-bar" @click="onGoShopSearch">
					<u-icon name="search" color="#2e7d32" size="18" />
					<text class="shop-search-bar__text">搜索本店商品</text>
				</view>

				<scroll-view class="page-shop__l1" scroll-x show-scrollbar="false">
					<view class="tabs-inner">
						<view
							v-for="(tab, index) in level1Tabs"
							:key="tab.categoryId"
							class="tab-item"
							:class="{ 'tab-item--active': activeLevel1Index === index }"
							@click="onLevel1Change(index)"
						>
							<text>{{ tab.categoryName }}</text>
						</view>
					</view>
				</scroll-view>

				<view v-if="!isAllLevel1 && tabsLoading" class="page-shop__hint">
					<u-loading-icon mode="circle" size="20" />
				</view>
				<scroll-view
					v-else-if="!isAllLevel1 && level2Tabs.length"
					class="page-shop__l2"
					scroll-x
					show-scrollbar="false"
				>
					<view class="tabs-inner">
						<view
							v-for="(tab, index) in level2Tabs"
							:key="tab.categoryId"
							class="tab-item tab-item--sm"
							:class="{ 'tab-item--active': activeLevel2Index === index }"
							@click="onLevel2Change(index)"
						>
							<text>{{ tab.categoryName }}</text>
						</view>
					</view>
				</scroll-view>

				<shop-goods-block
					:shop-id="shopId"
					:shop-category-id="activeShopCategoryId"
					:scroll-top-key="goodsScrollKey"
					:scroll-height="goodsScrollHeight"
					:enabled="goodsBlockEnabled"
					:empty-text="goodsEmptyText"
					@goods-click="onGoodsClick"
				/>
			</template>
		</template>
	</view>
</template>

<script setup>
import { ref, computed } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { getShopProfile, getShopCategories, getShopLevel2Tabs, followShop, unfollowShop } from '@/api/shop'
import {
	mapShopProfile,
	mapShopCategoryTree,
	mapShopLevel2Tabs,
	sortShopTabsWithHot
} from '@/utils/shopDisplay'
import {
	SHOP_ALL_TAB_ID,
	SHOP_ALL_TAB_NAME,
	SHOP_CLOSED_LABEL
} from '@/constants/shop'
import { goShopSearch } from '@/utils/shopNav'
import { goGoodsDetail } from '@/utils/goodsDetail'
import { ensureApiToken } from '@/utils/apiAuth'
import { smartNavigateBack } from '@/utils/navBack'
import ShopGoodsBlock from '@/components/shop/ShopGoodsBlock.vue'

const shopId = ref('')
const profile = ref(null)
const profileLoading = ref(true)
const pageError = ref('')
const followLoading = ref(false)
const closedLabel = SHOP_CLOSED_LABEL

const categoryTree = ref([])
const level2Tabs = ref([])
const activeLevel1Index = ref(0)
const activeLevel2Index = ref(0)
const tabsLoading = ref(false)
const tabsFailed = ref(false)
const goodsScrollKey = ref(0)
const goodsScrollHeight = ref('500px')

const allTab = { categoryId: SHOP_ALL_TAB_ID, categoryName: SHOP_ALL_TAB_NAME }

const level1Tabs = computed(() => [allTab, ...categoryTree.value])

const isAllLevel1 = computed(() => {
	const tab = level1Tabs.value[activeLevel1Index.value]
	return !tab || tab.categoryId === SHOP_ALL_TAB_ID
})

const activeLevel1Id = computed(() => {
	const tab = level1Tabs.value[activeLevel1Index.value]
	return tab && tab.categoryId !== SHOP_ALL_TAB_ID ? tab.categoryId : ''
})

const activeShopCategoryId = computed(() => {
	if (isAllLevel1.value) return ''
	if (!level2Tabs.value.length) return ''
	const tab = level2Tabs.value[activeLevel2Index.value]
	return tab ? tab.categoryId : ''
})

const goodsBlockEnabled = computed(() => {
	if (isAllLevel1.value) return true
	return level2Tabs.value.length > 0
})

const goodsEmptyText = computed(() => {
	if (!isAllLevel1.value && !level2Tabs.value.length && !tabsLoading.value) {
		return '该分类下暂无商品'
	}
	return '暂无商品'
})

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

function onBack() {
	smartNavigateBack()
}

async function loadProfile() {
	profileLoading.value = true
	pageError.value = ''
	try {
		const res = await getShopProfile(shopId.value)
		const mapped = mapShopProfile(res.data)
		if (!mapped) {
			throw new Error('店铺数据异常')
		}
		profile.value = mapped
		const title = mapped.shopName || '店铺'
		uni.setNavigationBarTitle({ title })
	} catch (e) {
		profile.value = null
		const msg = (e && e.msg) || (e && e.message) || '店铺不存在或已关闭'
		pageError.value = msg
	} finally {
		profileLoading.value = false
	}
}

async function loadCategories() {
	try {
		const res = await getShopCategories(shopId.value)
		categoryTree.value = sortShopTabsWithHot(mapShopCategoryTree(res.data || []))
	} catch (e) {
		categoryTree.value = []
	}
}

async function loadLevel2Tabs() {
	if (!activeLevel1Id.value) {
		level2Tabs.value = []
		return
	}
	tabsLoading.value = true
	tabsFailed.value = false
	try {
		const res = await getShopLevel2Tabs(shopId.value, activeLevel1Id.value)
		level2Tabs.value = sortShopTabsWithHot(mapShopLevel2Tabs(res.data || []))
		if (activeLevel2Index.value >= level2Tabs.value.length) {
			activeLevel2Index.value = 0
		}
	} catch (e) {
		tabsFailed.value = true
		level2Tabs.value = []
	} finally {
		tabsLoading.value = false
	}
}

function bumpGoodsList() {
	goodsScrollKey.value += 1
}

async function onLevel1Change(index) {
	if (activeLevel1Index.value === index) return
	activeLevel1Index.value = index
	activeLevel2Index.value = 0
	if (isAllLevel1.value) {
		level2Tabs.value = []
		bumpGoodsList()
		return
	}
	await loadLevel2Tabs()
	bumpGoodsList()
}

function onLevel2Change(index) {
	if (activeLevel2Index.value === index) return
	activeLevel2Index.value = index
	bumpGoodsList()
}

async function onFollowTap() {
	if (!profile.value || followLoading.value) return
	if (!ensureApiToken()) return
	followLoading.value = true
	try {
		if (profile.value.followed) {
			await unfollowShop(shopId.value)
			profile.value.followed = false
			profile.value.fansCount = Math.max(0, profile.value.fansCount - 1)
		} else {
			await followShop(shopId.value)
			profile.value.followed = true
			profile.value.fansCount += 1
		}
	} catch (e) {
		// request 已 Toast
	} finally {
		followLoading.value = false
	}
}

function onGoShopSearch() {
	goShopSearch(shopId.value)
}

function onGoodsClick(item) {
	if (item && item.goodsId) {
		goGoodsDetail(item.goodsId)
	}
}

async function initPage() {
	if (!shopId.value) return
	await loadProfile()
	if (!profile.value) return
	await loadCategories()
	if (!isAllLevel1.value) {
		await loadLevel2Tabs()
	}
}

onLoad((options) => {
	shopId.value = options.shopId || ''
	calcScrollHeight()
	if (!shopId.value) {
		pageError.value = '无法打开店铺'
		profileLoading.value = false
		setTimeout(() => onBack(), 800)
		return
	}
	initPage()
})
</script>

<style lang="scss" scoped>
.page-shop {
	display: flex;
	flex-direction: column;
	height: calc(100vh - 88rpx);
	background: #f5f6f8;
}
.page-shop__error,
.page-shop__loading,
.page-shop__hint {
	padding: 80rpx 24rpx;
	display: flex;
	flex-direction: column;
	align-items: center;
}
.shop-header {
	display: flex;
	align-items: flex-start;
	padding: 24rpx;
	background: #fff;
	margin-bottom: 2rpx;
}
.shop-header__avatar {
	width: 120rpx;
	height: 120rpx;
	border-radius: 12rpx;
	background: #eee;
	flex-shrink: 0;
}
.shop-header__main {
	flex: 1;
	margin: 0 20rpx;
	min-width: 0;
}
.shop-header__title-row {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 12rpx;
}
.shop-header__name {
	font-size: 32rpx;
	font-weight: 600;
	color: #333;
}
.shop-header__tag {
	font-size: 22rpx;
	color: #e65100;
	background: #fff3e0;
	padding: 4rpx 12rpx;
	border-radius: 6rpx;
}
.shop-header__meta {
	margin-top: 12rpx;
	display: flex;
	flex-wrap: wrap;
	gap: 16rpx;
}
.shop-header__meta-item {
	font-size: 24rpx;
	color: #999;
}
.shop-header__desc {
	margin-top: 12rpx;
	font-size: 24rpx;
	color: #666;
	line-height: 1.5;
	overflow: hidden;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
}
.shop-header__follow {
	flex-shrink: 0;
	padding: 12rpx 24rpx;
	border-radius: 32rpx;
	border: 2rpx solid #2e7d32;
	background: #fff;
}
.shop-header__follow text {
	font-size: 26rpx;
	color: #2e7d32;
}
.shop-header__follow--on {
	background: #e8f5e9;
	border-color: #a5d6a7;
}
.shop-header__follow--on text {
	color: #666;
}
.shop-search-bar {
	display: flex;
	align-items: center;
	margin: 16rpx 24rpx;
	padding: 0 24rpx;
	height: 72rpx;
	background: #fff;
	border-radius: 36rpx;
	border: 2rpx solid #c8e6c9;
}
.shop-search-bar__text {
	margin-left: 12rpx;
	font-size: 28rpx;
	color: #999;
}
.page-shop__l1,
.page-shop__l2 {
	background: #fff;
	white-space: nowrap;
}
.page-shop__l2 {
	border-top: 1rpx solid #f0f0f0;
}
.tabs-inner {
	display: inline-flex;
	padding: 16rpx 12rpx;
}
.tab-item {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 12rpx 28rpx;
	margin: 0 8rpx;
	border-radius: 32rpx;
	background: #f5f5f5;
}
.tab-item--sm {
	padding: 8rpx 24rpx;
}
.tab-item text {
	font-size: 26rpx;
	color: #666;
}
.tab-item--active {
	background: #e8f5e9;
}
.tab-item--active text {
	color: #2e7d32;
	font-weight: 500;
}
</style>
