<template>
	<view class="live-video-player">
		<!-- 预告片预览视频 status == 1 -->
		<view v-if="liveItem && liveItem.status == 1 && liveItem.previewUrl" class="preview-wrap">
			<view class="video-container2"
				:style="{ paddingBottom: videoRatio + '%', height: 'auto', width: '100%' }">
				<video :id="videoId" class="trailer-video" :src="liveItem.previewUrl" :autoplay="true"
					:loop="false" :object-fit="isHeight ? 'contain' : 'fill'" :custom-cache="false"
					:enable-progress-gesture="false" vslide-gesture-in-fullscreen="false"
					:show-center-play-btn="false" :http-cache="false" :disable-progress="true"
					:enable-play-gesture="true" preload="auto" type="application/x-mpegURL" :controls="false"
					@error="videoError" @loadedmetadata="onVideoMetaLoaded" @pause="onVideoPause"
					@play="onVideoPlay" @waiting="onVideoWaiting" @statechange="onLiveStateChange"></video>
			</view>
		</view>

		<!-- 直播中 status == 2 -->
		<view class="videolist" v-if="liveItem && liveItem.status == 2" :class="isFullscreen ? 'screen' : ''">
			<view class="video-container"
				:style="{
					paddingBottom: liveItem.showType == 2 || isFullscreen ? '' : videoRatio + '%',
					height: liveItem.showType == 2 ? '100vh' : isFullscreen ? 'auto' : '400rpx',
					width: isFullscreen ? '0' : '100%'
				}"
				:class="{ 'horizontal-layout': liveItem.showType == 1, 'fullscreen-mode': isFullscreen }">
				<video v-if="liveItem.videoUrl && liveItem.liveType == 2 && !generating" :id="videoId"
					:autoplay="true" class="video-player" :src="liveItem.videoUrl"
					:style="{
						transform: liveItem.showType !== 2 ? `scale(${scale})` : '',
						transformOrigin: 'center center',
						bottom: isFullscreen ? '0' : ''
					}"
					:object-fit="liveItem.showType == 2 || isFullscreen ? 'contain' : 'fill'"
					:custom-cache="false" :enable-progress-gesture="false"
					vslide-gesture-in-fullscreen="false" :show-center-play-btn="false" :http-cache="false" loop
					@error="videoError" @timeupdate="onVideoTimeUpdate" @loadedmetadata="onVideoMetaLoaded"
					@pause="onVideoPause" @play="onVideoPlay" @waiting="onVideoWaiting"
					:enable-play-gesture="false" :play-strategy="1" @dblclick="preventDoubleClick" preload="auto"
					:enable-stash-buffer="false" :stash-initial-size="0" :stash-max-size="0" :stash-time="0"
					type="application/x-mpegURL" :controls="false" :show-fullscreen-btn="false" show-play-btn
					show-mute-btn enable-play-gesture="true" @fullscreenchange="onFullscreenChange"
					x5-video-player-fullscreen="false" x5-video-player-type="h5"
					x5-video-orientation="landscape" :webkit-playsinline="true" playsinline="true"
					:x5-playsinline="true" @statechange="onLiveStateChange"></video>
				<view v-else class="txt">回放生成中...</view>

				<view v-if="showCustomControls && liveItem.showType == 1 && !isFullscreen" class="custom-controls"
					@click.stop="toggleFullscreen">
					<image src="/static/images/full_screen.png" class="control-icon" />
				</view>

				<view v-if="isFullscreen" class="fullscreen-exit-btn" @click="exitFullscreen">
					<image src="/static/images/half_screen.png" class="exit-fullscreen-icon" />
					<text class="exit-text">退出全屏</text>
				</view>

				<view v-if="liveItem.showType == 2 || isFullscreen" class="complaint-box"
					:class="isFullscreen ? 'complaint-full' : ''"
					:style="{ top: isFullscreen ? '' : '15%', bottom: isFullscreen ? '86vw' : '' }"
					@click="goComplaint">
					<image class="image w32 h32 mr10" src="/static/images/complaint.png" mode="widthFix" />
					<view class="fs26">投诉</view>
				</view>

				<view v-if="isPlayback" class="replay-label"
					:style="{
						top: liveItem.showType === 2 ? '22%' : isFullscreen ? '' : '10%',
						bottom: isFullscreen ? '75vw' : ''
					}"
					:class="isFullscreen ? 'replay-full' : ''">回放</view>

				<view class="look-time" v-if="isPlayback && liveItem.showType == 1"
					:class="isFullscreen ? 'look-full' : ''">{{ playbackTime }}</view>
			</view>
		</view>

		<!-- 直播结束 status == 3 -->
		<view class="videolist" v-if="liveItem && liveItem.status == 3">
			<view class="video-container" style="height: 500rpx;"
				:class="{ 'horizontal-layout': liveItem.showType == 1, 'fullscreen-mode': isFullscreen }">
				<view class="live-end-message" :style="{ marginTop: liveItem.showType === 2 ? '50%' : '' }">
					直播已结束
				</view>
			</view>
		</view>

		<!-- 直播回放 status == 4 -->
		<view class="videolist" v-if="liveItem && liveItem.status == 4">
			<view class="video-container" :class="liveItem.showType == 1 ? 'horizontal-layout' : ''">
				<video v-if="liveItem.videoUrl && liveItem.liveType == 3" :id="videoId" class="video-player"
					:src="liveItem.videoUrl" :autoplay="true" :controls="true"
					:object-fit="isFullscreen ? 'contain' : 'contain'" :custom-cache="false"
					:enable-progress-gesture="liveItem.isSpeedAllowed" vslide-gesture-in-fullscreen="true"
					:show-center-play-btn="true" :http-cache="false" loop @error="videoError"
					@timeupdate="onVideoTimeUpdate" @loadedmetadata="onVideoMetaLoaded" @pause="onVideoPause"
					@play="onVideoPlay" :enable-play-gesture="true" preload="auto" @waiting="onVideoWaiting"
					type="application/x-mpegURL" @statechange="onLiveStateChange"></video>
				<view v-if="liveItem.videoUrl && liveItem.liveType == 3" class="replay-label">直播回放</view>
			</view>
		</view>
	</view>
