<template>
	<view class="hall-page">
		<view class="hall-hd" :style="{ paddingTop: (statusBar + 12) + 'px' }">
			<view class="hall-hd-row">
				<view class="hall-hd-left">
					<view class="hall-hd-title-row">
						<text class="hall-hd-title">{{ copy.title }}</text>
						<text class="hall-hd-tag">LIVE</text>
					</view>
					<text v-if="!loading && !loadError" class="hall-hd-desc">
						{{ liveCountLabel }} · {{ totalCountLabel }}
					</text>
					<text v-else class="hall-hd-desc hall-hd-desc--placeholder">—</text>
				</view>
				<view class="hall-tool-btn" @tap="openLiveSearch">
					<image
						class="hall-tool-icon"
						src="/static/icon/searchline.png"
						mode="aspectFit"
					/>
				</view>
			</view>
		</view>

		<scroll-view
			scroll-y
			class="hall-scroll"
			:style="{ height: scrollHeight + 'px' }"
			:show-scrollbar="false"
			:refresher-enabled="true"
			:refresher-triggered="refreshing"
			refresher-background="#eef3fb"
			refresher-default-style="black"
			@refresherrefresh="onRefresherRefresh"
			@refresherrestore="onRefresherEnd"
			@refresherabort="onRefresherEnd"
		>
			<view v-if="loading && !rooms.length" class="hall-state">
				<text class="hall-state-txt">{{ copy.loading }}</text>
			</view>

			<view v-else-if="loadError && !rooms.length" class="hall-state">
				<text class="hall-state-txt">{{ loadError }}</text>
				<view class="hall-retry" @tap="loadCatalog">
					<text class="hall-retry-txt">{{ copy.retry }}</text>
				</view>
			</view>

			<view v-else-if="!rooms.length" class="hall-state hall-state--empty">
				<empty src="find_default3x" :text="copy.empty" />
				<text class="hall-state-hint">{{ copy.emptyHint }}</text>
			</view>

			<view v-else class="hall-list-inner">
				<view
					v-for="(item, index) in rooms"
					:key="item.id + '_' + index"
					class="hall-card"
					@tap="enterRoom(item, index)"
				>
					<view class="hall-cover-wrap">
						<image class="hall-cover" :src="item.cover" mode="aspectFill" />
						<view v-if="item.live" class="hall-live-badge">
							<view class="hall-live-dot" />
							<text class="hall-live-txt">{{ copy.liveOn }}</text>
						</view>
					</view>
					<view class="hall-card-body">
						<text class="hall-card-title">{{ item.title }}</text>
						<text class="hall-card-status" :class="{ 'hall-card-status--on': item.live }">
							{{ item.live ? copy.statusOn : copy.statusOff }}
						</text>
					</view>
				</view>
			</view>
			<view class="hall-bottom-safe" :style="{ height: listBottomPad + 'px' }" />
		</scroll-view>

		<app-tabbar active="live" />
	</view>
</template>

<script>
import appSettings from '@/core/config/app-settings'
import { pullBroadcastCatalog, fetchBroadcastStatus } from '@/features/live/gateway'
import { mapRowToHallCard } from '@/features/live/list-normalize'
import { saveRoomQueue } from '@/features/live/room-queue'
import AppTabbar from '@/components/app-tabbar/app-tabbar.vue'

/** 与 app-tabbar-inner height: 100rpx 一致 */
const TABBAR_INNER_RPX = 100
/** 列表底部额外留白，避免最后一张卡片贴边或被遮挡 */
const LIST_BOTTOM_GAP_RPX = 32

