"use client";
import { useEffect, useMemo, useRef, useState } from "react";
import { useRouter } from "next/navigation";
import {
  ChevronLeft,
  ChevronRight,
  Pause,
  Play,
  Volume2,
  VolumeX,
  Maximize,
  Minimize2,
  MessageSquare,
  ThumbsUp,
  MessageSquareText,
  RotateCcw,
  RotateCw,
  Maximize2,
  Minimize,
  ChevronUp,
  ChevronDown,
  X,
  Repeat,
  Repeat1,
  ArrowDownUp,
  Download,
} from "lucide-react";

type User = { nickname: string; avatar_url: string | null };
type Comment = { cid: string; text: string; digg_count: number; created_at: string | Date; user: User };

// 格式化相对时间
function formatRelativeTime(date: string | Date): string {
  const now = new Date();
  const target = new Date(date);
  const diffMs = now.getTime() - target.getTime();
  const diffSeconds = Math.floor(diffMs / 1000);
  const diffMinutes = Math.floor(diffSeconds / 60);
  const diffHours = Math.floor(diffMinutes / 60);
  const diffDays = Math.floor(diffHours / 24);
  const diffMonths = Math.floor(diffDays / 30);
  const diffYears = Math.floor(diffDays / 365);

  if (diffYears > 0) return `${diffYears}年前`;
  if (diffMonths > 0) return `${diffMonths}月前`;
  if (diffDays > 0) return `${diffDays}天前`;
  if (diffHours > 0) return `${diffHours}小时前`;
  if (diffMinutes > 0) return `${diffMinutes}分钟前`;
  return '刚刚';
}

// 处理评论文本中的表情占位符
function parseCommentText(text: string): (string | { type: "emoji"; name: string })[] {
  const parts: (string | { type: "emoji"; name: string })[] = [];
  const regex = /\[([^\]]+)\]/g;
  let lastIndex = 0;
  let match: RegExpExecArray | null;

  while ((match = regex.exec(text)) !== null) {
    // 添加表情前的文本
    if (match.index > lastIndex) {
      parts.push(text.slice(lastIndex, match.index));
    }
    // 添加表情
    parts.push({ type: "emoji", name: match[1] });
    lastIndex = regex.lastIndex;
  }

  // 添加剩余文本
  if (lastIndex < text.length) {
    parts.push(text.slice(lastIndex));
  }

  return parts;
}

// 渲染评论文本（包含表情）
function CommentText({ text }: { text: string }) {
  const parts = parseCommentText(text);

  return (
    <>
      {parts.map((part, idx) => {
        if (typeof part === "string") {
          return <span key={idx}>{part}</span>;
        }
        return (
          <img
            key={idx}
            src={`/emojis/${part.name}.webp`}
            alt={part.name}
            className="inline-block w-5 h-5 align-text-bottom mx-0.5"
            onError={(e) => {
              // 如果图片加载失败，显示原始文本
              e.currentTarget.style.display = "none";
              const textNode = document.createTextNode(`[${part.name}]`);
              e.currentTarget.parentNode?.insertBefore(textNode, e.currentTarget);
            }}
          />
        );
      })}
    </>
  );
}

type VideoData = {
  type: "video";
  aweme_id: string;
  desc: string;
  created_at: string | Date;
  duration_ms?: number | null;
  video_url: string;
  width?: number | null;
  height?: number | null;
  author: User;
  comments: Comment[];
};

type ImageData = {
  type: "image";
  aweme_id: string;
  desc: string;
  created_at: string | Date;
  images: { id: string; url: string; width?: number; height?: number }[];
  music_url?: string | null;
  author: User;
  comments: Comment[];
};

const SEGMENT_MS = 5000; // 图文每段 5s

type Neighbors = { prev: { aweme_id: string } | null; next: { aweme_id: string } | null };

