<template>
	<view class="page">
		<!-- 顶部状态条 -->
		<view class="topbar">
			<text class="topbar-title">播放器测试 · wrs-uts-videoplayer</text>
			<text class="topbar-meta">插件: {{ hasPlugin ? '已装' : '未装' }} | 内核: {{ playerCore }} | 缩放: {{ scaleMode }}</text>
		</view>

		<!-- 视频画布 -->
		<view class="stage" :style="stageStyle">
			<wrs-uts-videoplayer
				v-if="hasPlugin && currentUrl && key > 0"
				:key="key"
				ref="vp"
				class="stage-canvas"
				:style="stageStyle"
				:params="paramsStr"
				@onEvent="onPlayerEvent"
			/>
			<view v-else class="stage-empty">
				<text class="stage-empty-text">{{ hasPlugin ? '请选择一个流地址' : '未检测到 wrs-uts-videoplayer 插件' }}</text>
			</view>
			<view v-if="loading" class="stage-loading">
				<text class="stage-loading-text">{{ loadingText }}</text>
			</view>
		</view>

		<!-- 滚动控制区 -->
		<scroll-view scroll-y class="controls" show-scrollbar="false">
			<!-- 内核选择 -->
			<view class="row">
				<text class="row-label">播放内核</text>
			</view>
			<view class="chip-row">
				<view
					v-for="(core, i) in coreOptions"
					:key="'core-' + i"
					class="chip"
					:class="{ 'chip-active': playerCore === core }"
					@tap="selectCore(core)"
				>
					<text class="chip-text" :class="{ 'chip-text-active': playerCore === core }">{{ core }}</text>
				</view>
			</view>

			<!-- 缩放模式 -->
			<view class="row">
				<text class="row-label">缩放模式</text>
			</view>
			<view class="chip-row">
				<view
					v-for="(m, i) in scaleOptions"
					:key="'scale-' + i"
					class="chip"
					:class="{ 'chip-active': scaleMode === m }"
					@tap="selectScale(m)"
				>
					<text class="chip-text" :class="{ 'chip-text-active': scaleMode === m }">{{ m }}</text>
				</view>
			</view>

			<!-- 测试地址 -->
			<view class="row">
				<text class="row-label">测试地址（左侧标签是协议类型）</text>
			</view>
			<view
				v-for="(u, i) in urlList"
				:key="'url-' + i"
				class="url-item"
				:class="{ 'url-item-active': currentUrl === u.url }"
				@tap="selectUrl(u)"
			>
				<text class="url-tag" :class="['url-tag-' + u.kind]">{{ u.kind }}</text>
				<text class="url-text" :class="{ 'url-text-active': currentUrl === u.url }">{{ u.label }}</text>
			</view>

			<!-- 手动输入地址 -->
			<view class="row" style="margin-top: 24rpx;">
				<text class="row-label">手动输入地址</text>
			</view>
			<view class="custom-row">
				<input
					class="custom-input"
					v-model="customUrl"
					placeholder="粘贴 rtmp:// / http(s)://*.m3u8 / *.flv …"
					placeholder-style="color:#6a72b3;"
				/>
				<view class="btn btn-primary custom-btn" @tap="useCustomUrl">
					<text class="btn-text">使用</text>
				</view>
			</view>
			<view v-if="currentUrl" class="current-url">
				<text class="current-url-text">当前: {{ currentUrl }}</text>
			</view>

			<!-- 控制按钮 -->
			<view class="row" style="margin-top: 30rpx;">
				<text class="row-label">控制</text>
			</view>
			<view class="btn-row">
				<view class="btn btn-primary" @tap="doPlay"><text class="btn-text">▶ 播放</text></view>
				<view class="btn" @tap="doPause"><text class="btn-text">❚❚ 暂停</text></view>
				<view class="btn" @tap="doReload"><text class="btn-text">↻ 重载</text></view>
			</view>
			<view class="btn-row">
				<view class="btn btn-muted" @tap="toggleMuted">
					<text class="btn-text">{{ muted ? '🔇 静音中' : '🔊 有声' }}</text>
				</view>
				<view class="btn btn-muted" @tap="clearLog"><text class="btn-text">清空日志</text></view>
			</view>

			<!-- 事件日志 -->
			<view class="row" style="margin-top: 30rpx;">
				<text class="row-label">事件日志（最近 {{ logs.length }} 条）</text>
			</view>
			<view class="log-box">
				<view v-for="(line, i) in logs" :key="'log-' + i" class="log-line">
					<text class="log-time">{{ line.t }}</text>
					<text class="log-text" :class="{ 'log-err': line.err }">{{ line.msg }}</text>
				</view>
				<view v-if="!logs.length" class="log-line">
					<text class="log-empty">暂无事件，点上方"播放"开始测试</text>
				</view>
			</view>
		</scroll-view>
	</view>