</template>

<script>
export default {
	name: 'LiveVideoPlayer',
	props: {
		liveId: {
			type: [String, Number],
			required: true
		},
		liveItem: {
			type: Object,
			default: () => ({})
		},
		isFullscreen: {
			type: Boolean,
			default: false
		},
		isHeight: {
			type: Boolean,
			default: false
		},
		videoRatio: {
			type: [String, Number],
			default: 56.25
		},
		scale: {
			type: [String, Number],
			default: 1
		},
		generating: {
			type: Boolean,
			default: false
		},
		isPlayback: {
			type: Boolean,
			default: false
		},
		playbackTime: {
			type: String,
			default: ''
		},
		liveCountdown: {
			type: Object,
			default: null
		}
	},
	data() {
		return {
			showCustomControls: true,
			videoContext: null,
			videoRetryCounts: {},
			isManualPause: false,
			waitingStartTime: 0,
			waitingTimer: null,
			lastVideoUpdateTime: 0
		};
	},
	computed: {
		videoId() {
			return `myVideo_${this.liveId}`;
		}
	},
	watch: {
		liveId() {
			this.initVideoContext();
		},
		isFullscreen(val) {
			this.showCustomControls = !val;
		}
	},
	mounted() {
		this.initVideoContext();
	},
	beforeDestroy() {
		if (this.waitingTimer) {
			clearTimeout(this.waitingTimer);
			this.waitingTimer = null;
		}
	},
	methods: {
		initVideoContext() {
			this.$nextTick(() => {
				this.videoContext = uni.createVideoContext(this.videoId, this);
			});
		},
		goComplaint() {
			uni.navigateTo({
				url: '/pages_shopping/live/complaintList'
			});
		},
		preventDoubleClick(e) {
			if (e && e.preventDefault) {
				e.preventDefault();
			}
			if (e && e.stopPropagation) {
				e.stopPropagation();
			}
			return false;
		},
		toggleFullscreen() {
			if (this.isFullscreen) {
				this.exitFullscreen();
			} else {
				this.$emit('fullscreen-change', true);
			}
		},
		exitFullscreen() {
			this.$emit('fullscreen-change', false);
		},
		onFullscreenChange(e) {
			let fullScreen = false;
			if (e.detail && typeof e.detail.fullScreen !== 'undefined') {
				fullScreen = e.detail.fullScreen;
			} else if (e.detail && typeof e.detail.fullscreen !== 'undefined') {
				fullScreen = e.detail.fullscreen;
			} else {
				try {
					const systemInfo = uni.getSystemInfoSync();
					fullScreen = systemInfo.windowWidth > systemInfo.windowHeight;
				} catch (err) {
					fullScreen = !!(e.detail && e.detail.fullScreen);
				}
			}
			this.showCustomControls = !fullScreen;
			this.$emit('fullscreen-change', fullScreen);
		},
		onLiveStateChange(e) {
			const code = e && e.detail ? e.detail.code : undefined;
			this.$emit('live-state-change', code);
		},
		playVideo() {
			if (!this.liveItem) {
				return;
			}
			try {
				this.$nextTick(() => {
					if (this.liveItem.liveType === 1 && this.liveItem.livingUrl && this.liveItem.status == 2) {
						return;
					}
					if (this.liveItem.status == 1 && this.liveItem.previewUrl) {
						this._playVideoWithRetry(this.videoId, 0);
					} else if (this.liveItem.liveType === 2 && this.liveItem.videoUrl && this.liveItem.status == 2) {
						this._playVideoWithRetry(this.videoId, 0);
					} else if (this.liveItem.liveType === 3 && this.liveItem.videoUrl && this.liveItem.status == 4) {
						this._playVideoWithRetry(this.videoId, 0);
					}
				});
			} catch (error) {
				console.error('播放视频失败:', error);
			}
		},
		_playVideoWithRetry(videoId, retryCount) {
			if (retryCount >= 3) {
				uni.showToast({
					title: '视频加载失败，请稍后重试',
					icon: 'none',
					duration: 2000
				});
				return;
			}

			const videoContext = uni.createVideoContext(videoId, this);
			if (!videoContext) {
				setTimeout(() => {
					this._playVideoWithRetry(videoId, retryCount + 1);
				}, 300);
				return;
			}

			this.$nextTick(() => {
				const query = uni.createSelectorQuery().in(this);
				query.select(`#${videoId}`).boundingClientRect((data) => {
					if (!data && retryCount < 2) {
						setTimeout(() => {
							this._playVideoWithRetry(videoId, retryCount + 1);
						}, 500);
						return;
					}
					try {
						videoContext.play();
					} catch (error) {
						setTimeout(() => {
							this._playVideoWithRetry(videoId, retryCount + 1);
						}, 500);
					}
				}).exec();
			});
		},
		pauseVideo() {
			if (!this.liveItem) {
				return;
			}
			try {
				if (this.liveItem.status == 1 || this.liveItem.status == 2 || this.liveItem.status == 4) {
					if (this.liveItem.status == 2 && this.liveItem.liveType === 1) {
						return;
					}
					const videoContext = uni.createVideoContext(this.videoId, this);
					if (videoContext) {
						videoContext.pause();
					}
				}
			} catch (error) {
				console.error('暂停视频失败:', error);
			}
		},
		videoError(e) {
			this.$emit('error', e);
			if (!this.liveItem || !this.liveId) {
				return;
			}
			const key = String(this.liveId);
			if (this.videoRetryCounts[key] === undefined) {
				this.videoRetryCounts[key] = 0;
			}
			if (this.videoRetryCounts[key] >= 3) {
				uni.showToast({
					title: '视频加载失败，请检查网络',
					icon: 'none',
					duration: 2000
				});
				return;
			}
			this.videoRetryCounts[key]++;
			setTimeout(() => {
				this.playVideo();
			}, 2000);
		},
		onVideoMetaLoaded(e) {
			this.$emit('loadedmetadata', e);
		},
		onVideoPause(e) {
			this.$emit('pause', e);
			if (this.liveItem.liveType === 2 && !this.isManualPause) {
				const videoContext = uni.createVideoContext(this.videoId, this);
				if (videoContext) {
					setTimeout(() => {
						if (!this.isManualPause && this.liveItem && this.liveItem.liveType === 2) {
							videoContext.play();
						}
					}, 200);
				}
			}
		},
		onVideoPlay(e) {
			this.isManualPause = false;
			if (this.waitingTimer) {
				clearTimeout(this.waitingTimer);
				this.waitingTimer = null;
			}
			this.waitingStartTime = 0;
			this.lastVideoUpdateTime = Date.now();
			this.$emit('play', e);
		},
		onVideoWaiting(e) {
			if (!this.waitingStartTime) {
				this.waitingStartTime = Date.now();
			}
			if (!this.waitingTimer) {
				this.waitingTimer = setTimeout(() => {
					const waitingDuration = Date.now() - this.waitingStartTime;
					const timeSinceLastUpdate = Date.now() - this.lastVideoUpdateTime;
					if (waitingDuration >= 5000 && timeSinceLastUpdate >= 3000) {
						uni.showToast({
							title: '当前您的网络不稳定',
							icon: 'none',
							duration: 2000
						});
					}
				}, 5000);
			}
		},
		onVideoTimeUpdate(e) {
			this.lastVideoUpdateTime = Date.now();
			if (this.waitingStartTime && this.lastVideoUpdateTime - this.waitingStartTime < 1000) {
				if (this.waitingTimer) {
					clearTimeout(this.waitingTimer);
					this.waitingTimer = null;
				}
				this.waitingStartTime = 0;
			}
			this.$emit('timeupdate', e);
		}
	}
};
</script>

