<template>
	<view class="ls-page">
		<view class="ls-hd" :style="{ paddingTop: (statusBar + 12) + 'px' }">
			<view class="ls-hd-row">
				<view class="ls-back" @tap="goBack">
					<text class="ls-back-icon">←</text>
				</view>
				<view class="ls-input-wrap">
					<image
						class="ls-input-icon"
						src="/static/icon/searchline.png"
						mode="aspectFit"
					/>
					<input
						class="ls-input"
						type="text"
						maxlength="32"
						confirm-type="search"
						:focus="inputFocus"
						:value="keyword"
						:placeholder="copy.placeholder"
						placeholder-class="ls-input-ph"
						@input="onInput"
						@confirm="onSearch"
					/>
					<view v-if="keyword" class="ls-clear" @tap="clearKeyword">
						<text class="ls-clear-icon">×</text>
					</view>
				</view>
			</view>
		</view>

		<scroll-view
			scroll-y
			class="ls-scroll"
			:style="{ height: scrollHeight + 'px' }"
			:lower-threshold="120"
			:refresher-enabled="searched"
			:refresher-triggered="refreshing"
			@refresherrefresh="onPullRefresh"
			@scrolltolower="loadMore"
		>
			<view class="ls-body" :style="{ paddingBottom: safeBottom + 'px' }">
				<view v-if="!searched" class="ls-hint">
					<text class="ls-hint-txt">{{ copy.hint }}</text>
				</view>

				<view v-else-if="loading && !rooms.length" class="ls-state">
					<text class="ls-state-txt">{{ copy.loading }}</text>
				</view>

				<view v-else-if="loadError" class="ls-state">
					<text class="ls-state-txt">{{ loadError }}</text>
					<view class="ls-retry" @tap="reload">
						<text class="ls-retry-txt">{{ copy.retry }}</text>
					</view>
				</view>

				<view v-else-if="loaded && !rooms.length" class="ls-state ls-state--empty">
					<empty src="find_default3x" :text="copy.empty" />
				</view>

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

				<uni-load-more
					v-if="searched && rooms.length"
					:status="loadStatus"
					:content-text="loadMoreText"
				/>
			</view>
		</scroll-view>
	</view>
</template>

<script>
import appSettings from '@/core/config/app-settings'
import { searchBroadcastCatalog } from '@/features/live/gateway'
import { mapRowToHallCard } from '@/features/live/list-normalize'
import { saveRoomQueue } from '@/features/live/room-queue'

export default {
	data() {
		return {
			statusBar: 0,
			safeBottom: 0,
			scrollHeight: 600,
			inputFocus: true,
			keyword: '',
			searched: false,
			loading: false,
			loaded: false,
			refreshing: false,
			loadError: '',
			loadStatus: 'more',
			page: 1,
			lastPage: 1,
			rooms: []
		}
	},
	computed: {
		copy() {
			const t = this.$t.bind(this)
			return {
				placeholder: t('live.searchPlaceholder'),
				hint: t('live.searchHint'),
				empty: t('live.searchEmpty'),
				enterKeyword: t('live.searchEnterKeyword'),
				loading: t('home.loading'),
				loadFailed: t('home.loadFailed'),
				retry: t('live.retry'),
				liveOn: t('live.statusOn'),
				statusOn: t('live.statusOnLong'),
				statusOff: t('live.statusOff'),
				loadMore: t('home.loadMore'),
				noMore: t('home.noMore')
			}
		},
		loadMoreText() {
			return {
				contentdown: this.copy.loadMore,
				contentrefresh: this.copy.loading,
				contentnomore: this.copy.noMore
			}
		}
	},
	onLoad(query) {
		this.initLayout()
		if (query && query.keyword) {
			this.keyword = decodeURIComponent(query.keyword)
			this.$nextTick(() => this.onSearch())
		}
	},
	methods: {
		initLayout() {
			try {
				const info = uni.getSystemInfoSync()
				this.statusBar = info.statusBarHeight || 0
				this.safeBottom = (info.safeAreaInsets && info.safeAreaInsets.bottom) || 0
				const navH = this.statusBar + uni.upx2px(100)
				this.scrollHeight = (info.windowHeight || 667) - navH
			} catch (_) {}
		},
		goBack() {
			uni.navigateBack({
				fail: () => uni.switchTab({ url: '/pages/live/hall' })
			})
		},
		onInput(e) {
			this.keyword = (e.detail && e.detail.value) || ''
		},
		clearKeyword() {
			this.keyword = ''
			this.searched = false
			this.rooms = []
			this.loaded = false
			this.loadError = ''
		},
		onSearch() {
			const kw = (this.keyword || '').trim()
			if (!kw) {
				this.$appKit && this.$appKit.msg(this.copy.enterKeyword)
				return
			}
			this.keyword = kw
			this.reload()
		},
		onPullRefresh() {
			if (!this.searched) {
				this.refreshing = false
				return
			}
			this.refreshing = true
			this.reload().finally(() => {
				this.refreshing = false
			})
		},
		loadMore() {
			if (!this.searched || this.loading || this.loadStatus !== 'more') return
			if (this.page >= this.lastPage) {
				this.loadStatus = 'noMore'
				return
			}
			this.fetchPage(this.page + 1, 'append')
		},
		reload() {
			this.searched = true
			this.page = 1
			this.lastPage = 1
			this.loadStatus = 'more'
			this.rooms = []
			this.loaded = false
			return this.fetchPage(1, 'refresh')
		},
		async fetchPage(page, mode) {
			if (this.loading) return
			this.loading = true
			this.loadError = ''
			if (mode === 'refresh') this.loadStatus = 'loading'
			try {
				const pack = await searchBroadcastCatalog({
					page,
					search: this.keyword
				})
				const list = (pack.rows || [])
					.map((row) => {
						const card = mapRowToHallCard(row)
						card.cover = this.resolveCover(card.cover)
						return card
					})
					.filter((r) => r.id)
				this.page = pack.currentPage || page
				this.lastPage = pack.lastPage || this.page
				if (mode === 'append') {
					this.rooms = this.rooms.concat(list)
				} else {
					this.rooms = list
				}
				this.loadStatus =
					this.page >= this.lastPage || !list.length ? 'noMore' : 'more'
				this.loaded = true
			} catch (err) {
				if (mode !== 'append') {
					this.rooms = []
					this.loadError = err?.message || this.copy.loadFailed
				}
				this.loadStatus = 'more'
				this.loaded = true
			} finally {
				this.loading = 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}`}`
		},
		enterRoom(item, index) {
			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) {
				url += `&user_no=${encodeURIComponent(anchorNo)}`
				url += `&userNo=${encodeURIComponent(anchorNo)}`
			}
			if (item.isFollow) {
				url += '&isFollow=1'
			}
			uni.navigateTo({ url })
		}
	}
}
</script>