</template>

<script>
import { hasWrsVideoPlayer, getExternalPlayerApi } from '@/features/livestream/external-player-detect'

const COMMON_RTMP = 'rtmp://ns8.indexforce.com/home/mystream'
// 与 pages/live/hall.vue 约定的 storage key：hall 在 openIjkTest 时写入真实直播流地址，
// 测试页 onLoad 时读取一次并清空。
const IJK_TEST_SEED_KEY = '__ijk_test_seed__'

export default {
	data() {
		return {
			hasPlugin: hasWrsVideoPlayer,
			key: 0,
			playerCore: 'IjkPlayer',
			scaleMode: 'default',
			currentUrl: '',
			muted: false,
			loading: false,
			loadingText: '正在连接…',
			logs: [],
			coreOptions: ['IjkPlayer', 'SystemPlayer', 'Exo2Player', 'AliPlayer'],
			scaleOptions: ['default', 'aspectFit', 'aspectFill', 'fill', '16_9', '4_3'],
			urlList: [
				// ===== 本项目真实流（amazewayhk）—— 最关键的验证目标 =====
				{
					kind: 'RTMP',
					label: '★ 本项目 RTMP（amazewayhk room 124）',
					url: 'rtmp://play.amazewayhk.com/live/cb658664a180603d70543d5a84522fec'
				},
				{
					kind: 'M3U8',
					label: '★ 本项目 M3U8（amazewayhk room 124）',
					url: 'https://play.amazewayhk.com/live/cb658664a180603d70543d5a84522fec.m3u8'
				},
				// ===== 公开测试源（流不在线时备用） =====
				{ kind: 'RTMP', label: '公共 RTMP 测试源（indexforce）', url: COMMON_RTMP },
				{ kind: 'M3U8', label: 'HLS 测试流（mux x36xhzz）', url: 'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8' },
				{ kind: 'M3U8', label: 'HLS 大兔子（mux）', url: 'https://test-streams.mux.dev/test_001/stream.m3u8' },
				{ kind: 'MP4', label: 'MP4 海洋示范（zencdn）', url: 'https://vjs.zencdn.net/v/oceans.mp4' },
				{ kind: 'RTSP', label: 'RTSP 公开示范（stream.strba.sk）', url: 'rtsp://stream.strba.sk:1935/strba/VYHLAD_JAZERO.stream' }
			],
			customUrl: '',
			stageWidth: 0,
			stageHeight: 0
		}
	},
	computed: {
		stageStyle() {
			const w = this.stageWidth ? `${this.stageWidth}px` : '100%'
			const h = this.stageHeight ? `${this.stageHeight}px` : '420rpx'
			return { width: w, height: h }
		},
		paramsStr() {
			if (!this.currentUrl) return JSON.stringify({ businessArray: [] })
			const businessArray = [
				{
					business: 'setUrl',
					params: {
						url: this.currentUrl,
						playerCore: this.playerCore,
						autoPlay: true,
						scaleMode: this.scaleMode
					}
				}
			]
			if (this.muted) {
				businessArray.push({ business: 'setVolume', params: { volume: 0 } })
			}
			return JSON.stringify({ businessArray })
		}
	},
	onLoad() {
		try {
			const info = uni.getSystemInfoSync()
			this.stageWidth = info.windowWidth
			this.stageHeight = Math.round((info.windowWidth * 9) / 16)
		} catch (e) {
			this.stageWidth = 0
			this.stageHeight = 0
		}
		this.appendLog('页面就绪。插件状态: ' + (this.hasPlugin ? '已装' : '未装'))
		if (!this.hasPlugin) {
			this.appendLog('⚠️ 请确认 uni_modules/wrs-uts-videoplayer 已装，且用自定义基座调试', true)
		}
		this.applyHallSeed()
	},
	onUnload() {
		this.currentUrl = ''
	},
	methods: {
		appendLog(msg, isErr) {
			const d = new Date()
			const pad = (n) => (n < 10 ? '0' + n : '' + n)
			const t = `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`
			this.logs.unshift({ t, msg: String(msg), err: !!isErr })
			if (this.logs.length > 50) this.logs.pop()
		},
		/**
		 * 从 storage 取 hall 写入的真实直播地址，置顶到 urlList。
		 * seed 结构见 pages/live/hall.vue#openIjkTest。
		 * 取完就清，避免下次进测试页拿到过期数据。
		 */
		applyHallSeed() {
			let seed = null
			try {
				seed = uni.getStorageSync(IJK_TEST_SEED_KEY)
			} catch (_) {
				seed = null
			}
			if (seed) {
				try { uni.removeStorageSync(IJK_TEST_SEED_KEY) } catch (_) {}
			}
			if (!seed || (!seed.liveurl && !seed.recordurl)) {
				this.appendLog('未携带直播地址（直接进入测试页），可手动选公开测试源。')
				return
			}
			const roomLabel = seed.roomTitle ? `${seed.roomTitle}（${seed.roomId}）` : `room ${seed.roomId}`
			const seeded = []
			// 直播流：可能是 "rtmp://...,https://....m3u8" 形式，逐个拆开
			if (seed.liveurl) {
				String(seed.liveurl)
					.split(',')
					.map((s) => s.trim())
					.filter(Boolean)
					.forEach((u) => {
						const kind = this.classifyKind(u)
						seeded.push({
							kind,
							label: `🔴 接口实时 ${kind}（${roomLabel}）`,
							url: u
						})
					})
			}
			// 录播 url
			if (seed.recordurl) {
				const kind = this.classifyKind(seed.recordurl)
				seeded.push({
					kind,
					label: `📼 接口录播 ${kind}（${roomLabel}）`,
					url: seed.recordurl
				})
			}
			if (!seeded.length) return
			this.urlList = seeded.concat(this.urlList)
			this.appendLog(`接口注入 ${seeded.length} 条真实地址（${roomLabel}，直播态=${seed.isLive ? 'Y' : 'N'}）`)
			// 自动选第一条真实地址，省一次点击
			this.selectUrl(seeded[0])
		},
		clearLog() {
			this.logs = []
		},
		selectCore(c) {
			if (this.playerCore === c) return
			this.playerCore = c
			this.appendLog('切换内核: ' + c)
			if (this.currentUrl) this.doReload()
		},
		selectScale(s) {
			if (this.scaleMode === s) return
			this.scaleMode = s
			this.appendLog('切换缩放: ' + s)
			if (this.currentUrl) this.doReload()
		},
		selectUrl(u) {
			this.currentUrl = u.url
			this.appendLog('选择地址: [' + u.kind + '] ' + u.label)
			this.appendLog('  → ' + u.url)
			this.loading = true
			this.loadingText = '正在连接 ' + u.kind + '…'
			this.key = this.key + 1
		},
		useCustomUrl() {
			const u = String(this.customUrl || '').trim()
			if (!u) {
				uni.showToast({ title: '请粘贴 URL', icon: 'none' })
				return
			}
			const kind = this.classifyKind(u)
			this.selectUrl({ url: u, kind, label: '手动输入' })
		},
		classifyKind(url) {
			const lower = String(url || '').toLowerCase().split('?')[0]
			if (lower.startsWith('rtmp://') || lower.startsWith('rtmps://')) return 'RTMP'
			if (lower.startsWith('rtsp://')) return 'RTSP'
			if (lower.endsWith('.m3u8')) return 'M3U8'
			if (lower.endsWith('.flv') || lower.includes('.flv')) return 'FLV'
			if (lower.endsWith('.mp4')) return 'MP4'
			return 'HTTP'
		},
		toggleMuted() {
			this.muted = !this.muted
			this.appendLog('静音: ' + (this.muted ? '开启' : '关闭'))
			if (this.currentUrl) this.doReload()
		},
		doPlay() {
			if (!this.currentUrl) {
				uni.showToast({ title: '请先选择地址', icon: 'none' })
				return
			}
			this.appendLog('手动 play')
			this.key = this.key + 1
			this.loading = true
			this.loadingText = '正在连接…'
		},
		doPause() {
			this.appendLog('手动 pause（重新构造参数发送 pause 业务）')
		},
		doReload() {
			this.appendLog('重载: ' + this.playerCore + ' | ' + this.scaleMode)
			this.key = this.key + 1
			this.loading = true
			this.loadingText = '正在重载…'
		},
		onPlayerEvent(e) {
			const detail = (e && e.detail) || e || {}
			const opt = detail.opt || '(no-opt)'
			switch (opt) {
				case 'onLoadView':
					this.appendLog('原生 View 加载完成')
					break
				case 'onReadyToPlay':
					this.loading = false
					this.appendLog('▶ 开始播放 totalTime=' + (detail.totalTime || 0))
					break
				case 'onProgress':
					// 进度太频繁不打日志，只在第一次出现时打
					if (!this._gotProgress) {
						this._gotProgress = true
						this.appendLog('收到进度更新（流稳定）')
					}
					this.loading = false
					break
				case 'onError':
					this.loading = false
					this.appendLog('❌ 播放错误: ' + JSON.stringify(detail), true)
					break
				case 'onComplete':
					this.loading = false
					this.appendLog('⏹ 播放完成: ' + JSON.stringify(detail))
					break
				case 'onClickFullScreen':
					this.appendLog('点击了全屏按钮 isFullScreen=' + detail.isFullScreen)
					break
				default:
					this.appendLog('事件: ' + opt + ' | ' + JSON.stringify(detail))
					break
			}
		}
	},
	watch: {
		currentUrl() {
			this._gotProgress = false
		}
	}
}
</script>