<style scoped lang="scss">
.live-video-player {
	width: 100%;
	position: relative;
}

.preview-wrap {
	width: 100%;
}

.fullscreen-exit-btn {
	position: fixed;
	bottom: 40rpx;
	left: 82vh;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	z-index: 100001;
	background: rgba(57, 57, 57, 0.6);
	border-radius: 40rpx;
	padding: 20rpx 24rpx;
	transition: all 0.3s ease;

	&:active {
		transform: scale(0.95);
		background: rgba(50, 50, 50, 0.6);
	}

	.exit-fullscreen-icon {
		width: 40rpx;
		height: 40rpx;
		margin-bottom: 10rpx;
	}

	.exit-text {
		color: #ffffff;
		font-size: 22rpx;
		white-space: nowrap;
	}
}

.video-container.fullscreen-mode .fullscreen-exit-btn {
	z-index: 999999 !important;
}

.fullscreen-mode {
	background-color: #000 !important;
}

.video-container.fullscreen-mode {
	z-index: 99999 !important;
	background-color: #000 !important;
	transform: rotate(90deg) !important;
	transform-origin: center center !important;

	.video-player {
		width: 100vh !important;
		height: 100vw !important;
	}
}

.video-container.fullscreen-mode~* {
	display: none !important;
}

.video-container,
.video-container2 {
	position: relative;
	bottom: -1px;
	transition: all 0.3s ease;
}