export default function AwemeDetailClient(props: { data: VideoData | ImageData; neighbors?: Neighbors }) {
  const { data, neighbors } = props;
  const isVideo = data.type === "video";
  const router = useRouter();

  // ====== 布局 & 评论 ======
  const [open, setOpen] = useState(false); // 评论是否展开（竖屏为 bottom sheet；横屏为并排分栏）
  const [mounted, setMounted] = useState(false); // 用于跳过首次加载的动画
  const comments = useMemo(() => data.comments ?? [], [data]);

  // ====== 从 localStorage 恢复评论区状态（仅客户端） ======
  useEffect(() => {
    if (typeof window === "undefined") return;
    const saved = localStorage.getItem("aweme_player_comments_open");
    if (saved === "true") {
      setOpen(true);
    }
    // 短暂延迟后标记为已挂载，启用动画
    requestAnimationFrame(() => {
      requestAnimationFrame(() => {
        setMounted(true);
      });
    });
  }, []);

  // ====== 媒体引用 ======
  const mediaContainerRef = useRef<HTMLDivElement | null>(null);
  const videoRef = useRef<HTMLVideoElement | null>(null);
  const audioRef = useRef<HTMLAudioElement | null>(null);
  const wheelCooldownRef = useRef<number>(0);
  const backgroundCanvasRef = useRef<HTMLCanvasElement | null>(null);

  // ====== 统一控制状态 ======
  const [isPlaying, setIsPlaying] = useState(true); // 视频=播放；图文=是否自动切换
  const [isFullscreen, setIsFullscreen] = useState(false);
  const [volume, setVolume] = useState(() => {
    // 从 localStorage 读取音量，默认 1
    if (typeof window === "undefined") return 1;
    const saved = localStorage.getItem("aweme_player_volume");
    if (!saved) return 1;
    const parsed = parseFloat(saved);
    return Number.isNaN(parsed) ? 1 : Math.max(0, Math.min(1, parsed));
  });
  const [rate, setRate] = useState(() => {
    // 从 localStorage 读取倍速，默认 1
    if (typeof window === "undefined") return 1;
    const saved = localStorage.getItem("aweme_player_rate");
    if (!saved) return 1;
    const parsed = parseFloat(saved);
    return Number.isNaN(parsed) ? 1 : parsed;
  });
  const [progress, setProgress] = useState(0); // 0..1 总进度
  const [rotation, setRotation] = useState(0); // 视频旋转角度：0/90/180/270
  const [progressRestored, setProgressRestored] = useState(false); // 标记进度是否已恢复
  const [objectFit, setObjectFit] = useState<"contain" | "cover">("contain"); // 媒体显示模式
  const [loopMode, setLoopMode] = useState<"loop" | "sequential">(() => {
    // 从 localStorage 读取循环模式，默认 loop
    if (typeof window === "undefined") return "loop";
    const saved = localStorage.getItem("aweme_player_loop_mode");
    if (!saved) return "loop";
    return saved === "sequential" ? "sequential" : "loop";
  });

  // ====== 图文专用（分段） ======
  const images = (data as any).images as ImageData["images"] | undefined;
  const totalSegments = images?.length ?? 0;
  const [idx, setIdx] = useState(0); // 当前图片索引
  const scrollerRef = useRef<HTMLDivElement | null>(null);

  // 用 ref 解决“闪回”
  const segStartRef = useRef<number | null>(null);   // 当前段开始时间戳
  const idxRef = useRef<number>(0);
  const rafRef = useRef<number | null>(null);
  const [segProgress, setSegProgress] = useState(0); // 段内 0..1
  const [, forceUpdate] = useState(0); // 用于强制更新时间显示

  useEffect(() => { idxRef.current = idx; }, [idx]);

  // ====== 持久化音量到 localStorage ======
  useEffect(() => {
    if (typeof window === "undefined") return;
    localStorage.setItem("aweme_player_volume", volume.toString());
  }, [volume]);

  // ====== 持久化倍速到 localStorage ======
  useEffect(() => {
    if (typeof window === "undefined") return;
    localStorage.setItem("aweme_player_rate", rate.toString());
  }, [rate]);

  // ====== 持久化评论区状态到 localStorage ======
  useEffect(() => {
    if (typeof window === "undefined") return;
    localStorage.setItem("aweme_player_comments_open", open.toString());
  }, [open]);

  // ====== 持久化循环模式到 localStorage ======
  useEffect(() => {
    if (typeof window === "undefined") return;
    localStorage.setItem("aweme_player_loop_mode", loopMode);
  }, [loopMode]);

  // ====== 恢复视频播放进度（带有效期） ======
  useEffect(() => {
    if (!isVideo || progressRestored) return;
    const v = videoRef.current;
    if (!v) return;

    const onLoadedMetadata = () => {
      if (progressRestored) return;

      try {
        const key = `aweme_progress_${data.aweme_id}`;
        const saved = localStorage.getItem(key);
        if (!saved) {
          setProgressRestored(true);
          return;
        }

        const { time, timestamp } = JSON.parse(saved);
        const now = Date.now();
        const fiveMinutes = 5 * 60 * 1000;

        // 检查是否在 5 分钟有效期内
        if (now - timestamp < fiveMinutes && time > 1 && time < v.duration - 1) {
          v.currentTime = time;
          console.log(`恢复播放进度: ${Math.round(time)}s`);
        } else if (now - timestamp >= fiveMinutes) {
          // 过期则清除
          localStorage.removeItem(key);
        }
      } catch (e) {
        console.error("恢复播放进度失败", e);
      }

      setProgressRestored(true);
    };

    if (v.readyState >= 1) {
      // 元数据已加载
      onLoadedMetadata();
    } else {
      v.addEventListener("loadedmetadata", onLoadedMetadata, { once: true });
      return () => v.removeEventListener("loadedmetadata", onLoadedMetadata);
    }
  }, [isVideo, data.aweme_id, progressRestored]);

  // ====== 实时保存视频播放进度到 localStorage ======
  useEffect(() => {
    if (!isVideo) return;
    const v = videoRef.current;
    if (!v) return;

    const saveProgress = () => {
      if (!v.duration || Number.isNaN(v.duration) || v.currentTime < 1) return;

      try {
        const key = `aweme_progress_${data.aweme_id}`;
        const value = JSON.stringify({
          time: v.currentTime,
          timestamp: Date.now(),
        });
        localStorage.setItem(key, value);
      } catch (e) {
        console.error("保存播放进度失败", e);
      }
    };

    // 每 2 秒保存一次进度
    const interval = setInterval(saveProgress, 2000);

    // 页面卸载时也保存一次
    const onBeforeUnload = () => saveProgress();
    window.addEventListener("beforeunload", onBeforeUnload);

    return () => {
      clearInterval(interval);
      window.removeEventListener("beforeunload", onBeforeUnload);
      saveProgress(); // 组件卸载时保存
    };
  }, [isVideo, data.aweme_id]);

  // ====== 视频：进度/播放/倍速/音量 ======
  useEffect(() => {
    if (!isVideo) return;
    const v = videoRef.current;
    if (!v) return;

    const onTime = () => {
      if (!v.duration || Number.isNaN(v.duration)) return;
      setProgress(v.currentTime / v.duration);
    };
    const onPlay = () => setIsPlaying(true);
    const onPause = () => setIsPlaying(false);
    const onEnded = () => {
      // 顺序播放模式下，视频结束时自动跳转到下一条
      if (loopMode === "sequential" && neighbors?.next) {
        router.push(`/aweme/${neighbors.next.aweme_id}`);
      }
    };

    v.addEventListener("timeupdate", onTime);
    v.addEventListener("loadedmetadata", onTime);
    v.addEventListener("play", onPlay);
    v.addEventListener("pause", onPause);
    v.addEventListener("ended", onEnded);
    return () => {
      v.removeEventListener("timeupdate", onTime);
      v.removeEventListener("loadedmetadata", onTime);
      v.removeEventListener("play", onPlay);
      v.removeEventListener("pause", onPause);
      v.removeEventListener("ended", onEnded);
    };
  }, [isVideo, loopMode, neighbors?.next?.aweme_id, router]);

  // ====== 视频：监听自动播放失败 ======
  useEffect(() => {
    if (!isVideo) return;
    const v = videoRef.current;
    if (!v) return;

    // 检测自动播放是否成功
    const checkAutoplay = async () => {
      try {
        await v.play();
        setIsPlaying(true);
      } catch (error) {
        // 自动播放失败（通常是浏览器策略限制）
        console.log("自动播放被阻止，需要用户交互");
        setIsPlaying(false);
      }
    };

    // 等待元数据加载后尝试播放
    if (v.readyState >= 1) {
      checkAutoplay();
    } else {
      v.addEventListener("loadedmetadata", checkAutoplay, { once: true });
      return () => v.removeEventListener("loadedmetadata", checkAutoplay);
    }
  }, [isVideo, data.aweme_id]); // 依赖 aweme_id 确保切换视频时重新检查

  useEffect(() => {
    if (!isVideo) return;
    const v = videoRef.current;
    if (v) v.volume = volume;
  }, [volume, isVideo]);

  useEffect(() => {
    if (!isVideo) return;
    const v = videoRef.current;
    if (v) v.playbackRate = rate;
  }, [rate, isVideo]);

  // ====== 视频：定期更新时间显示 ======
  useEffect(() => {
    if (!isVideo) return;
    const interval = setInterval(() => {
      forceUpdate(n => n + 1);
    }, 100); // 每 100ms 更新一次显示
    return () => clearInterval(interval);
  }, [isVideo]);

  // ====== 图文：BGM & 初次自动播放尝试 ======
  useEffect(() => {
    if (isVideo) return;
    const el = audioRef.current;
    if (!el) return;
    el.volume = volume;
    if (isPlaying) {
      el.play().catch(() => {/* 被策略阻止无妨，用户点播放即可 */ });
    } else {
      el.pause();
    }
  }, [isVideo]); // 初次挂载

  useEffect(() => {
    if (isVideo) return;
    const el = audioRef.current;
    if (el) el.volume = volume;
  }, [volume, isVideo]);

  // ====== 全屏状态监听 ======
  useEffect(() => {
    const onFsChange = () => setIsFullscreen(!!document.fullscreenElement);
    document.addEventListener("fullscreenchange", onFsChange);
    return () => document.removeEventListener("fullscreenchange", onFsChange);
  }, []);

  // ====== 监听浏览器返回事件，尝试关闭页面 ======
  useEffect(() => {
    // 在 history 中添加一个状态，用于拦截返回事件
    window.history.pushState({ interceptBack: true }, "");

    const handlePopState = (e: PopStateEvent) => {
      // 尝试关闭窗口
      window.close();

      // 如果关闭失败（100ms 后页面仍可见），则导航到首页
      setTimeout(() => {
        if (!document.hidden) {
          router.push("/");
        }
      }, 100);
    };

    window.addEventListener("popstate", handlePopState);

    return () => {
      window.removeEventListener("popstate", handlePopState);
    };
  }, [router]);

  // ====== 图文：自动切页 ======
  useEffect(() => {
    if (isVideo || !images?.length) return;

    if (segStartRef.current == null) segStartRef.current = performance.now();
    let lastTs = performance.now();
    const tick = (ts: number) => {
      if (!images?.length) return;

      if (!isPlaying) segStartRef.current! += ts - lastTs;
      lastTs = ts

      let start = segStartRef.current!;
      let localIdx = idxRef.current;

      // 前进时间：处理跨多段情况（极少见，但更稳妥）
      let elapsed = ts - start;
      while (elapsed >= SEGMENT_MS) {
        elapsed -= SEGMENT_MS;

        // 检查是否到达最后一张
        if (localIdx >= images.length - 1) {
          // 顺序播放模式：跳转到下一条作品
          if (loopMode === "sequential" && neighbors?.next) {
            router.push(`/aweme/${neighbors.next.aweme_id}`);
            return; // 停止当前动画循环
          }
          // 循环播放模式：回到第一张
          localIdx = 0;
        } else {
          localIdx = localIdx + 1;
        }
      }
      segStartRef.current = ts - elapsed;

      if (localIdx !== idxRef.current) {
        idxRef.current = localIdx;
        setIdx(localIdx);
        const el = scrollerRef.current;
        if (el) el.scrollTo({ left: localIdx * el.clientWidth, behavior: "smooth" });
      }

      const localSeg = Math.max(0, Math.min(1, elapsed / SEGMENT_MS));
      setSegProgress(localSeg);
      setProgress((localIdx + localSeg) / images.length);

      rafRef.current = requestAnimationFrame(tick);
    };

    rafRef.current = requestAnimationFrame(tick);
    return () => {
      if (rafRef.current) cancelAnimationFrame(rafRef.current);
      rafRef.current = null;
    };
  }, [isVideo, images?.length, isPlaying, loopMode, neighbors?.next?.aweme_id, router]);

  // ====== 统一操作 ======
  const seekTo = (ratio: number) => {
    ratio = Math.min(1, Math.max(0, ratio));
    if (isVideo) {
      const v = videoRef.current;
      if (!v || !v.duration) return;
      v.currentTime = v.duration * ratio;
      return;
    }
    if (!images?.length) return;
    const total = images.length;
    const exact = ratio * total;
    const targetIdx = Math.min(total - 1, Math.floor(exact));
    const remainder = exact - targetIdx;

    idxRef.current = targetIdx;
    setIdx(targetIdx);
    segStartRef.current = performance.now() - remainder * SEGMENT_MS;
    setSegProgress(remainder);
    setProgress((targetIdx + remainder) / total);

    const el = scrollerRef.current;
    if (el) el.scrollTo({ left: targetIdx * el.clientWidth, behavior: "smooth" });
  };

  const togglePlay = async () => {
    if (isVideo) {
      const v = videoRef.current;
      if (!v) return;
      if (v.paused) await v.play().catch(() => { });
      else v.pause();
      return;
    }
    const el = audioRef.current;
    if (!isPlaying) {
      setIsPlaying(true);
      try { await el?.play().catch(() => { }); } catch { }
    } else {
      setIsPlaying(false);
      el?.pause();
    }
  };

  const toggleFullscreen = () => {
    if (!document.fullscreenElement) {
      if (document.body.requestFullscreen) {
        document.body.requestFullscreen().catch(() => { });
        return
      }
      const vRef = videoRef.current;
      if (vRef && vRef.requestFullscreen) {
        vRef.requestFullscreen().catch(() => { });
        return
      }
      // @ts-ignore
      if (vRef && vRef.webkitEnterFullscreen) {
        // @ts-ignore
        vRef.webkitEnterFullscreen();
      }
    } else {
      document.exitFullscreen().catch(() => { });
    }
  };

  const prevImg = () => {
    if (!images?.length) return;
    const next = Math.max(0, idxRef.current - 1);
    idxRef.current = next;
    setIdx(next);
    segStartRef.current = performance.now();
    setSegProgress(0);
    const el = scrollerRef.current;
    if (el) el.scrollTo({ left: next * el.clientWidth, behavior: "smooth" });
  };

  const nextImg = () => {
    if (!images?.length) return;
    const next = Math.min(images.length - 1, idxRef.current + 1);
    idxRef.current = next;
    setIdx(next);
    segStartRef.current = performance.now();
    setSegProgress(0);
    const el = scrollerRef.current;
    if (el) el.scrollTo({ left: next * el.clientWidth, behavior: "smooth" });
  };

  // ====== 下载功能 ======
  const handleDownload = () => {
    if (isVideo) {
      // 下载视频
      const videoUrl = (data as VideoData).video_url;
      const link = document.createElement("a");
      link.href = videoUrl;
      link.download = `video_${data.aweme_id}.mp4`;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
    } else {
      // 下载当前图片
      if (!images?.length) return;
      const currentImage = images[idx];
      const link = document.createElement("a");
      link.href = currentImage.url;
      link.download = `image_${data.aweme_id}_${idx + 1}.jpg`;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
    }
  };

  // ====== 格式化时间显示 ======
  const formatTime = (seconds: number) => {
    const mins = Math.floor(seconds / 60);
    const secs = Math.floor(seconds % 60);
    return `${mins}:${secs.toString().padStart(2, '0')}`;
  };

  // ====== 评论内容组件 - 使用 useMemo 避免不必要的重新渲染 ======
  const commentContent = useMemo(() => (
    <>
      <header className="flex items-center gap-4 mb-5">
        <div className="size-10 rounded-full overflow-hidden bg-zinc-700/60">
          {data.author.avatar_url ? (
            // eslint-disable-next-line @next/next/no-img-element
            <img src={data.author.avatar_url} alt="avatar" className="w-full h-full object-cover" />
          ) : null}
        </div>
        <div>
          <div className="font-medium text-white/95 text-sm sm:text-base">{data.author.nickname}</div>
          <div className="text-xs text-white/50" title={new Date(data.created_at).toLocaleString()}>
            发布于 {formatRelativeTime(data.created_at)}
          </div>
        </div>
      </header>

      <ul className="space-y-4 sm:space-y-5">
        {comments.map((c) => (
          <li key={c.cid} className="flex items-start gap-3 sm:gap-4">
            <div className="size-8 rounded-full overflow-hidden bg-zinc-700/60 shrink-0">
              {c.user.avatar_url ? (
                // eslint-disable-next-line @next/next/no-img-element
                <img src={c.user.avatar_url} alt="avatar" className="w-full h-full object-cover" />
              ) : null}
            </div>
            <div className="min-w-0 flex-1">
              <div className="flex items-center gap-2">
                <span className="font-medium text-white/95 text-sm">{c.user.nickname}</span>
                <span className="text-xs text-white/50" title={new Date(c.created_at).toLocaleString()}>
                  {formatRelativeTime(c.created_at)}
                </span>
              </div>
              <p className="mt-1 text-sm leading-relaxed text-white/90 break-words">
                <CommentText text={c.text} />
              </p>
              <div className="mt-2 inline-flex items-center gap-1 text-xs text-white/70">
                <ThumbsUp size={14} />
                <span>{c.digg_count}</span>
              </div>
            </div>
          </li>
        ))}
        {comments.length === 0 ? <li className="text-sm text-white/60">暂无评论</li> : null}
      </ul>
    </>
  ), [comments, data.author, data.created_at]);

  // ====== 预取上/下一条路由，提高切换流畅度 ======
  useEffect(() => {
    if (!neighbors) return;
    if (neighbors.next) router.prefetch(`/aweme/${neighbors.next.aweme_id}`);
    if (neighbors.prev) router.prefetch(`/aweme/${neighbors.prev.aweme_id}`);
  }, [neighbors?.next?.aweme_id, neighbors?.prev?.aweme_id]);

  // ====== 鼠标滚轮切换上一条/下一条（纵向滚动） ======
  useEffect(() => {
    const el = mediaContainerRef.current;
    if (!el) return;
    const onWheel = (e: WheelEvent) => {
      // 避免缩放/横向滚动干扰
      if (e.ctrlKey) return;
      const now = performance.now();
      if (now - wheelCooldownRef.current < 700) return; // 冷却 700ms
      const dy = e.deltaY;
      if (Math.abs(dy) < 40) return; // 过滤轻微滚轮

      // 有上一条/下一条才拦截默认行为
      if ((dy > 0 && neighbors?.next) || (dy < 0 && neighbors?.prev)) {
        e.preventDefault();
      }

      if (dy > 0 && neighbors?.next) {
        wheelCooldownRef.current = now;
        router.push(`/aweme/${neighbors.next.aweme_id}`);
      } else if (dy < 0 && neighbors?.prev) {
        wheelCooldownRef.current = now;
        router.push(`/aweme/${neighbors.prev.aweme_id}`);
      }
    };
    // 需非被动监听以便 preventDefault
    el.addEventListener("wheel", onWheel, { passive: false });
    return () => el.removeEventListener("wheel", onWheel as any);
  }, [neighbors?.next?.aweme_id, neighbors?.prev?.aweme_id]);

  // ====== 键盘快捷键 ======
  useEffect(() => {
    const onKeyDown = (e: KeyboardEvent) => {
      // 如果焦点在输入框等元素上，不处理快捷键
      const target = e.target as HTMLElement;
      if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable) {
        return;
      }

      const key = e.key.toLowerCase();
      
      // 上下方向键 / w s：切换上一条/下一条视频
      if (key === 'arrowup' || key === 'w') {
        e.preventDefault();
        const now = performance.now();
        if (now - wheelCooldownRef.current < 700) return; // 冷却 700ms
        if (neighbors?.prev) {
          wheelCooldownRef.current = now;
          router.push(`/aweme/${neighbors.prev.aweme_id}`);
        }
      } else if (key === 'arrowdown' || key === 's') {
        e.preventDefault();
        const now = performance.now();
        if (now - wheelCooldownRef.current < 700) return; // 冷却 700ms
        if (neighbors?.next) {
          wheelCooldownRef.current = now;
          router.push(`/aweme/${neighbors.next.aweme_id}`);
        }
      }
      // 左右方向键 / a d：快进快退(视频) 或 切换图片(图文)
      else if (key === 'arrowleft' || key === 'a') {
        e.preventDefault();
        if (isVideo) {
          // 视频：后退 5 秒
          const v = videoRef.current;
          if (v && v.duration) {
            v.currentTime = Math.max(0, v.currentTime - 5);
          }
        } else {
          // 图文：上一张
          prevImg();
        }
      } else if (key === 'arrowright' || key === 'd') {
        e.preventDefault();
        if (isVideo) {
          // 视频：前进 5 秒
          const v = videoRef.current;
          if (v && v.duration) {
            v.currentTime = Math.min(v.duration, v.currentTime + 5);
          }
        } else {
          // 图文：下一张
          nextImg();
        }
      }
      // 空格：播放/暂停
      else if (key === ' ') {
        e.preventDefault();
        togglePlay();
      }
    };

    window.addEventListener('keydown', onKeyDown);
    return () => window.removeEventListener('keydown', onKeyDown);
  }, [isVideo, neighbors?.prev?.aweme_id, neighbors?.next?.aweme_id, router]);

  // ====== 动态模糊背景：定时截取当前媒体内容绘制到背景 canvas ======
  useEffect(() => {
    const canvas = backgroundCanvasRef.current;
    if (!canvas) return;

    const ctx = canvas.getContext("2d");
    if (!ctx) return;

    // 更新 canvas 尺寸以匹配视口
    const updateCanvasSize = () => {
      canvas.width = Math.floor(window.innerWidth / 10);
      canvas.height = Math.floor(window.innerHeight / 10);
    };
    updateCanvasSize();

    // 防抖处理 resize 事件（300ms）
    let resizeTimeout: NodeJS.Timeout;
    const debouncedResize = () => {
      clearTimeout(resizeTimeout);
      resizeTimeout = setTimeout(updateCanvasSize, 300);
    };
    window.addEventListener("resize", debouncedResize);

    // 绘制媒体内容到 canvas（cover 策略）
    const drawMediaToCanvas = () => {
      if (!ctx) return;

      let sourceElement: HTMLVideoElement | HTMLImageElement | null = null;

      // 获取当前媒体元素
      if (isVideo) {
        sourceElement = videoRef.current;
      } else {
        // 对于图文，获取当前显示的图片
        const scroller = scrollerRef.current;
        if (scroller) {
          const currentImgContainer = scroller.children[idx] as HTMLElement;
          if (currentImgContainer) {
            sourceElement = currentImgContainer.querySelector("img");
          }
        }
      }

      // 不要在帧不可用时清空画布，避免出现黑屏闪烁
      // 仅当有可绘制帧时才进行绘制，画面会被完整覆盖，无需提前 clear
      if (!sourceElement || (sourceElement instanceof HTMLVideoElement && sourceElement.readyState < 2)) return;

      const canvasWidth = canvas.width;
      const canvasHeight = canvas.height;
      const sourceWidth = sourceElement instanceof HTMLVideoElement ? sourceElement.videoWidth : sourceElement.naturalWidth;
      const sourceHeight = sourceElement instanceof HTMLVideoElement ? sourceElement.videoHeight : sourceElement.naturalHeight;

      // 图片在切换时可能尚未完成解码（naturalWidth/Height 为 0），此时保持上一帧
      if (!sourceWidth || !sourceHeight) return;

      // 计算 cover 模式的尺寸和位置
      const canvasRatio = canvasWidth / canvasHeight;
      const sourceRatio = sourceWidth / sourceHeight;

      let drawWidth: number, drawHeight: number, offsetX: number, offsetY: number;

      if (canvasRatio > sourceRatio) {
        // canvas 更宽，按宽度填充
        drawWidth = canvasWidth;
        drawHeight = canvasWidth / sourceRatio;
        offsetX = 0;
        offsetY = (canvasHeight - drawHeight) / 2;
      } else {
        // canvas 更高，按高度填充
        drawHeight = canvasHeight;
        drawWidth = canvasHeight * sourceRatio;
        offsetX = (canvasWidth - drawWidth) / 2;
        offsetY = 0;
      }

      // 直接绘制一帧即可（cover 会完全覆盖整个画布，无需 clearRect）
      ctx.drawImage(sourceElement, offsetX, offsetY, drawWidth, drawHeight);
    };

    const intervalId = setInterval(drawMediaToCanvas, 20);

    return () => {
      clearInterval(intervalId);
      window.removeEventListener("resize", debouncedResize);
      clearTimeout(resizeTimeout);
    };
  }, [isVideo, idx]);

  return (
    <div className="h-screen w-full">
      {/* 动态模糊背景 canvas */}
      <canvas
        ref={backgroundCanvasRef}
        className="fixed inset-0 w-full h-full -z-10"
        style={{ filter: "blur(40px)" }}
      />

      {/* 横屏下使用并排布局；竖屏下为单栏（评论为 bottom sheet） */}
      <div className="relative h-full landscape:flex landscape:flex-row">
        {/* 主媒体区域 */}
        <section ref={mediaContainerRef} className="relative h-screen landscape:flex-1">
          <div
            className="relative h-screen overflow-hidden"
          >
            {isVideo ? (
              <video
                ref={videoRef}
                src={(data as VideoData).video_url}
                className={[
                  // 旋转 0/180：充满容器盒子；
                  // 旋转 90/270：用中心定位 + 100vh/100vw，保证铺满全屏
                  rotation % 180 === 0
                    ? `absolute inset-0 h-full w-full bg-black/70 cursor-pointer`
                    : `absolute top-1/2 left-1/2 h-[100vw] w-[100vh] bg-black/70 cursor-pointer`,
                ].join(" ")}
                style={{
                  transform:
                    rotation % 180 === 0
                      ? `rotate(${rotation}deg)`
                      : `translate(-50%, -50%) rotate(${rotation}deg)`,
                  transformOrigin: "center center",
                  objectFit,
                }}
                playsInline
                loop={loopMode === "loop"}
                onClick={togglePlay}
              />
            ) : (
              <div className="absolute inset-0">
                <div
                  ref={scrollerRef}
                  className="absolute inset-0 overflow-x-auto  overflow-y-hidden snap-x snap-mandatory flex no-scrollbar"
                >
                  {(data as ImageData).images.map((img) => (
                    <div
                      key={img.id}
                      className="snap-center shrink-0 w-full h-screen relative bg-black/70"
                      style={{ aspectRatio: img.width && img.height ? `${img.width}/${img.height}` : undefined }}
                    >
                      {/* eslint-disable-next-line @next/next/no-img-element */}
                      <img src={img.url} alt="image" className={`absolute inset-0 w-full h-full cursor-pointer`} style={{ objectFit }} onClick={togglePlay} draggable={false} />
                    </div>
                  ))}
                </div>

                {/* 左右切图（多张时显示） */}
                {images && images.length > 1 ? (
                  <>
                    <button
                      className="absolute top-5/11 left-3 -translate-y-1/2 w-12 h-12 flex items-center justify-center text-white hover:bg-white/10 transition-colors cursor-pointer disabled:opacity-30 disabled:cursor-not-allowed border-b border-white/20 bg-black/40 backdrop-blur-sm border overflow-hidden rounded-full"
                      onClick={prevImg}
                      aria-label="上一张"
                    >
                      <ChevronLeft />
                    </button>
                    <button
                      className="absolute top-5/11 right-3 -translate-y-1/2 w-12 h-12 flex items-center justify-center text-white hover:bg-white/10 transition-colors cursor-pointer disabled:opacity-30 disabled:cursor-not-allowed border-b border-white/20 bg-black/40 backdrop-blur-sm border overflow-hidden rounded-full"
                      onClick={nextImg}
                      aria-label="下一张"
                    >
                      <ChevronRight />
                    </button>
                  </>
                ) : null}
              </div>
            )}

            {/* 暂停状态时显示的播放图标 */}
            {!isPlaying && (
              <div className="absolute inset-0 flex items-center justify-center pointer-events-none z-20">
                <div className="w-20 h-20 rounded-full bg-black/40 backdrop-blur-sm border border-white/30 flex items-center justify-center">
                  <Play size={40} className="text-white/90 ml-1" />
                </div>
              </div>
            )}

            {/* 统一控制条：desc 在上、进度在下 */}
            <div className="absolute left-0 right-0 bottom-0 px-3 pb-4 pt-2 bg-gradient-to-b from-black/0 via-black/45 to-black/65 flex flex-col gap-2.5">
              {/* 描述行 */}

              <div className="pointer-events-none flex items-center gap-2.5 mb-1">
                <img src={data.author.avatar_url!} alt="" className="w-8 h-8 rounded-full" />
                <span className="text-[15px] leading-tight text-white/95 drop-shadow">
                  {data.author.nickname}
                </span>
                <span className="text-[13px] leading-tight text-white/95 drop-shadow">
                  ·
                </span>
                <span className="text-[11px] leading-tight text-white/95 drop-shadow" title={new Date(data.created_at).toLocaleString()}>
                  {formatRelativeTime(data.created_at)}
                </span>
              </div>

              {data.desc ? (
                <div className="pointer-events-none">
                  <p className="text-[13px] leading-tight text-white/95 max-h-[3.9em] overflow-hidden [display:-webkit-box] [-webkit-line-clamp:3] [-webkit-box-orient:vertical] drop-shadow">
                    {data.desc}
                  </p>
                </div>
              ) : null}

              {/* 进度条：图文=分段；视频=单段 */}
              {!isVideo && totalSegments > 0 ? (
                <div
                  className="relative h-1.5 cursor-pointer"
                  onClick={(e) => {
                    const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();
                    seekTo((e.clientX - rect.left) / rect.width);
                  }}
                >
                  <div className="flex gap-1.5 h-full">
                    {Array.from({ length: totalSegments }).map((_, i) => {
                      let fill = 0;
                      if (i < idx) fill = 1;
                      else if (i === idx) fill = segProgress;
                      return (
                        <div
                          key={i}
                          aria-label={`第 ${i + 1} 段`}
                          className="relative flex-1 h-full rounded-full bg-white/25 overflow-hidden"
                        >
                          <div
                            className="h-full origin-left bg-white"
                            style={{ transform: `scaleX(${fill})` }}
                          />
                        </div>
                      );
                    })}
                  </div>
                </div>
              ) : (
                <div
                  className="relative h-1.5 rounded-full bg-white/25 overflow-hidden cursor-pointer"
                  onClick={(e) => {
                    const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();
                    seekTo((e.clientX - rect.left) / rect.width);
                  }}
                >
                  <div
                    className="origin-left h-full bg-white"
                    style={{ transform: `scaleX(${progress || 0})` }}
                  />
                </div>
              )}

              {/* 控制按钮行 - 响应式布局 */}
              <div className="flex items-center justify-between gap-1.5 sm:gap-2.5">
                {/* 左侧：播放控制 + 时间/进度 */}
                <div className="inline-flex items-center gap-1.5 sm:gap-2 min-w-0">
                  <button
                    className="w-[34px] h-[34px] shrink-0 inline-flex items-center justify-center rounded-full bg-white/15 text-white border border-white/20 backdrop-blur-sm cursor-pointer"
                    onClick={togglePlay}
                    aria-label={isPlaying ? "暂停" : "播放"}
                  >
                    {isPlaying ? <Pause size={18} /> : <Play size={18} />}
                  </button>

                  {/* 播放进度显示 - 所有设备都显示 */}
                  <div className="text-[13px] text-white/90 font-mono min-w-[70px] sm:min-w-[80px]">
                    {isVideo ? (
                      (() => {
                        const v = videoRef.current;
                        const current = v?.currentTime ?? 0;
                        const total = v?.duration ?? 0;
                        return total > 0 ? `${formatTime(current)} / ${formatTime(total)}` : '--:-- / --:--';
                      })()
                    ) : (
                      `${idx + 1} / ${totalSegments}`
                    )}
                  </div>

                  {/* 倍速 - 中等屏幕以上显示，仅视频 */}
                  {isVideo && (
                    <button
                      className="hidden md:block h-[30px] px-[10px] rounded-full text-[12px] bg-white/15 text-white border border-white/20 backdrop-blur-sm cursor-pointer shrink-0"
                      onClick={() => {
                        const steps = [1, 1.25, 1.5, 2, 0.75, 0.5];
                        const i = steps.indexOf(rate);
                        const next = steps[(i + 1) % steps.length];
                        setRate(next);
                      }}
                      aria-label="切换倍速"
                    >
                      {rate}x
                    </button>
                  )}
                </div>

                {/* 中间：音量控制 - 中等屏幕以上显示 */}
                <div className="hidden md:inline-flex items-center gap-2 shrink-0">
                  {/* 旋转按钮 - 小屏幕以上显示 */}
                  <button
                    className="hidden sm:inline-flex w-[34px] h-[34px] items-center justify-center rounded-full bg-white/15 text-white border border-white/20 backdrop-blur-sm cursor-pointer"
                    onClick={() => setRotation((r) => (r + 270) % 360)}
                    aria-label="向左旋转 90 度"
                    title="向左旋转 90 度"
                  >
                    <RotateCcw size={18} />
                  </button>
                  <button
                    className="w-[34px] h-[34px] inline-flex items-center justify-center rounded-full bg-white/15 text-white border border-white/20 backdrop-blur-sm cursor-pointer"
                    onClick={() => setVolume((v) => (v > 0 ? 0 : 1))}
                    aria-label={volume > 0 ? "静音" : "取消静音"}
                  >
                    {volume > 0 ? <Volume2 size={18} /> : <VolumeX size={18} />}
                  </button>
                  <input
                    type="range"
                    min={0}
                    max={1}
                    step={0.05}
                    value={volume}
                    onChange={(e) => setVolume(parseFloat(e.target.value))}
                    className="w-20 lg:w-28 accent-white cursor-pointer"
                    aria-label="音量"
                  />
                  <button
                    className="hidden sm:inline-flex w-[34px] h-[34px] items-center justify-center rounded-full bg-white/15 text-white border border-white/20 backdrop-blur-sm cursor-pointer"
                    onClick={() => setRotation((r) => (r + 90) % 360)}
                    aria-label="向右旋转 90 度"
                    title="向右旋转 90 度"
                  >
                    <RotateCw size={18} />
                  </button>
                </div>

                {/* 右侧：功能按钮组 */}
                <div className="inline-flex items-center gap-1 sm:gap-1.5 lg:gap-2 shrink-0">

                  {/* 音量按钮 - 仅在小屏幕显示（中等屏幕以上有滑块） */}
                  <button
                    className="md:hidden w-[34px] h-[34px] inline-flex items-center justify-center rounded-full bg-white/15 text-white border border-white/20 backdrop-blur-sm cursor-pointer"
                    onClick={() => setVolume((v) => (v > 0 ? 0 : 1))}
                    aria-label={volume > 0 ? "静音" : "取消静音"}
                  >
                    {volume > 0 ? <Volume2 size={18} /> : <VolumeX size={18} />}
                  </button>

                  {/* 循环模式 - 中等屏幕以上显示 */}
                  <button
                    className="hidden md:inline-flex w-[34px] h-[34px] items-center justify-center rounded-full bg-white/15 text-white border border-white/20 backdrop-blur-sm cursor-pointer"
                    onClick={() => setLoopMode((m) => (m === "loop" ? "sequential" : "loop"))}
                    aria-label={loopMode === "loop" ? "循环播放" : "顺序播放"}
                    title={loopMode === "loop" ? "循环播放" : "顺序播放"}
                  >
                    {loopMode === "loop" ? <Repeat1 size={18} /> : <ArrowDownUp size={18} />}
                  </button>

                  {/* 适配模式 - 小屏幕以上显示 */}
                  <button
                    className="hidden sm:inline-flex w-[34px] h-[34px] items-center justify-center rounded-full bg-white/15 text-white border border-white/20 backdrop-blur-sm cursor-pointer"
                    onClick={() => setObjectFit((f) => (f === "contain" ? "cover" : "contain"))}
                    aria-label={objectFit === "contain" ? "切换到填充模式" : "切换到适应模式"}
                    title={objectFit === "contain" ? "切换到填充模式" : "切换到适应模式"}
                  >
                    {objectFit === "contain" ? <Maximize2 size={18} /> : <Minimize size={18} />}
                  </button>

                  {/* 下载 - 中等屏幕以上显示 */}
                  <button
                    className="hidden md:inline-flex w-[34px] h-[34px] items-center justify-center rounded-full bg-white/15 text-white border border-white/20 backdrop-blur-sm cursor-pointer"
                    onClick={handleDownload}
                    aria-label={isVideo ? "下载视频" : "下载当前图片"}
                    title={isVideo ? "下载视频" : "下载当前图片"}
                  >
                    <Download size={18} />
                  </button>

                  {/* 全屏 - 所有设备都显示 */}
                  <button
                    className="w-[34px] h-[34px] inline-flex items-center justify-center rounded-full bg-white/15 text-white border border-white/20 backdrop-blur-sm cursor-pointer"
                    onClick={toggleFullscreen}
                    aria-label="切换全屏"
                  >
                    {isFullscreen ? <Minimize2 size={18} /> : <Maximize size={18} />}
                  </button>
                </div>
              </div>

              {/* 图文 BGM（隐藏控件，仅用于播放） */}
              {!isVideo && "music_url" in data && data.music_url ? (
                <audio ref={audioRef} src={data.music_url ?? undefined} loop preload="metadata" />
              ) : null}
            </div>
          </div>

          {/* 评论开关（竖屏：底部居中；横屏：右侧中部悬浮） */}
          <button
            className={[
              "z-10 grid place-items-center w-[54px] h-[54px] rounded-full ",
              "absolute right-4 top-2/3 -translate-y-1/2",
            ].join(" ")}
            onClick={() => setOpen((v) => !v)}
            aria-label="切换评论"
            aria-expanded={open}
          >
            <div className="grid place-items-center gap-1 drop-shadow-lg">
              <MessageSquareText size={40} className="" />
              <span className="text-xl text-white">
                {comments.length > 0 ? `${comments.length}` : "暂无评论"}
              </span>
            </div>
          </button>

          {/* 上下切换视频按钮（右侧胶囊形状） */}
          <div className="absolute right-4 top-6/11 -translate-y-1/2 z-10">
            <div className="flex flex-col rounded-full bg-black/40 backdrop-blur-sm border border-white/20 overflow-hidden">
              <button
                className="w-10 h-12 flex items-center justify-center text-white hover:bg-white/10 transition-colors cursor-pointer disabled:opacity-30 disabled:cursor-not-allowed border-b border-white/20"
                onClick={() => neighbors?.prev && router.push(`/aweme/${neighbors.prev.aweme_id}`)}
                disabled={!neighbors?.prev}
                aria-label="上一个视频"
                title="上一个视频"
              >
                <ChevronUp size={20} />
              </button>
              <button
                className="w-10 h-12 flex items-center justify-center text-white hover:bg-white/10 transition-colors cursor-pointer disabled:opacity-30 disabled:cursor-not-allowed"
                onClick={() => neighbors?.next && router.push(`/aweme/${neighbors.next.aweme_id}`)}
                disabled={!neighbors?.next}
                aria-label="下一个视频"
                title="下一个视频"
              >
                <ChevronDown size={20} />
              </button>
            </div>
          </div>
        </section>

        {/* 横屏评论面板：并排分栏 */}
        <aside
          className={`
            hidden landscape:flex
            z-30 flex-col bg-[rgba(22,22,22,0.92)] text-white
            relative h-full overflow-hidden
            ${mounted ? "transition-[width] duration-200 ease-out" : ""}
            ${open ? "w-[min(420px,36vw)] border-l border-white/10" : "w-0"}
          `}
        >
          <div className="flex items-center justify-between px-3 py-3 border-b border-white/10">
            <button
              className="w-8 h-8 inline-flex items-center justify-center rounded-full bg-white/15 text-white/90 border border-white/20 hover:bg-white/25 transition-colors"
              onClick={() => setOpen(false)}
              aria-label="关闭评论"
            >
              <X size={18} />
            </button>
            <div className="text-white font-semibold">
              评论 {comments.length > 0 ? `(${comments.length})` : ""}
            </div>
          </div>

          <div className="p-3 overflow-auto">
            {commentContent}
          </div>
        </aside>
      </div>

      {/* 竖屏评论面板：bottom sheet */}
      <aside
        className={`
          landscape:hidden
          z-30 flex flex-col bg-[rgba(22,22,22,0.92)] text-white
          fixed inset-x-0 bottom-0 w-full h-[min(80vh,88dvh)]
          ${mounted ? "transition-transform duration-200 ease-out" : ""}
          border-t border-white/10
          ${open ? "translate-y-0" : "translate-y-full"}
        `}
      >
        <div className="flex items-center justify-between px-3 py-3 border-b border-white/10">
          <div className="text-white font-semibold">
            评论 {comments.length > 0 ? `(${comments.length})` : ""}
          </div>
          <button
            className="w-8 h-8 inline-flex items-center justify-center rounded-full bg-white/15 text-white/90 border border-white/20 hover:bg-white/25 transition-colors"
            onClick={() => setOpen(false)}
            aria-label="关闭评论"
          >
            <X size={18} />
          </button>
        </div>

        <div className="p-3 overflow-auto">
          {commentContent}
        </div>
      </aside>
    </div>
  );
}
