'use client'

import { useState, useEffect, useRef, useCallback, useMemo } from 'react'
import { useParams, useRouter } from 'next/navigation'
import Image from 'next/image'
import Header from '@/components/Header'
import Sidebar from '@/components/Sidebar'
import BackToTop from '@/components/BackToTop'
import { useTranslation } from 'react-i18next'
import { FaArrowUp, FaArrowDown } from 'react-icons/fa'
import { FiX } from 'react-icons/fi'
import Skeleton from '@/components/Skeleton'
import MobileVideoPlayer from '../_components/MobileVideoPlayer'
import DesktopVideoPlayer from '../_components/DesktopVideoPlayer'
import VideoInfoCard from '../_components/VideoInfoCard'
import InteractionButtons from '../_components/InteractionButtons'
import DesktopInteractionButtons from '../_components/DesktopInteractionButtons'
import DesktopVideoInfo from '../_components/DesktopVideoInfo'
import CommentsList from '../_components/CommentsList'
import CommentInput from '../_components/CommentInput'
import CommentItem from '../_components/CommentItem'
import CommentsPanel from '../_components/CommentsPanel'
import RelatedVideos from '../_components/RelatedVideos'
import { formatViews } from '@/utils/format'
import { useToast } from '@/contexts/ToastContext'
import type { CatchVideo, Comment } from '../_components/types'
import {
    MobileVideoPlayerSkeleton,
    DesktopVideoPlayerSkeleton,
    VideoInfoCardSkeleton,
    InteractionButtonsSkeleton,
    DesktopInteractionButtonsSkeleton,
    CommentsListSkeleton,
    RelatedVideosSkeleton,
} from '../_components/Skeletons'