.video-player.fullscreen {
	width: 100vh !important;
	height: 100vw !important;
	object-fit: contain !important;
}

.custom-controls {
	position: absolute;
	bottom: 24rpx;
	right: 40rpx;
	z-index: 9999;
	background: rgba(0, 0, 0, 0.6);
	border-radius: 50%;
	width: 80rpx;
	height: 80rpx;
	display: flex;
	align-items: center;
	justify-content: center;
	transition: all 0.3s ease;

	&:active {
		transform: scale(0.95);
		background: rgba(0, 0, 0, 0.8);
	}
}

.control-icon {
	width: 46rpx;
	height: 46rpx;
}

@media screen and (orientation: landscape) {
	.video-container.horizontal-layout {
		width: 100%;
		height: 100%;
	}
}

.videolist {
	position: relative;
	width: 100%;

	&.screen {
		width: 100%;
		height: 100%;
	}

	.video-container {
		width: 100%;
		transform: translateZ(0);
		backface-visibility: hidden;
		perspective: 1000;

		.complaint-box {
			position: absolute;
			right: 20rpx;
			width: 140rpx;
			margin-top: 20rpx;
			display: flex;
			align-items: center;
			justify-content: center;
			background-color: rgba(57, 57, 57, 0.6);
			padding: 16rpx 0;
			color: #fff;
			border-radius: 28rpx;
			z-index: 999999 !important;

			&.complaint-full {
				left: 82vh;
			}

			&:active {
				transform: scale(0.95);
				background: rgba(50, 50, 50, 0.6);
			}
		}

		.txt {
			text-align: center;
			font-weight: 500;
			font-size: 40rpx;
			line-height: 400rpx;
		}

		.video-player {
			width: 100%;
			height: 100%;
			position: absolute;
			z-index: 1;
		}

		.live-end-message {
			position: absolute;
			top: 50%;
			left: 50%;
			transform: translate(-50%, -50%);
			font-size: 36rpx;
			color: #ffffff;
		}

		.replay-label {
			position: absolute;
			right: 24rpx;
			background-color: rgba(57, 57, 57, 0.6);
			width: 100rpx;
			height: 70rpx;
			line-height: 70rpx;
			text-align: center;
			color: #fff;
			border-radius: 15rpx;
			z-index: 999999 !important;

			&.replay-full {
				left: 82vh;
			}
		}

		.look-time {
			position: absolute;
			left: 24rpx;
			bottom: 24rpx;
			font-size: 20rpx;
			background-color: rgba(57, 57, 57, 0.6);
			border-radius: 15rpx;
			z-index: 999999 !important;
			padding: 10rpx 16rpx;
			color: #fff;

			&.look-full {
				left: 10vh;
			}
		}
	}
}

.trailer-video {
	width: 100%;
	height: 100%;
	position: absolute;
	z-index: 1;
	border-radius: 20rpx;
}
</style>
