import React, {useEffect, useMemo, useRef, useState} from "react";
import {Checkbox, Empty, Modal, Space} from "antd";
import {SortableContext, arrayMove} from '@dnd-kit/sortable';
import {DndContext} from "@dnd-kit/core";

import {VideoListItem} from "@/components/video/video-list-item.tsx";
import {deleteByIds, getList, modifyOrder, playState} from "@/service/api/live.ts";

import {showErrorToast, showToast} from "@/components/message.ts";
import ButtonBatch from "@/components/button-batch.tsx";
import FlvJs from "flv.js";
import {formatDuration} from "@/util/strings.ts";
import {useSetState} from "ahooks";
import {Player, PlayerInstance} from "@/components/video/player.tsx";
import {IconDelete, IconLocked, IconUnlock} from "@/components/icons";
import InfiniteScroller, {InfiniteScrollerRef} from "@/components/scoller/infinite-scroller.tsx";
import ButtonToTop from "@/components/scoller/button-to-top.tsx";
import {useTranslation} from "react-i18next";

const cache: { flvPlayer?: FlvJs.Player, timerPlayNext?: any, timerLoadState?: any, prevUrl?: string } = {}
export default function LiveIndex() {
	const {t} = useTranslation()
	const player = useRef<PlayerInstance | null>(null)

	const [videoData, setVideoData] = useState<LiveVideoInfo[]>([])
	const [modal, contextHolder] = Modal.useModal()
	const [checkedIdArray, setCheckedIdArray] = useState<number[]>([])
	const [editable, setEditable] = useState<boolean>(false)
	const scrollerRef = useRef<InfiniteScrollerRef | null>(null)

	const [state, setState] = useSetState({
		activeIndex: -1,
		muted: true,
		showToTop: false,
		checkedAll: false,
		originSort: '',
		playProgress: 0,
		loading:false
	})
	const activeIndex = useRef(state.activeIndex)
	useEffect(() => {
		activeIndex.current = state.activeIndex
	}, [state.activeIndex])

	const showVideoItem = (index: number) => {
		// 找到对应video item 并显示在视图可见区域
		const container = document.querySelector('.live-video-list-sort-container')
		const item = document.querySelector(`.list-item-${index}`)
		if (item && container) {
			// 获取容器数据
			const containerRect = container.getBoundingClientRect()
			// 获取对应item的数据
			const rect = item.getBoundingClientRect()
			// 计算对应item需要在容器中滚动的距离
			const scrollDistance = rect.top - containerRect.top
			// 设置滚动高度
			container.scrollTo({
				top: index == 0 ? 0 : container.scrollTop + scrollDistance - 10,
				behavior: 'smooth'
			})
		}
	}

	const activeToNext = (index?: number) => {
		const endToFirst = index != undefined && index > -1 ? false : activeIndex.current >= videoData.length - 1
		const _activeIndex = index != undefined && index > -1 ? index : (endToFirst ? 0 : activeIndex.current + 1)
		setState({activeIndex: _activeIndex})
		if (endToFirst) {
			showToast(t("live.play_first"));
		}
		// 找到对应video item 并显示在视图可见区域
		showVideoItem(_activeIndex)
		return _activeIndex;
	}
	const playVideo = (video: LiveVideoInfo, liveState: LiveState) => {
		if (player.current && video.video_oss_url) {
			if (cache.timerPlayNext) clearTimeout(cache.timerPlayNext)
			const duration = Math.ceil(video.video_duration / 1000)
			const playedTime = (Date.now() / 1000 >> 0) - liveState.live_start_time
			if (playedTime < 0 || playedTime > duration) { // 已播放时间大于总时长了
				//initPlayingState() // 重新获取播放状态
				return;
			}
			player.current?.play(video.video_oss_url, playedTime)
			cache.timerPlayNext = setTimeout(() => {
				const index = activeToNext(), nextVideo = videoData[index]
				playVideo(nextVideo, {live_start_time: (Date.now() / 1000 >> 0), id: nextVideo.id})
			}, (duration - playedTime) * 1000)

		}
	}
	const initPlayingState = () => {
		if (cache.timerLoadState) clearTimeout(cache.timerLoadState)
		if (videoData.length == 0) {
			cache.timerLoadState = setTimeout(initPlayingState, 1000)
			return;
		}
		playState().then(liveState => {
			const video = videoData.find(v => v.id === liveState.id)
			if (video) {
				activeToNext(videoData.findIndex(v => v.id === liveState.id))
				playVideo(video, liveState)
			} else {
				setState({activeIndex: -1})
				cache.timerLoadState = setTimeout(initPlayingState, 5000)
			}
		});
	}
	const clearAllTimer = () => {
		if (cache.timerPlayNext) clearTimeout(cache.timerPlayNext)
		if (cache.timerLoadState) clearTimeout(cache.timerLoadState)
	}

	const loadList = () => {
		clearAllTimer();
		setState({loading: true})
		getList().then(res => {
			// console.log('origin list', res.list.map(s => s.id))
			setVideoData(() => (res.list || []))
			setState({
				originSort: res.list ? res.list.map(s => s.id).join(',') : ''
			})
			setCheckedIdArray([])
		}).catch(showErrorToast).finally(()=>{
			setState({loading: false})
		});
	}

	useEffect(initPlayingState, [videoData])
	useEffect(() => {
		loadList()
		return ()=>{
			clearAllTimer();
			setTimeout(()=>{
				console.log('pause all video')
				try{
					Array.from(document.querySelectorAll('video')).forEach(v => v.pause())
				}catch (e){
					console.log(e)
				}
			},20)
		}
	}, [])

	const processDeleteVideo = async (ids: Id[]) => {
		deleteByIds(ids).then(() => {
			showToast(t('delete_success'), 'success')
			loadList()
		}).catch(showErrorToast)
	}
	const handleConfirm = () => {
		if (!editable) {
			setEditable(true)
			return;
		}
		const newSort = videoData.map(s => s.id).join(',')
		if (newSort == state.originSort) {
			setEditable(false)
			return;
		}
		modal.confirm({
			title: t('confirm.title'),
			content: t('video.sort_modify_confirm'),
			centered: true,
			onOk: () => {
				//showToast('编辑成功!!!', 'info');
				modifyOrder(videoData.map(s => s.id)).then(() => {
					showToast(t('video.sort_modify_live_success'), 'success')
					setEditable(false)
				}).catch(() => {
					showToast(t('video.sort_modify_failed'), 'warning')
				})
			},
			onCancel: () => {
				showToast(t('video.sort_modify_rollback'), 'info');
				loadList()
				setEditable(false)
			}
		})
	}
	const handleAllCheckedChange = () => {
		setCheckedIdArray(state.checkedAll ? [] : videoData.map(v => v.id))
		setState({
			checkedAll: !state.checkedAll
		})
	}

	const totalDuration = useMemo(() => {
		if (!videoData || videoData.length == 0) return 0;
		// 计算总时长
		return videoData.reduce((sum, v) => sum + Math.ceil(v.video_duration / 1000), 0);
	}, [videoData])
	// 根据当前播放index计算已经播放时长
	const currentTotalDuration = useMemo(() => {
		if (state.activeIndex == -1 || !videoData || videoData.length == 0) return 0;
		// 计算总时长
		return videoData
			.filter((_, index) => (index < state.activeIndex))
			.reduce((sum, v) => sum + Math.ceil(v.video_duration / 1000), 0) + state.playProgress
			;
	}, [videoData, state.playProgress])

	const currentSelectedId = useMemo(() => {
		if (state.activeIndex < 0 || state.activeIndex >= videoData.length) return [];
		const currentId = videoData[state.activeIndex];
		return checkedIdArray.filter(id => currentId.id != id)
	}, [checkedIdArray, state.activeIndex])

	return (<div className="container py-5 page-live">
		<div className="h-[36px]"></div>
		<div className="flex">
			<div className="video-player-container mr-16 flex items-center">
				<div>
					<div className="text-center text-base text-gray-400">{t('live.title')}</div>
					<div className="video-player flex justify-center flex-1 mt-1">
						<div className="live-player relative rounded overflow-hidden w-[360px] h-[636px]"
						     style={{backgroundColor: 'hsl(210, 100%, 48%)'}}>
							<Player
								ref={player} className="w-[360px] h-[636px] bg-white"
								muted={true}
								onProgress={(progress) => {
									setState({playProgress: progress})
								}}
							/>
						</div>
					</div>
					<div className="text-center text-sm mt-4 text-gray-400">
						<span>{t('live.duration')}: {formatDuration(currentTotalDuration)} / {formatDuration(totalDuration)}</span>
					</div>
				</div>
			</div>
			<div className="video-list-container video-list-sort-container flex flex-col flex-1 mt-2">
				<div className="live-control flex justify-between mb-1">
					<div>
						<Space>
							{/*<span className={"text-blue-500"}>视频正在播放{state.activeIndex == -1 ? '' : `到 ${state.activeIndex + 1} 条`}</span>*/}
							<span>{t('live.playlist_count',{count:videoData.length})}</span>
						</Space>
					</div>

					<div className="flex items-center">
						<div className={'flex items-center text-gray-400 cursor-pointer select-none'}
						     onClick={handleConfirm}>
							<span>{editable ? t('live.edit_unlock') : t('live.edit_locked')}</span>
							<span className="ml-2 text-sm">
								{editable ? <IconUnlock/> : <IconLocked/>}
							</span>
						</div>
						<div className="check-all ml-10">
							<button className="hover:text-blue-300 text-gray-400"
							        onClick={handleAllCheckedChange}>
								<span className="text-sm mr-2 whitespace-nowrap">{t('select.select_all')}</span>
								{/*<CheckCircleFilled className={clsx({'text-blue-500': state.checkedAll})}/>*/}
							</button>
							<Checkbox checked={state.checkedAll} onChange={() => handleAllCheckedChange()}/>
						</div>
					</div>
				</div>
				<div className="list-header">
					<div className="list-row header-row">
						<div className="col number">No.</div>
						<div className="col cover">{t('video.title_thumb')}</div>
						<div className="col title">{t('video.title')}</div>
						<div className="col generated-time">{t('video.title_generated_time')}</div>
						<div className="col operation">{t('video.title_operation')}</div>
					</div>
				</div>
				<div className="">
					<div className="live-video-list-sort-container ">
						<InfiniteScroller
							ref={scrollerRef}
							loading={state.loading}
							onScroll={top => setState({showToTop: top > 30})}
							onCallback={() => {
							}}
						>
							{videoData.length == 0 && <div className="m-auto py-16"><Empty/></div>}
							<div className="sort-list-container flex-1">
								<DndContext onDragEnd={(e) => {
									const {active, over} = e;
									if (over && active.id !== over.id) {
										let oldIndex = -1, newIndex = -1;
										setVideoData((items) => {
											oldIndex = items.findIndex(s => s.id == active.id);
											newIndex = items.findIndex(s => s.id == over.id);
											return arrayMove(items, oldIndex, newIndex);
										});
									}
								}}>
									<SortableContext items={videoData}>
										{videoData.map((v, index) => (
											<VideoListItem
												video={v}
												index={index + 1}
												id={v.id}
												key={index}
												active={state.activeIndex == index}
												playing={state.activeIndex == index}
												className={`list-item-${index} mt-3 mb-2`}
												checked={checkedIdArray.includes(v.id)}
												onCheckedChange={(checked) => {
													const newIdArray = checked ? checkedIdArray.concat(v.id) : checkedIdArray.filter(id => id != v.id);
													setState({checkedAll: newIdArray.length == videoData.length})
													setCheckedIdArray(newIdArray)
													// setCheckedIdArray(idArray => {
													// 	return checked ? idArray.concat(v.id) : idArray.filter(id => id != v.id);
													// })
												}}
												onRemove={() => processDeleteVideo([v.id])}
												editable={!editable && state.activeIndex != index}
												sortable={editable && state.activeIndex != index}
											/>))}
									</SortableContext>
								</DndContext>
							</div>
						</InfiniteScroller>
					</div>
				</div>
			</div>
		</div>
		<div className="page-action">
			<ButtonToTop visible={state.showToTop} onClick={() => scrollerRef.current?.scrollToPosition(0)}/>
			{checkedIdArray.length > 0 && <ButtonBatch
                className='bg-gray-300 hover:bg-gray-400 text-white'
                selected={checkedIdArray}
                emptyMessage={t('video.delete_empty')}
                confirmMessage={t('video.delete_description',{count:checkedIdArray.length})}
                onSuccess={loadList}
                onProcess={processDeleteVideo}
            >
                <span className={'text'}>{t('delete_batch')}</span>
                <IconDelete/>
            </ButtonBatch>}
		</div>
		{contextHolder}
	</div>)
}