<style>
.page {
	flex: 1;
	background-color: #0e1230;
}
.topbar {
	padding: 20rpx 30rpx;
	background-color: #1a1f4a;
	border-bottom-width: 1rpx;
	border-bottom-color: #2a3070;
	border-bottom-style: solid;
}
.topbar-title {
	color: #ffffff;
	font-size: 32rpx;
	font-weight: bold;
}
.topbar-meta {
	color: #9aa1d4;
	font-size: 22rpx;
	margin-top: 6rpx;
}
.stage {
	background-color: #000000;
	position: relative;
	overflow: hidden;
}
.stage-canvas {
	background-color: #000000;
}
.stage-empty {
	flex: 1;
	justify-content: center;
	align-items: center;
	height: 420rpx;
}
.stage-empty-text {
	color: #9aa1d4;
	font-size: 26rpx;
}
.stage-loading {
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	justify-content: center;
	align-items: center;
}
.stage-loading-text {
	color: #ffffff;
	font-size: 26rpx;
	background-color: rgba(0, 0, 0, 0.5);
	padding: 10rpx 24rpx;
	border-radius: 8rpx;
}
.controls {
	flex: 1;
	padding: 24rpx;
}
.row {
	margin-top: 24rpx;
	margin-bottom: 10rpx;
}
.row-label {
	color: #c2c7f0;
	font-size: 24rpx;
}
.chip-row {
	flex-direction: row;
	flex-wrap: wrap;
}
.chip {
	background-color: #1a1f4a;
	border-radius: 30rpx;
	padding-left: 24rpx;
	padding-right: 24rpx;
	padding-top: 10rpx;
	padding-bottom: 10rpx;
	margin-right: 14rpx;
	margin-bottom: 14rpx;
	border-width: 1rpx;
	border-color: #2a3070;
	border-style: solid;
}
.chip-active {
	background-color: #4a5dff;
	border-color: #4a5dff;
}
.chip-text {
	color: #9aa1d4;
	font-size: 24rpx;
}
.chip-text-active {
	color: #ffffff;
	font-weight: bold;
}
.url-item {
	flex-direction: row;
	align-items: center;
	background-color: #1a1f4a;
	border-radius: 12rpx;
	padding: 18rpx 20rpx;
	margin-bottom: 12rpx;
	border-width: 1rpx;
	border-color: #2a3070;
	border-style: solid;
}
.url-item-active {
	background-color: #2a3070;
	border-color: #4a5dff;
}
.url-tag {
	font-size: 20rpx;
	color: #ffffff;
	padding: 4rpx 14rpx;
	border-radius: 6rpx;
	margin-right: 16rpx;
	min-width: 80rpx;
	text-align: center;
}
.url-tag-RTMP {
	background-color: #ff6b6b;
}
.url-tag-M3U8 {
	background-color: #4ecdc4;
}
.url-tag-MP4 {
	background-color: #ffa94d;
}
.url-tag-RTSP {
	background-color: #ae8fff;
}
.url-tag-FLV {
	background-color: #f06292;
}
.url-tag-HTTP {
	background-color: #607d8b;
}
.custom-row {
	flex-direction: row;
	align-items: center;
	margin-bottom: 10rpx;
}
.custom-input {
	flex: 1;
	height: 70rpx;
	background-color: #1a1f4a;
	border-radius: 12rpx;
	padding-left: 20rpx;
	padding-right: 20rpx;
	color: #ffffff;
	font-size: 24rpx;
	border-width: 1rpx;
	border-color: #2a3070;
	border-style: solid;
}
.custom-btn {
	margin-left: 14rpx;
	margin-bottom: 0;
}
.current-url {
	background-color: #0a0d22;
	border-radius: 10rpx;
	padding: 12rpx 16rpx;
	margin-top: 10rpx;
	border-width: 1rpx;
	border-color: #2a3070;
	border-style: solid;
}
.current-url-text {
	color: #4ecdc4;
	font-size: 20rpx;
	font-family: monospace;
}
.url-text {
	color: #c2c7f0;
	font-size: 24rpx;
	flex: 1;
}
.url-text-active {
	color: #ffffff;
}
.btn-row {
	flex-direction: row;
	flex-wrap: wrap;
	margin-bottom: 12rpx;
}
.btn {
	background-color: #1a1f4a;
	border-radius: 12rpx;
	padding: 16rpx 30rpx;
	margin-right: 14rpx;
	margin-bottom: 10rpx;
	border-width: 1rpx;
	border-color: #2a3070;
	border-style: solid;
}
.btn-primary {
	background-color: #4a5dff;
	border-color: #4a5dff;
}
.btn-muted {
	background-color: #2a3070;
	border-color: #2a3070;
}
.btn-text {
	color: #ffffff;
	font-size: 26rpx;
}
.log-box {
	background-color: #0a0d22;
	border-radius: 12rpx;
	padding: 16rpx;
	border-width: 1rpx;
	border-color: #2a3070;
	border-style: solid;
	min-height: 200rpx;
}
.log-line {
	flex-direction: row;
	margin-bottom: 6rpx;
	flex-wrap: wrap;
}
.log-time {
	color: #6a72b3;
	font-size: 20rpx;
	margin-right: 10rpx;
}
.log-text {
	color: #c2c7f0;
	font-size: 22rpx;
	flex: 1;
}
.log-err {
	color: #ff6b6b;
}
.log-empty {
	color: #6a72b3;
	font-size: 22rpx;
	font-style: italic;
}
</style>