export default function CatchPage() {
    const params = useParams()
    const router = useRouter()
    const { t } = useTranslation()
    const { showToast } = useToast()
    const [sidebarOpen, setSidebarOpen] = useState(false)
    const [isPlaying, setIsPlaying] = useState(false)
    const [volume, setVolume] = useState(0.7)
    const [isMuted, setIsMuted] = useState(false)
    const [showVolume, setShowVolume] = useState(false)
    const CHUNK_SIZE = 5
    const [activeIndex, setActiveIndex] = useState(0)
    const [catchVideos, setCatchVideos] = useState<CatchVideo[]>([])
    const [loadedCount, setLoadedCount] = useState(0)
    const currentVideo = catchVideos[activeIndex] || null
    const [relatedVideos, setRelatedVideos] = useState<CatchVideo[]>([])
    const [commentsOpen, setCommentsOpen] = useState(false)
    const [desktopCommentsOpen, setDesktopCommentsOpen] = useState(false)
    const [isCommentsClosing, setIsCommentsClosing] = useState(false)
    const [isLiked, setIsLiked] = useState(false)
    const [isLoading, setIsLoading] = useState(true)
    const [commentsLoading, setCommentsLoading] = useState(false)
    const [comments, setComments] = useState<Comment[]>([])
    const [videoLikes, setVideoLikes] = useState<Record<string, number>>({})
    const [videoIsLiked, setVideoIsLiked] = useState<Record<string, boolean>>({})
    const [videoComments, setVideoComments] = useState<Record<string, number>>({})
    const [currentUserId, setCurrentUserId] = useState<string | null>(null)
    const [userAvatar, setUserAvatar] = useState<string | null>(null)
    // 使用單獨的 state 來管理當前視頻的 comments 計數，避免更新 catchVideos 導致重新渲染
    const [currentVideoComments, setCurrentVideoComments] = useState<number>(0)
    const [videoOwnerId, setVideoOwnerId] = useState<string | null>(null)
    const scrollLockRef = useRef(false)
    const isProgrammaticScrollRef = useRef(false)
    const feedRef = useRef<HTMLDivElement>(null)
    const desktopFeedRef = useRef<HTMLDivElement>(null)
    const videoItemRefs = useRef<(HTMLDivElement | null)[]>([])
    const desktopVideoItemRefs = useRef<(HTMLDivElement | null)[]>([])
    const currentIndexRef = useRef<number>(0)
    const switchLockRef = useRef(false)
    const lastKeySwitchRef = useRef(0)
    const lastWheelTimeRef = useRef(0)
    const wheelLockRef = useRef(false)

    const setVideoById = useCallback((rawId: string) => {
        if (switchLockRef.current || catchVideos.length === 0) return
        switchLockRef.current = true
        let index = catchVideos.findIndex((v) => v.id === rawId)
        if (index < 0) {
            const cleanId = rawId.replace(/^(catch-|virtual-catch-|music-catch-)/, '')
            index = catchVideos.findIndex((v) => v.id === cleanId)
        }

        if (index >= 0) {
            const video = catchVideos[index]
            setActiveIndex(index)
            currentIndexRef.current = index
            if (typeof window !== 'undefined') {
                window.history.replaceState({}, '', `/catch/${video.id}`)
            }
        }
        setTimeout(() => {
            switchLockRef.current = false
        }, 300)
    }, [catchVideos])

    useEffect(() => {
        if (!currentVideo || catchVideos.length === 0) return
        setRelatedVideos(catchVideos.filter((v) => v.id !== currentVideo.id).slice(0, 6))
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [currentVideo?.id, catchVideos])


    // 手機模式正常應該撐滿版不產生 overflow。
    // 只有在視窗寬度「真的小於最小支援寬度」時，才用水平捲動避免擠壓。
    useEffect(() => {
        if (typeof window === 'undefined') return
        const MIN_WIDTH = 380
        const html = document.documentElement
        const body = document.body

        const prevHtmlMinWidth = html.style.minWidth
        const prevBodyMinWidth = body.style.minWidth
        const prevHtmlOverflowX = html.style.overflowX
        const prevBodyOverflowX = body.style.overflowX

        const apply = () => {
            if (window.innerWidth < MIN_WIDTH) {
                html.style.minWidth = `${MIN_WIDTH}px`
                body.style.minWidth = `${MIN_WIDTH}px`
                html.style.overflowX = 'auto'
                body.style.overflowX = 'auto'
            } else {
                // >= 最小寬度時，不應該有水平 overflow：直接隱藏 X 軸，避免 1px 誤差造成水平捲動
                html.style.minWidth = prevHtmlMinWidth
                body.style.minWidth = prevBodyMinWidth
                html.style.overflowX = 'hidden'
                body.style.overflowX = 'hidden'
            }
        }

        apply()
        window.addEventListener('resize', apply)
        return () => {
            window.removeEventListener('resize', apply)
            html.style.minWidth = prevHtmlMinWidth
            body.style.minWidth = prevBodyMinWidth
            html.style.overflowX = prevHtmlOverflowX
            body.style.overflowX = prevBodyOverflowX
        }
    }, [])

    useEffect(() => {
        if (typeof window === 'undefined') return
        const body = document.body
        const prevOverflowY = body.style.overflowY

        const apply = () => {
            if (window.innerWidth < 768 && !desktopCommentsOpen) {
                body.style.overflowY = 'hidden'
            } else if (!desktopCommentsOpen) {
                body.style.overflowY = prevOverflowY
            }
        }

        apply()
        window.addEventListener('resize', apply)
        return () => {
            window.removeEventListener('resize', apply)
            if (!desktopCommentsOpen) body.style.overflowY = prevOverflowY
        }
    }, [desktopCommentsOpen])

    const handleCloseComments = () => {
        setIsCommentsClosing(true)
        setTimeout(() => {
            setDesktopCommentsOpen(false)
            setIsCommentsClosing(false)
        }, 200)
    }

    useEffect(() => {
        const fetchUserInfo = async () => {
            try {
                const response = await fetch('/api/profile/user-info')
                const result = await response.json()
                if (result.ok && result.id) {
                    setCurrentUserId(result.id)
                    setUserAvatar(result.avatarUrl || null)
                } else {
                    setCurrentUserId(null)
                    setUserAvatar(null)
                }
            } catch (error) {
                console.error('Failed to fetch user info:', error)
                setCurrentUserId(null)
                setUserAvatar(null)
            }
        }
        fetchUserInfo()
    }, [])

    const fetchComments = useCallback(async (videoId: string) => {
        if (!videoId) return

        setCommentsLoading(true)
        try {
            const commentsResponse = await fetch(`/api/catch/${encodeURIComponent(videoId)}/comments`)
            const commentsResult = await commentsResponse.json()
            if (commentsResult.ok && commentsResult.data) {
                setComments(commentsResult.data)
                // 同步更新當前視頻的 comments 計數（使用實際留言數量）
                const commentsCount = commentsResult.data.length || 0
                setCurrentVideoComments(commentsCount)
                setVideoComments((prev) => ({
                    ...prev,
                    [videoId]: commentsCount,
                }))
            } else {
                setComments([])
                setCurrentVideoComments(0)
                setVideoComments((prev) => ({
                    ...prev,
                    [videoId]: 0,
                }))
            }
        } catch (error) {
            console.error('Failed to fetch comments:', error)
            setComments([])
            setCurrentVideoComments(0)
        } finally {
            setCommentsLoading(false)
        }
    }, [])

    useEffect(() => {
        if (!currentVideo?.id) return

        // 立即從 currentVideo.comments 設置初始值，避免延遲
        if (currentVideo.comments !== undefined) {
            setCurrentVideoComments(currentVideo.comments)
        }

        const fetchVideoOwnerAndComments = async () => {
            setCommentsLoading(true)
            try {
                const videoResponse = await fetch(`/api/catch/${encodeURIComponent(currentVideo.id)}`)
                const videoResult = await videoResponse.json()
                if (videoResult.ok && videoResult.data) {
                    const ownerId = videoResult.data.userId
                    // 確保不是字符串 "null" 或 "undefined"，並且是有效的字符串
                    if (ownerId != null && typeof ownerId === 'string' && ownerId.trim() !== '' && ownerId !== 'null' && ownerId !== 'undefined') {
                        setVideoOwnerId(ownerId)
                    } else {
                        setVideoOwnerId(null)
                    }

                    // 更新精確的 comments 計數（如果 API 返回了）
                    if (videoResult.data.comments !== undefined) {
                        setCurrentVideoComments(videoResult.data.comments)
                    }
                } else {
                    setVideoOwnerId(null)
                }

                await fetchComments(currentVideo.id)
            } catch (error) {
                console.error('Failed to fetch video owner and comments:', error)
                setComments([])
                setCurrentVideoComments(0)
                setCommentsLoading(false)
            }
        }

        fetchVideoOwnerAndComments()
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [currentVideo?.id, fetchComments])

    useEffect(() => {
        if ((commentsOpen || desktopCommentsOpen) && currentVideo?.id) {
            fetchComments(currentVideo.id)
        }
    }, [commentsOpen, desktopCommentsOpen, currentVideo?.id, fetchComments])

    // 處理創建新留言（根留言）
    const handleCreateComment = async (content: string) => {
        if (!currentVideo?.id) {
            console.error('Missing video ID')
            return
        }

        try {
            const response = await fetch(`/api/catch/${encodeURIComponent(currentVideo.id)}/comments`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    content: content,
                }),
            })

            const result = await response.json()
            if (result.ok && result.data) {
                const commentsResponse = await fetch(`/api/catch/${encodeURIComponent(currentVideo.id)}/comments`)
                const commentsResult = await commentsResponse.json()
                if (commentsResult.ok && commentsResult.data) {
                    setComments(commentsResult.data)
                    // 只更新當前視頻的 comments 計數（使用單獨的 state，完全不更新 catchVideos）
                    setCurrentVideoComments(commentsResult.data.length || 0)
                }
                // 不更新 catchVideos，避免導致視頻重新渲染
            } else {
                if (result.error === 'UNAUTHORIZED') {
                    showToast(t('catch.toast.loginRequiredComment'), 'error')
                } else {
                    console.error('Failed to create comment:', result.message)
                    showToast(t('catch.toast.commentFailed'), 'error')
                }
            }
        } catch (error) {
            console.error('Failed to create comment:', error)
            showToast(t('catch.toast.commentFailed'), 'error')
        }
    }

    // 處理回覆功能
    const handleReply = async (commentId: string, replyText: string, replyTo: string) => {
        if (!currentVideo?.id) {
            console.error('Missing video ID')
            return
        }

        try {
            const response = await fetch(`/api/catch/${encodeURIComponent(currentVideo.id)}/comments`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    content: replyText,
                    parentId: commentId,
                    replyTo: replyTo,
                }),
            })

            const result = await response.json()
            if (result.ok && result.data) {
                const commentsResponse = await fetch(`/api/catch/${encodeURIComponent(currentVideo.id)}/comments`)
                const commentsResult = await commentsResponse.json()
                if (commentsResult.ok && commentsResult.data) {
                    setComments(commentsResult.data)
                    // 只更新當前視頻的 comments 計數（使用單獨的 state，完全不更新 catchVideos）
                    setCurrentVideoComments(commentsResult.data.length || 0)
                }
                // 不更新 catchVideos，避免導致視頻重新渲染
            } else {
                if (result.error === 'UNAUTHORIZED') {
                    showToast(t('catch.toast.loginRequiredReply'), 'error')
                } else {
                    console.error('Failed to create reply:', result.message)
                    showToast(t('catch.toast.replyFailed'), 'error')
                }
            }
        } catch (error) {
            console.error('Failed to create reply:', error)
            showToast(t('catch.toast.replyFailed'), 'error')
        }
    }

    const handlePin = async (commentId: string, isPinned: boolean) => {
        if (!currentVideo?.id) {
            console.error('Missing video ID')
            return
        }

        const videoId = currentVideo.id

        try {
            const response = await fetch(`/api/catch/${encodeURIComponent(videoId)}/comments`, {
                method: 'PATCH',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    commentId,
                    isPinned,
                }),
            })

            const result = await response.json()
            if (result.ok) {
                const commentsResponse = await fetch(`/api/catch/${encodeURIComponent(videoId)}/comments`)
                const commentsResult = await commentsResponse.json()
                if (commentsResult.ok && commentsResult.data) {
                    setComments(commentsResult.data)
                }
                showToast(isPinned ? t('catch.toast.pinSuccess') : t('catch.toast.unpinSuccess'), 'success')
            } else {
                if (result.error === 'UNAUTHORIZED') {
                    showToast(t('catch.toast.loginRequired'), 'error')
                } else if (result.error === 'FORBIDDEN') {
                    showToast(t('catch.toast.onlyOwnerPin'), 'error')
                } else if (result.error === 'CANNOT_PIN_REPLY') {
                    showToast(t('catch.toast.onlyRootPin'), 'error')
                } else {
                    console.error('Failed to pin/unpin comment:', result.message)
                    showToast(t('catch.toast.actionFailed'), 'error')
                }
            }
        } catch (error) {
            console.error('Failed to pin/unpin comment:', error)
            showToast(t('catch.toast.actionFailed'), 'error')
        }
    }

    // 處理留言喜歡功能
    const handleCommentLike = async (commentId: string) => {
        if (!currentVideo?.id) {
            console.error('Missing video ID')
            return
        }

        const videoId = currentVideo.id

        try {
            const response = await fetch(`/api/catch/${encodeURIComponent(videoId)}/comments/${encodeURIComponent(commentId)}/like`, {
                method: 'POST',
            })

            const result = await response.json()
            if (result.ok && result.data) {
                // 更新留言列表中的喜歡狀態和數量
                const updateCommentLikes = (comments: Comment[]): Comment[] => {
                    return comments.map(comment => {
                        if (comment.id === commentId) {
                            return {
                                ...comment,
                                isLiked: result.data.isLiked,
                                likes: result.data.likes,
                            }
                        }
                        if (comment.nestedReplies && comment.nestedReplies.length > 0) {
                            return {
                                ...comment,
                                nestedReplies: updateCommentLikes(comment.nestedReplies),
                            }
                        }
                        return comment
                    })
                }

                setComments(prevComments => updateCommentLikes(prevComments))
            } else {
                console.error('Failed to toggle comment like:', result.message)
                showToast(t('catch.toast.actionFailed'), 'error')
            }
        } catch (error) {
            console.error('Failed to toggle comment like:', error)
            showToast(t('catch.toast.actionFailed'), 'error')
            throw error // 重新拋出錯誤，讓 CommentItem 可以恢復狀態
        }
    }

    // 處理編輯留言功能
    const handleCommentEdit = async (commentId: string, newContent: string) => {
        if (!currentVideo?.id) {
            console.error('Missing video ID')
            return
        }

        const videoId = currentVideo.id // 保存 videoId，避免依賴 currentVideo

        try {
            const response = await fetch(`/api/catch/${encodeURIComponent(videoId)}/comments/${encodeURIComponent(commentId)}`, {
                method: 'PATCH',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({ content: newContent }),
            })

            const result = await response.json()
            if (result.ok) {
                const commentsResponse = await fetch(`/api/catch/${encodeURIComponent(videoId)}/comments`)
                const commentsResult = await commentsResponse.json()
                if (commentsResult.ok && commentsResult.data) {
                    setComments(commentsResult.data)
                }
                showToast(t('catch.toast.commentUpdated'), 'success')
            } else {
                if (result.error === 'UNAUTHORIZED') {
                    showToast(t('catch.toast.loginRequired'), 'error')
                } else if (result.error === 'FORBIDDEN') {
                    showToast(t('catch.toast.noPermissionEdit'), 'error')
                } else if (result.error === 'COMMENT_NOT_FOUND') {
                    showToast(t('catch.toast.commentNotFound'), 'error')
                } else {
                    console.error('Failed to edit comment:', result.message)
                    showToast(t('catch.toast.editFailed'), 'error')
                }
                throw new Error(result.message || 'Failed to edit comment')
            }
        } catch (error) {
            console.error('Failed to edit comment:', error)
            throw error // 重新拋出錯誤，讓 CommentItem 可以保持編輯狀態
        }
    }

    // 處理刪除留言功能
    const handleDelete = async (commentId: string) => {
        if (!currentVideo?.id) {
            console.error('Missing video ID')
            return
        }

        const videoId = currentVideo.id // 保存 videoId，避免依賴 currentVideo

        try {
            const response = await fetch(`/api/catch/${encodeURIComponent(videoId)}/comments?commentId=${encodeURIComponent(commentId)}`, {
                method: 'DELETE',
            })

            const result = await response.json()
            if (result.ok) {
                const commentsResponse = await fetch(`/api/catch/${encodeURIComponent(videoId)}/comments`)
                const commentsResult = await commentsResponse.json()
                if (commentsResult.ok && commentsResult.data) {
                    setComments(commentsResult.data)
                    setCurrentVideoComments(commentsResult.data.length || 0)
                }
            } else {
                if (result.error === 'UNAUTHORIZED') {
                    showToast(t('catch.toast.loginRequired'), 'error')
                } else if (result.error === 'FORBIDDEN') {
                    showToast(t('catch.toast.noPermissionDelete'), 'error')
                } else {
                    console.error('Failed to delete comment:', result.message)
                    showToast(t('catch.toast.deleteFailed'), 'error')
                }
            }
        } catch (error) {
            console.error('Failed to delete comment:', error)
            showToast(t('catch.toast.deleteFailed'), 'error')
        }
    }

    useEffect(() => {
        if (catchVideos.length === 0) return
        if (activeIndex >= loadedCount) {
            setLoadedCount((prev) =>
                Math.min(catchVideos.length, activeIndex + CHUNK_SIZE)
            )
            return
        }

        if (loadedCount < catchVideos.length && activeIndex + 2 >= loadedCount) {
            setLoadedCount((prev) => Math.min(catchVideos.length, prev + CHUNK_SIZE))
        }
    }, [activeIndex, loadedCount, catchVideos.length])

    useEffect(() => {
        const fetchCatchVideos = async () => {
            try {
                const response = await fetch('/api/catch?limit=50')
                const result = await response.json()
                if (result.ok && result.data) {
                    setCatchVideos(result.data)
                    setLoadedCount(Math.min(CHUNK_SIZE, result.data.length))
                    // 初始化 likes 狀態
                    const likesMap: Record<string, number> = {}
                    result.data.forEach((video: CatchVideo) => {
                        likesMap[video.id] = video.likes || 0
                    })
                    setVideoLikes(likesMap)
                }
            } catch (error) {
                console.error('Failed to fetch catch videos:', error)
            }
        }
        fetchCatchVideos()
    }, [])

    // 檢查當前視頻的喜歡狀態
    useEffect(() => {
        if (!currentVideo) return

        // 立即從 videoLikes 或 currentVideo.likes 設置初始值，避免延遲
        const initialLikes = videoLikes[currentVideo.id] ?? currentVideo.likes ?? 0
        setVideoLikes((prev) => ({
            ...prev,
            [currentVideo.id]: initialLikes,
        }))

        // 立即從 currentVideo.comments 設置初始值
        if (currentVideo.comments !== undefined) {
            setCurrentVideoComments(currentVideo.comments)
        }

        // 立即重置 isLiked 為 false，避免顯示上一個視頻的狀態
        setIsLiked(false)

        const checkLikeStatus = async () => {
            try {
                const response = await fetch(`/api/catch/${encodeURIComponent(currentVideo.id)}/like`, { method: 'GET' })
                const result = await response.json()
                if (result.ok && result.data) {
                    const isLikedValue = result.data.isLiked || false
                    setIsLiked(isLikedValue)
                    setVideoIsLiked((prev) => ({
                        ...prev,
                        [currentVideo.id]: isLikedValue,
                    }))
                    // 更新精確的 likes 數
                    if (result.data.likes !== undefined) {
                        setVideoLikes((prev) => ({
                            ...prev,
                            [currentVideo.id]: result.data.likes,
                        }))
                    }
                }
            } catch (error) {
                // 如果 GET 方法不存在，忽略錯誤（使用默認值）
            }
        }
        checkLikeStatus()
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [currentVideo?.id])

    // 處理喜歡按鈕點擊
    const handleLikeClick = async (videoId: string) => {
        const video = catchVideos.find((v) => v.id === videoId)
        if (!video) return

        const prevIsLiked = videoIsLiked[videoId] ?? false
        const prevLikes = videoLikes[videoId] ?? video.likes ?? 0

        // 樂觀更新
        const newIsLiked = !prevIsLiked
        setVideoIsLiked((prev) => ({
            ...prev,
            [videoId]: newIsLiked,
        }))
        setVideoLikes((prev) => ({
            ...prev,
            [videoId]: prevIsLiked ? Math.max(0, prevLikes - 1) : prevLikes + 1,
        }))

        // 如果是當前視頻，也更新 isLiked
        if (videoId === currentVideo?.id) {
            setIsLiked(newIsLiked)
        }

        try {
            const response = await fetch(`/api/catch/${encodeURIComponent(videoId)}/like`, { method: 'POST' })
            const result = await response.json()
            if (result.ok && result.data) {
                const newLikes = result.data.likes ?? 0
                const newIsLikedValue = result.data.isLiked || false
                setVideoIsLiked((prev) => ({
                    ...prev,
                    [videoId]: newIsLikedValue,
                }))
                setVideoLikes((prev) => ({
                    ...prev,
                    [videoId]: newLikes,
                }))
                // 如果是當前視頻，也更新 isLiked
                if (videoId === currentVideo?.id) {
                    setIsLiked(newIsLikedValue)
                }
            } else {
                // 如果 API 失敗，恢復原狀態
                setVideoIsLiked((prev) => ({
                    ...prev,
                    [videoId]: prevIsLiked,
                }))
                setVideoLikes((prev) => ({
                    ...prev,
                    [videoId]: prevLikes,
                }))
                if (videoId === currentVideo?.id) {
                    setIsLiked(prevIsLiked)
                }
            }
        } catch (error) {
            console.error('Failed to toggle like:', error)
            // 恢復原狀態
            setVideoIsLiked((prev) => ({
                ...prev,
                [videoId]: prevIsLiked,
            }))
            setVideoLikes((prev) => ({
                ...prev,
                [videoId]: prevLikes,
            }))
            if (videoId === currentVideo?.id) {
                setIsLiked(prevIsLiked)
            }
        }
    }

    useEffect(() => {
        const videoId = params.id as string
        if (!videoId || catchVideos.length === 0) return
        setIsLoading(true)
        setVideoById(videoId)
        setIsPlaying(true)
        // 模擬載入延遲
        const timer = setTimeout(() => {
            setIsLoading(false)
        }, 800)
        return () => clearTimeout(timer)
    }, [params.id, catchVideos, setVideoById])

    useEffect(() => {
        if (currentVideo && !isLoading) {
            setIsPlaying(true)
        }
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [activeIndex, currentVideo?.id, isLoading])

    const updateCurrentIndex = useCallback(() => {
        if (isProgrammaticScrollRef.current || catchVideos.length === 0) return

        const feed = window.innerWidth < 768 ? feedRef.current : desktopFeedRef.current
        const itemRefs = window.innerWidth < 768 ? videoItemRefs : desktopVideoItemRefs

        if (!feed) return

        let nearest = currentIndexRef.current
        let minDist = Infinity

        itemRefs.current.forEach((item, i) => {
            if (!item) return
            const rect = item.getBoundingClientRect()
            const feedRect = feed.getBoundingClientRect()
            const itemCenter = rect.top + rect.height / 2
            const feedCenter = feedRect.top + feedRect.height / 2
            const dist = Math.abs(itemCenter - feedCenter)

            if (rect.top < feedRect.bottom && rect.bottom > feedRect.top && dist < minDist) {
                minDist = dist
                nearest = i
            }
        })

        if (nearest !== currentIndexRef.current && nearest >= 0 && nearest < catchVideos.length) {
            currentIndexRef.current = nearest
            setActiveIndex(nearest)
        }
    }, [catchVideos.length])

    const smoothScrollTo = useCallback((container: HTMLElement, targetY: number, duration = 420) => {
        const startY = container.scrollTop
        const diff = targetY - startY
        const startTime = performance.now()

        // 緩動函數：easeOutCubic（提供自然的減速效果）
        const easeOutCubic = (t: number) => 1 - Math.pow(1 - t, 3)

        const step = () => {
            const now = performance.now()
            const progress = Math.min((now - startTime) / duration, 1)
            const eased = easeOutCubic(progress)

            container.scrollTop = startY + diff * eased

            if (progress < 1) {
                requestAnimationFrame(step)
            }
        }

        requestAnimationFrame(step)
    }, [])

    const scrollToIndex = useCallback((targetIndex: number) => {
        if (targetIndex < 0 || targetIndex >= catchVideos.length || catchVideos.length === 0) return

        const feed = window.innerWidth < 768 ? feedRef.current : desktopFeedRef.current
        const itemRefs = window.innerWidth < 768 ? videoItemRefs : desktopVideoItemRefs

        if (!feed) return

        const targetItem = itemRefs.current[targetIndex]
        if (!targetItem) return

        isProgrammaticScrollRef.current = true
        scrollLockRef.current = true
        currentIndexRef.current = targetIndex
        setActiveIndex(targetIndex)

        const previousSnap = feed.style.scrollSnapType
        feed.style.scrollSnapType = 'none'

        const savedScrollTop = feed.scrollTop
        feed.style.scrollSnapType = 'y mandatory'
        targetItem.scrollIntoView({ behavior: 'auto', block: 'start' })
        const targetOffset = feed.scrollTop

        feed.scrollTop = savedScrollTop
        feed.style.scrollSnapType = 'none'

        smoothScrollTo(feed, targetOffset, 420)

        setTimeout(() => {
            feed.style.scrollSnapType = previousSnap || 'y mandatory'
            scrollLockRef.current = false
            isProgrammaticScrollRef.current = false
        }, 450)
    }, [smoothScrollTo, catchVideos.length])

    useEffect(() => {
        const keyThrottleMs = 1000
        const handleKeyDown = (e: KeyboardEvent) => {
            if (isLoading || !currentVideo || catchVideos.length === 0) return
            const now = performance.now()
            if (now - lastKeySwitchRef.current < keyThrottleMs) return
            const target = e.target as HTMLElement
            if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable) return

            let targetIndex = currentIndexRef.current
            if (e.key === 'ArrowDown') {
                targetIndex += 1
            } else if (e.key === 'ArrowUp') {
                targetIndex -= 1
            } else {
                return
            }

            if (targetIndex < 0 || targetIndex >= catchVideos.length) return
            lastKeySwitchRef.current = now
            e.preventDefault()
            scrollToIndex(targetIndex)
        }

        window.addEventListener('keydown', handleKeyDown)
        return () => {
            window.removeEventListener('keydown', handleKeyDown)
        }
    }, [isLoading, currentVideo, scrollToIndex, catchVideos.length])

    useEffect(() => {
        if (isLoading || !currentVideo || catchVideos.length === 0) return

        const feed = window.innerWidth < 768 ? feedRef.current : desktopFeedRef.current
        if (!feed) return

        const wheelThrottleMs = 800

        const handleWheel = (e: WheelEvent) => {
            if (isProgrammaticScrollRef.current || wheelLockRef.current) {
                e.preventDefault()
                e.stopPropagation()
                return
            }

            const target = e.target as HTMLElement
            if (
                target.tagName === 'INPUT' ||
                target.tagName === 'TEXTAREA' ||
                target.isContentEditable ||
                target.closest('[role="dialog"]') ||
                target.closest('.overflow-y-auto') !== feed
            ) {
                return
            }

            const isInFeed = feed.contains(target) || feed.isSameNode(target)
            if (!isInFeed) {
                return
            }

            const feedRect = feed.getBoundingClientRect()
            const mouseY = e.clientY
            if (mouseY < feedRect.top || mouseY > feedRect.bottom) {
                return
            }

            const now = performance.now()
            if (now - lastWheelTimeRef.current < wheelThrottleMs) {
                e.preventDefault()
                e.stopPropagation()
                return
            }

            const deltaY = e.deltaY
            if (Math.abs(deltaY) < 10) {
                return
            }

            e.preventDefault()
            e.stopPropagation()

            let targetIndex = currentIndexRef.current

            if (deltaY > 0) {
                targetIndex += 1
            } else if (deltaY < 0) {
                targetIndex -= 1
            } else {
                return
            }

            if (targetIndex < 0 || targetIndex >= catchVideos.length) {
                return
            }

            lastWheelTimeRef.current = now
            wheelLockRef.current = true
            scrollToIndex(targetIndex)

            setTimeout(() => {
                wheelLockRef.current = false
            }, 500)
        }

        feed.addEventListener('wheel', handleWheel, { passive: false })

        return () => {
            feed.removeEventListener('wheel', handleWheel)
        }
    }, [isLoading, currentVideo, scrollToIndex, catchVideos.length])

    useEffect(() => {
        const feed = window.innerWidth < 768 ? feedRef.current : desktopFeedRef.current
        const itemRefs = window.innerWidth < 768 ? videoItemRefs : desktopVideoItemRefs

        if (!feed || !currentVideo || catchVideos.length === 0) return

        const observer = new IntersectionObserver(
            (entries) => {
                if (isProgrammaticScrollRef.current) return

                let maxVisibleRatio = 0
                let mostVisibleIndex = currentIndexRef.current

                entries.forEach((entry) => {
                    const targetElement = entry.target as HTMLElement
                    const index = itemRefs.current.findIndex((ref) => ref === targetElement)

                    if (index >= 0 && entry.intersectionRatio > maxVisibleRatio) {
                        maxVisibleRatio = entry.intersectionRatio
                        mostVisibleIndex = index
                    }
                })

                if (mostVisibleIndex !== currentIndexRef.current && mostVisibleIndex >= 0 && mostVisibleIndex < catchVideos.length) {
                    currentIndexRef.current = mostVisibleIndex
                    setActiveIndex(mostVisibleIndex)
                }
            },
            {
                root: feed,
                rootMargin: '-20% 0px -20% 0px',
                threshold: [0, 0.5, 1],
            }
        )

        itemRefs.current.forEach((item) => {
            if (item) {
                observer.observe(item)
            }
        })

        let scrollTimeout: NodeJS.Timeout | null = null
        const handleScroll = () => {
            if (isProgrammaticScrollRef.current) return

            if (scrollTimeout) {
                clearTimeout(scrollTimeout)
            }

            scrollTimeout = setTimeout(() => {
                if (isProgrammaticScrollRef.current) return
                updateCurrentIndex()
            }, 100)
        }

        feed.addEventListener('scroll', handleScroll, { passive: true })

        return () => {
            observer.disconnect()
            feed.removeEventListener('scroll', handleScroll)
            if (scrollTimeout) {
                clearTimeout(scrollTimeout)
            }
        }
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [currentVideo?.id, updateCurrentIndex, catchVideos.length])

    // 只有在載入完成且真的沒有資料時才顯示"沒有資料"
    if (!isLoading && !currentVideo) {
        return (
            <>
                <Header onMenuClick={() => setSidebarOpen(!sidebarOpen)} />
                <div className="relative min-h-screen min-w-[380px] bg-white dark:bg-[#0c0d0e] flex overflow-x-hidden transition-colors">
                    <Sidebar isOpen={sidebarOpen} onClose={() => setSidebarOpen(false)} />
                    <main className="main-content flex-1 lg:ml-64 pt-[6rem] md:pt-[6rem] min-h-screen w-full max-w-full overflow-x-hidden transition-all">
                        <div className="w-full max-w-7xl mx-auto px-5 py-5">
                            <div className="text-center text-gray-600 dark:text-gray-400">
                                {t('explore.noData')}
                            </div>
                        </div>
                    </main>
                </div>
            </>
        )
    }

    // 載入中時顯示骨架
    if (isLoading || !currentVideo) {
        return (
            <>
                <Header onMenuClick={() => setSidebarOpen(!sidebarOpen)} />
                <div className="relative min-h-screen min-w-[380px] bg-white dark:bg-[#0c0d0e] flex overflow-x-hidden transition-colors">
                    <Sidebar isOpen={sidebarOpen} onClose={() => setSidebarOpen(false)} />
                    <main
                        className="flex-1 pt-0 md:pt-[65px] min-h-screen max-w-full overflow-x-hidden transition-all md:ml-10"
                        data-compact-open={sidebarOpen ? 'true' : 'false'}
                    >
                        {/* 手機模式：YouTube Shorts 風格 */}
                        <div
                            className="md:hidden absolute top-[65px] bottom-0 left-0 right-0 overflow-y-auto hide-scrollbar w-full"
                            style={{
                                scrollSnapType: 'y mandatory',
                                scrollBehavior: 'smooth',
                            }}
                        >
                            <MobileVideoPlayerSkeleton />
                        </div>

                        {/* 桌面模式：垂直短視頻風格布局 */}
                        <div className="hidden md:flex items-center w-full h-[calc(100vh-80px)] py-1 px-3 md:px-4 lg:px-6">
                            <div className="flex items-center h-full w-full justify-center gap-3 md:gap-4 lg:gap-6">
                                <div className="flex items-center flex-shrink-0 gap-3 md:gap-4 lg:gap-6 h-full">
                                    <div className="flex justify-center h-full flex-shrink-0 relative w-[280px] sm:w-[320px] md:w-[380px] lg:w-[450px] xl:w-[500px]">
                                        <div className="w-full h-full overflow-y-auto hide-scrollbar">
                                            <DesktopVideoPlayerSkeleton />
                                        </div>
                                    </div>

                                    {/* 右側互動按鈕骨架 */}
                                    <div className="flex flex-col items-center gap-3 md:gap-4 lg:gap-6 flex-shrink-0" style={{ width: '60px', minWidth: '60px' }}>
                                        <DesktopInteractionButtonsSkeleton />
                                    </div>

                                    {/* 最右側切換箭頭骨架 */}
                                    <div className="flex flex-col gap-3 md:gap-4 lg:gap-6 flex-shrink-0 items-center" style={{ width: '50px', minWidth: '50px' }}>
                                        <Skeleton variant="circular" width={44} height={44} animation="shimmer" />
                                        <Skeleton variant="circular" width={44} height={44} animation="shimmer" />
                                    </div>
                                </div>
                            </div>
                        </div>
                    </main>
                </div>
            </>
        )
    }

    const formatDate = (dateStr: string) => {
        return dateStr
    }

    return (
        <>
            <Header onMenuClick={() => setSidebarOpen(!sidebarOpen)} />
            <div className="relative min-h-screen min-w-[380px] bg-white dark:bg-[#0c0d0e] flex overflow-x-hidden transition-colors">
                <Sidebar isOpen={sidebarOpen} onClose={() => setSidebarOpen(false)} />
                <main
                    className="flex-1 pt-0 md:pt-[65px] min-h-screen max-w-full overflow-x-hidden transition-all md:ml-10"
                    data-compact-open={sidebarOpen ? 'true' : 'false'}
                >
                    {/* 手機模式：YouTube Shorts 風格 */}
                    <div
                        ref={feedRef}
                        className="md:hidden absolute top-[65px] bottom-0 left-0 right-0 overflow-y-auto hide-scrollbar w-full"
                        style={{
                            scrollSnapType: 'y mandatory',
                            scrollBehavior: 'smooth',
                        }}
                    >
                        {isLoading || !currentVideo ? (
                            <MobileVideoPlayerSkeleton />
                        ) : (
                            (() => {
                                const minRenderIndex = Math.max(0, activeIndex - 2)
                                const maxRenderIndex = Math.min(loadedCount - 1, activeIndex + 1)
                                const renderVideos = catchVideos.slice(0, loadedCount)
                                return renderVideos.map((video, index) => {
                                    const isVisible = index >= minRenderIndex && index <= maxRenderIndex
                                    const isCurrent = index === activeIndex
                                    return (
                                        <div
                                            ref={(el) => {
                                                videoItemRefs.current[index] = el
                                            }}
                                            data-video-index={index}
                                            key={video.id}
                                            style={{
                                                visibility: isVisible ? 'visible' : 'hidden',
                                                pointerEvents: isVisible ? 'auto' : 'none',
                                                height: 'calc(100vh - 65px)',
                                            }}
                                        >
                                            <MobileVideoPlayer
                                                video={video}
                                                isCurrent={isCurrent}
                                                isPlaying={isPlaying}
                                                volume={volume}
                                                isMuted={isMuted}
                                                showVolume={showVolume}
                                                onPlayToggle={() => setIsPlaying(!isPlaying)}
                                                onMuteToggle={() => setIsMuted(!isMuted)}
                                                onVolumeChange={(v) => {
                                                    setVolume(v)
                                                    if (v === 0) {
                                                        setIsMuted(true)
                                                    } else {
                                                        setIsMuted(false)
                                                    }
                                                }}
                                                onShowVolume={setShowVolume}
                                                onCommentsClick={() => setCommentsOpen(true)}
                                                formatViews={formatViews}
                                                isLiked={isLiked}
                                                onLikeClick={() => currentVideo && handleLikeClick(currentVideo.id)}
                                                videoUrl={typeof window !== 'undefined' ? window.location.href : ''}
                                                videoTitle={video.title}
                                                isCommentsOpen={commentsOpen}
                                            />
                                        </div>
                                    )
                                })
                            })()
                        )}
                    </div>

                    {/* 桌面模式：垂直短視頻風格布局（中央視頻，右側資訊和按鈕，最右側切換箭頭） */}
                    <div className="hidden md:flex items-center w-full h-[calc(100vh-80px)] py-1 px-3 md:px-4 lg:px-6">
                        <div className="flex items-center h-full w-full justify-center gap-3 md:gap-4 lg:gap-6">
                            <div className="flex items-center flex-shrink-0 gap-3 md:gap-4 lg:gap-6 h-full">
                                <div className="flex justify-center h-full flex-shrink-0 relative w-[280px] sm:w-[320px] md:w-[380px] lg:w-[450px] xl:w-[500px]">
                                    <div
                                        ref={desktopFeedRef}
                                        className="w-full h-full overflow-y-auto hide-scrollbar"
                                        style={{
                                            scrollSnapType: 'y mandatory',
                                            scrollBehavior: 'smooth',
                                        }}
                                    >
                                        {isLoading || !currentVideo ? (
                                            <DesktopVideoPlayerSkeleton />
                                        ) : (
                                            catchVideos.map((video, index) => {
                                                const isCurrent = video.id === currentVideo.id
                                                return (
                                                    <div
                                                        ref={(el) => {
                                                            desktopVideoItemRefs.current[index] = el
                                                        }}
                                                        data-desktop-video-index={index}
                                                        key={video.id}
                                                        className="mt-3 first:mt-0 relative w-full"
                                                        style={{
                                                            height: 'calc(100vh - 6.5rem)',
                                                            minHeight: 'calc(100vh - 6.5rem)',
                                                        }}
                                                    >
                                                        <DesktopVideoPlayer
                                                            video={video}
                                                            isCurrent={isCurrent}
                                                            isPlaying={isPlaying}
                                                            volume={volume}
                                                            isMuted={isMuted}
                                                            onPlayToggle={() => setIsPlaying(!isPlaying)}
                                                            onMuteToggle={() => setIsMuted(!isMuted)}
                                                            onVolumeChange={(v) => {
                                                                setVolume(v)
                                                                if (v === 0) {
                                                                    setIsMuted(true)
                                                                } else {
                                                                    setIsMuted(false)
                                                                }
                                                            }}
                                                            formatViews={formatViews}
                                                        />
                                                    </div>
                                                )
                                            })
                                        )}
                                    </div>
                                </div>

                                {/* 右側互動按鈕 - 影片播放器右邊 */}
                                {isLoading || !currentVideo ? (
                                    <div className="flex flex-col items-center gap-3 md:gap-4 lg:gap-6 flex-shrink-0" style={{ width: '60px', minWidth: '60px' }}>
                                        <DesktopInteractionButtonsSkeleton />
                                    </div>
                                ) : (
                                    <div className="flex flex-col items-center gap-3 md:gap-4 lg:gap-6 flex-shrink-0" style={{ width: '60px', minWidth: '60px' }}>
                                        <DesktopInteractionButtons
                                            likes={(videoLikes[currentVideo.id] ?? currentVideo.likes) || 0}
                                            comments={videoComments[currentVideo.id] ?? currentVideoComments}
                                            formatViews={formatViews}
                                            onCommentsClick={() => setDesktopCommentsOpen(!desktopCommentsOpen)}
                                            isCommentsOpen={desktopCommentsOpen}
                                            isLiked={videoIsLiked[currentVideo.id] ?? isLiked}
                                            onLikeClick={() => currentVideo && handleLikeClick(currentVideo.id)}
                                            videoUrl={typeof window !== 'undefined' ? window.location.href : ''}
                                            videoTitle={currentVideo.title}
                                        />
                                    </div>
                                )}

                                {/* 最右側切換箭頭 */}
                                {isLoading || !currentVideo ? (
                                    <div className="flex flex-col gap-3 md:gap-4 lg:gap-6 flex-shrink-0 items-center" style={{ width: '50px', minWidth: '50px' }}>
                                        <Skeleton variant="circular" width={44} height={44} animation="shimmer" />
                                        <Skeleton variant="circular" width={44} height={44} animation="shimmer" />
                                    </div>
                                ) : (
                                    <div className="flex flex-col gap-3 md:gap-4 lg:gap-6 flex-shrink-0 items-center" style={{ width: '50px', minWidth: '50px' }}>
                                        {(() => {
                                            const currentIndex = catchVideos.findIndex((v) => v.id === currentVideo.id)
                                            const hasPrevious = currentIndex > 0
                                            const hasNext = currentIndex < catchVideos.length - 1
                                            return (
                                                <>
                                                    {hasPrevious && (
                                                        <button
                                                            onClick={() => scrollToIndex(currentIndex - 1)}
                                                            className="w-10 h-10 md:w-11 md:h-11 flex items-center justify-center bg-black/60 dark:bg-white/20 backdrop-blur-sm rounded-full text-white dark:text-gray-100 hover:bg-black/80 dark:hover:bg-white/30 transition-all shadow-lg hover:scale-110"
                                                            aria-label={t('catch.player.prevVideo')}
                                                        >
                                                            <FaArrowUp className="w-5 h-5" />
                                                        </button>
                                                    )}
                                                    {hasNext && (
                                                        <button
                                                            onClick={() => scrollToIndex(currentIndex + 1)}
                                                            className="w-10 h-10 md:w-11 md:h-11 flex items-center justify-center bg-black/60 dark:bg-white/20 backdrop-blur-sm rounded-full text-white dark:text-gray-100 hover:bg-black/80 dark:hover:bg-white/30 transition-all shadow-lg hover:scale-110"
                                                            aria-label={t('catch.player.nextVideo')}
                                                        >
                                                            <FaArrowDown className="w-5 h-5" />
                                                        </button>
                                                    )}
                                                </>
                                            )
                                        })()}
                                    </div>
                                )}
                            </div>

                        </div>
                    </div>

                </main>
                <BackToTop />

                {/* 評論面板（僅手機模式） - 掛在頁面容器內，跟著水平捲動內容，不再以 viewport 計算造成擠壓 */}
                <CommentsPanel
                    isOpen={commentsOpen}
                    onClose={() => setCommentsOpen(false)}
                    comments={comments}
                    commentCount={currentVideoComments}
                    onReply={handleReply}
                    onCreateComment={handleCreateComment}
                    onDelete={handleDelete}
                    onEdit={handleCommentEdit}
                    onPin={handlePin}
                    onLike={handleCommentLike}
                    userAvatar={userAvatar}
                    isLoggedIn={!!currentUserId}
                    currentUserId={currentUserId}
                    videoOwnerId={videoOwnerId}
                    usePortal={false}
                />

                {/* 桌面留言區 Popup（掛在頁面容器內，跟著水平捲動內容） */}
                {desktopCommentsOpen && !isLoading && currentVideo && (
                    <>
                        <div
                            className={`absolute inset-0 bg-black/50 z-[9999] ${isCommentsClosing ? 'opacity-0 transition-opacity duration-200' : 'opacity-100 transition-opacity duration-200'}`}
                            onClick={handleCloseComments}
                        />

                        <div
                            className={`absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 w-[90%] max-w-[500px] h-[80vh] max-h-[800px] bg-white dark:bg-[#0c0d0e] rounded-xl shadow-xl z-[10000] flex flex-col ${isCommentsClosing ? 'scale-95 opacity-0 transition-all duration-200' : 'scale-100 opacity-100 transition-all duration-200'}`}
                        >
                            <div className="flex items-center justify-between px-4 md:px-5 pt-4 md:pt-5 pb-3 border-b border-gray-200 dark:border-gray-800 flex-shrink-0">
                                <div className="flex items-center gap-2">
                                    <h2 className="text-base md:text-lg font-semibold text-black dark:text-white">
                                        {t('catch.comments')}
                                    </h2>
                                    <span
                                        role="text"
                                        aria-label={t('catch.a11y.commentCount')}
                                        className="text-xs md:text-sm text-gray-500 dark:text-gray-400 font-medium">
                                        {currentVideoComments.toLocaleString()}
                                    </span>
                                </div>
                                <button
                                    onClick={handleCloseComments}
                                    className="p-2 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-full transition-colors"
                                    aria-label={t('catch.a11y.closeComments')}
                                >
                                    <FiX className="w-5 h-5 text-gray-600 dark:text-gray-400" />
                                </button>
                            </div>

                            <div className="flex-1 overflow-y-auto hide-scrollbar p-4 min-h-0">
                                {commentsLoading ? (
                                    <CommentsListSkeleton />
                                ) : (
                                    <div className="space-y-3 md:space-y-4">
                                        {comments.length > 0 ? (
                                            comments.map((comment) => (
                                                <CommentItem
                                                    key={comment.id}
                                                    comment={comment}
                                                    onReply={handleReply}
                                                    onDelete={handleDelete}
                                                    onEdit={handleCommentEdit}
                                                    onPin={handlePin}
                                                    onLike={handleCommentLike}
                                                    userAvatar={userAvatar}
                                                    isLoggedIn={!!currentUserId}
                                                    currentUserId={currentUserId}
                                                    videoOwnerId={videoOwnerId}
                                                />
                                            ))
                                        ) : (
                                            <div className="flex items-center justify-center py-8 text-gray-400 dark:text-gray-500 text-sm">
                                                {t('catch.commentsEmpty')}
                                            </div>
                                        )}
                                    </div>
                                )}
                            </div>

                            {!commentsLoading && (
                                <div className="flex-shrink-0 px-6 pt-4 pb-6 border-t border-gray-200 dark:border-gray-800 bg-white dark:bg-[#0c0d0e] rounded-b-xl">
                                    <CommentInput
                                        onSubmit={handleCreateComment}
                                        userAvatar={userAvatar}
                                        isLoggedIn={!!currentUserId}
                                    />
                                </div>
                            )}
                        </div>
                    </>
                )}
            </div>
        </>
    )
}