<style scoped>
.ls-page {
	min-height: 100vh;
	background-color: #eef3fb;
}

.ls-hd {
	flex-shrink: 0;
	padding-left: 28rpx;
	padding-right: 28rpx;
	padding-bottom: 16rpx;
}

.ls-hd-row {
	display: flex;
	flex-direction: row;
	align-items: center;
}

.ls-back {
	width: 72rpx;
	height: 72rpx;
	border-radius: 20rpx;
	background-color: #ffffff;
	box-shadow: 0 6rpx 20rpx rgba(74, 140, 255, 0.12);
	display: flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	margin-right: 20rpx;
}

.ls-back-icon {
	font-size: 36rpx;
	color: #4a8cff;
	line-height: 1;
}

.ls-input-wrap {
	flex: 1;
	min-width: 0;
	height: 72rpx;
	border-radius: 20rpx;
	background-color: #ffffff;
	box-shadow: 0 6rpx 20rpx rgba(74, 140, 255, 0.1);
	display: flex;
	flex-direction: row;
	align-items: center;
	padding: 0 20rpx;
	box-sizing: border-box;
}

.ls-input-icon {
	width: 36rpx;
	height: 36rpx;
	margin-right: 12rpx;
	flex-shrink: 0;
	opacity: 0.85;
}

.ls-input {
	flex: 1;
	min-width: 0;
	font-size: 28rpx;
	color: #1a1d29;
	height: 72rpx;
	line-height: 72rpx;
}

.ls-input-ph {
	color: #8a8d9e;
	font-size: 26rpx;
}

.ls-clear {
	width: 44rpx;
	height: 44rpx;
	border-radius: 22rpx;
	background-color: #eef3fb;
	display: flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
}

.ls-clear-icon {
	font-size: 32rpx;
	color: #8a8d9e;
	line-height: 1;
}

.ls-scroll {
	width: 100%;
}

.ls-body {
	padding: 8rpx 28rpx 32rpx;
	box-sizing: border-box;
}

.ls-hint {
	padding: 80rpx 24rpx;
	text-align: center;
}

.ls-hint-txt {
	font-size: 26rpx;
	color: #8a8d9e;
	line-height: 1.5;
}

.ls-state {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	padding: 80rpx 48rpx;
}

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

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

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

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

.ls-list {
	width: 100%;
}

.ls-card {
	overflow: hidden;
	margin-bottom: 24rpx;
	background-color: #ffffff;
	border-radius: 24rpx;
	box-shadow: 0 8rpx 28rpx rgba(74, 140, 255, 0.08);
}

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

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

.ls-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);
}

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

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

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

.ls-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;
}

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

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