export default {
	components: { AppTabbar },
	data() {
		return {
			statusBar: 0,
			safeBottom: 0,
			windowHeight: 667,
			refreshing: false,
			loading: true,
			loadError: '',
			rooms: [],
			_loadRunning: false,
			_hallReady: false,
			_enteringRoom: false
		}
	},
	computed: {
		copy() {
			const t = this.$t.bind(this)
			return {
				title: t('tabbar.live'),
				loading: t('home.loading'),
				empty: t('live.hallEmpty'),
				emptyHint: t('live.hallEmptyHint'),
				liveOn: t('live.statusOn'),
				statusOn: t('live.statusOnLong'),
				statusOff: t('live.statusOff'),
				roomEnded: t('live.broadcastEndTitle'),
				loadFailed: t('home.loadFailed'),
				retry: t('live.retry')
			}
		},
		liveCount() {
			return this.rooms.filter((r) => r.live).length
		},
		liveCountLabel() {
			return this.$t('live.hallLiveCount', { n: this.liveCount })
		},
		totalCountLabel() {
			return this.$t('live.hallTotalCount', { n: this.rooms.length })
		},
		/** 自定义 tabbar 总高度 = 内容区 100rpx + 底部安全区 */
		tabbarTotal() {
			return uni.upx2px(TABBAR_INNER_RPX) + (this.safeBottom || 0)
		},
		/** scroll-view 内底部垫高，保证最后一项可滚出 tabbar */
		listBottomPad() {
			return this.tabbarTotal + uni.upx2px(LIST_BOTTOM_GAP_RPX)
		},
		headerHeight() {
			// 顶内边距 + 标题行 + 副标题 + 底内边距，与 .hall-hd 占位一致
			return this.statusBar + 12 + uni.upx2px(140)
		},
		scrollHeight() {
			return Math.max(200, this.windowHeight - this.headerHeight - this.tabbarTotal)
		}
	},
	onLoad() {
		try {
			const info = uni.getSystemInfoSync()
			this.statusBar = info.statusBarHeight || 0
			this.safeBottom = (info.safeAreaInsets && info.safeAreaInsets.bottom) || 0
			this.windowHeight = info.windowHeight || 667
		} catch (_) {}
		this.loadCatalog()
	},
	onShow() {
		setTimeout(() => {
			try { uni.hideTabBar({ animation: false }) } catch (_) {}
		}, 0)
		// 参考 hklivelist.vue onShow → getLiveList：从观看页/结束页返回时刷新列表
		if (this._hallReady) {
			this.loadCatalog({ keepContent: true }).catch(() => {})
		}
	},
	methods: {
		onRefresherRefresh() {
			this.pullRefresh()
		},
		onRefresherEnd() {
			this.refreshing = false
		},
		async pullRefresh() {
			if (this.refreshing || this._loadRunning) return
			this.refreshing = true
			try {
				await this.loadCatalog({ keepContent: true })
			} finally {
				this.refreshing = false
			}
		},
		resolveCover(path) {
			if (!path) return ''
			if (/^https?:\/\//.test(path)) return path
			if (path.startsWith('//')) return `https:${path}`
			return `${appSettings.cdnurl}${path.startsWith('/') ? path : `/${path}`}`
		},
		async loadCatalog(options = {}) {
			const keepContent = options.keepContent === true
			if (this._loadRunning) return
			this._loadRunning = true
			if (!keepContent) {
				this.loading = true
				this.loadError = ''
			}
			try {
				const list = await pullBroadcastCatalog()
				this.rooms = (list || [])
					.map((row) => {
						const card = mapRowToHallCard(row)
						card.cover = this.resolveCover(card.cover)
						return card
					})
					.filter((r) => r.id)
				this.loadError = ''
			} catch (err) {
				if (!keepContent) {
					this.rooms = []
					this.loadError = err?.message || this.copy.loadFailed
				} else {
					uni.showToast({
						title: err?.message || this.copy.loadFailed,
						icon: 'none'
					})
				}
			} finally {
				if (!keepContent) this.loading = false
				this._loadRunning = false
				this._hallReady = true
			}
		},
		async enterRoom(item, index) {
			if (this._enteringRoom || !item?.id) return
			this._enteringRoom = true
			try {
				// 参考 live-lists.vue golive：进房前 getLiveStatus
				const status = await fetchBroadcastStatus(item.id)
				if (status === '0' || status === '2' || status === '3') {
					this.loadCatalog({ keepContent: true }).catch(() => {})
					uni.redirectTo({
						url: `/pages/live/end?id=${item.id}`,
						fail: () => {
							uni.showToast({ title: this.copy.roomEnded, icon: 'none' })
						}
					})
					return
				}
				if (status !== '1' && !item.live) {
					uni.showToast({ title: this.copy.statusOff, icon: 'none' })
					this.loadCatalog({ keepContent: true }).catch(() => {})
					return
				}
				const ids = this.rooms.map((r) => r.id)
				const thumbs = this.rooms.map((r) => r.raw.image || r.raw.thumb || '')
				const metas = this.rooms.map((r) => ({
					isFollow: r.isFollow,
					userNo: r.anchorUserNo || (r.raw && (r.raw.user_no || r.raw.userNo)) || ''
				}))
				saveRoomQueue(ids, thumbs, index, metas)
				const anchorNo =
					item.anchorUserNo ||
					(item.raw && (item.raw.user_no || item.raw.userNo)) ||
					''
				let url = `/pages/live/watch?id=${item.id}`
				if (anchorNo) {
					// 关注接口字段为 user_no；同时带 userNo 兼容旧读取
					url += `&user_no=${encodeURIComponent(anchorNo)}`
					url += `&userNo=${encodeURIComponent(anchorNo)}`
				}
				if (item.isFollow) {
					url += '&isFollow=1'
				}
				uni.navigateTo({ url })
			} finally {
				this._enteringRoom = false
			}
		},
		openLiveSearch() {
			uni.navigateTo({ url: '/pages/live/search' })
		}
	}
}
</script>

<style scoped>
.hall-page {
	display: flex;
	flex-direction: column;
	min-height: 100vh;
	height: 100vh;
	background-color: #eef3fb;
	box-sizing: border-box;
	overflow: hidden;
}

/* 顶栏：沿用首页 section 标题体系 */
.hall-hd {
	flex-shrink: 0;
	padding-left: 32rpx;
	padding-right: 32rpx;
	padding-bottom: 8rpx;
}

.hall-hd-row {
	display: flex;
	flex-direction: row;
	align-items: flex-start;
	justify-content: space-between;
}

.hall-hd-left {
	flex: 1;
	min-width: 0;
}

.hall-hd-title-row {
	display: flex;
	flex-direction: row;
	align-items: baseline;
}

.hall-hd-title {
	font-size: 36rpx;
	font-weight: 700;
	color: #1a1d26;
	line-height: 1.2;
}

.hall-hd-tag {
	margin-left: 12rpx;
	font-size: 20rpx;
	font-weight: 600;
	letter-spacing: 2rpx;
	color: #8a8d9e;
}

.hall-hd-desc {
	display: block;
	margin-top: 8rpx;
	font-size: 24rpx;
	color: #8a8d9e;
	line-height: 1.4;
}

.hall-hd-desc--placeholder {
	opacity: 0;
}

/* 右上角：与 feed 页一致的半透明黑圆 + 搜索图标（纯展示） */
.hall-tool-btn {
	flex-shrink: 0;
	margin-left: 16rpx;
	margin-top: 4rpx;
	width: 64rpx;
	height: 64rpx;
	border-radius: 32rpx;
	background-color: rgba(0, 0, 0, 0.32);
	display: flex;
	align-items: center;
	justify-content: center;
}

.hall-tool-icon {
	width: 40rpx;
	height: 40rpx;
}

.hall-scroll {
	width: 100%;
	flex: 1;
	min-height: 0;
}

/* 状态 */
.hall-state {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	min-height: 480rpx;
	padding: 0 48rpx;
	box-sizing: border-box;
}

.hall-state-txt {
	font-size: 28rpx;
	color: #8a8d9e;
	text-align: center;
}

.hall-state--empty {
	padding-top: 40rpx;
}

.hall-state-hint {
	margin-top: 8rpx;
	padding: 0 48rpx;
	font-size: 24rpx;
	color: #b0b3c0;
	text-align: center;
	line-height: 1.5;
}

.hall-retry {
	margin-top: 28rpx;
	padding: 14rpx 36rpx;
	border-radius: 999rpx;
	background-color: #4a8cff;
}

.hall-retry-txt {
	font-size: 26rpx;
	color: #ffffff;
}

.hall-list-inner {
	padding: 16rpx 28rpx 0;
	box-sizing: border-box;
}

.hall-bottom-safe {
	width: 100%;
}

/* 卡片：白底 + 轻阴影，与动态/首页卡片一致 */
.hall-card {
	overflow: hidden;
	margin-bottom: 24rpx;
	background-color: #ffffff;
	border-radius: 24rpx;
	box-shadow: 0 8rpx 28rpx rgba(74, 140, 255, 0.08);
}

.hall-cover-wrap {
	position: relative;
	width: 100%;
	height: 360rpx;
	background-color: #e8edf5;
}

.hall-cover {
	width: 100%;
	height: 100%;
	display: block;
}

.hall-live-badge {
	position: absolute;
	top: 20rpx;
	left: 20rpx;
	display: flex;
	flex-direction: row;
	align-items: center;
	padding: 8rpx 16rpx;
	border-radius: 999rpx;
	background-color: rgba(255, 77, 109, 0.92);
}

.hall-live-dot {
	width: 10rpx;
	height: 10rpx;
	margin-right: 8rpx;
	border-radius: 50%;
	background-color: #ffffff;
}

.hall-live-txt {
	font-size: 20rpx;
	font-weight: 600;
	color: #ffffff;
	letter-spacing: 1rpx;
}

.hall-card-body {
	display: flex;
	flex-direction: row;
	align-items: center;
	justify-content: space-between;
	padding: 24rpx 28rpx;
	box-sizing: border-box;
}

.hall-card-title {
	flex: 1;
	min-width: 0;
	font-size: 30rpx;
	font-weight: 600;
	color: #1a1d26;
	line-height: 1.45;
	overflow: hidden;
	text-overflow: ellipsis;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	display: -webkit-box;
}

.hall-card-status {
	flex-shrink: 0;
	margin-left: 20rpx;
	font-size: 24rpx;
	color: #8a8d9e;
}

.hall-card-status--on {
	color: #ff4d6d;
	font-weight: 500;
}
</style>
