"use client";

import { memo, useState, useEffect, useRef, useCallback } from "react";
import { motion, useMotionValue, animate } from "framer-motion";
import { useRouter } from "next/navigation";
import { useAppDispatch, useAppSelector } from "@/store/hooks";
import { clearReelQueue } from "@/store/slices/reelQueueSlice";
import { reelsListService } from "@/services/reelsListService";
import { ReelsPlayer } from "./ReelsPlayer";
import { GiftModal } from "@/components/shared/GiftModal";
import { CommentSection } from "@/components/shared/CommentSection";
import { ContentActionsModal } from "@/components/shared/ContentActionsModal";
import { CT } from "@/config/contentTypes";
import { useAddView } from "@/hooks/useAddView";
import { useLikeDislike } from "@/hooks/useLikeDislike";
import { useShare } from "@/hooks/useShare";
import type { MappedReel } from "@/services/reelsListService";

/* ── Shared heart SVG ────────────────────────────────────────────────────── */
const HeartSvg = ({ liked, size = 26 }: { liked: boolean; size?: number }) => (
  <svg
    width={size}
    height={size}
    viewBox="0 0 24 24"
    fill={liked ? "var(--accent)" : "none"}
    stroke={liked ? "var(--accent)" : "#fff"}
    strokeWidth="1.8"
    strokeLinecap="round"
    strokeLinejoin="round"
    style={{ transition: "fill 0.2s, stroke 0.2s" }}
  >
    <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
  </svg>
);

/* ── Right-rail like button ──────────────────────────────────────────────── */
function ReelLikeBtn({ reel }: { reel: MappedReel }) {
  const { liked, totalLikes, handleLike } = useLikeDislike({
    contentId: reel.id,
    contentType: reel.contentType,
    initialLikes: reel.totalLikeCount,
    initialDislikes: reel.totalDislikeCount,
    initialReaction: reel.isUserLikeDislike,
  });
  return (
    <div className="reels-action-stack" onClick={handleLike}>
      <div className="reels-action-icon">
        <HeartSvg liked={liked} size={28} />
      </div>
      <span className="reels-action-count">
        {totalLikes > 0 ? totalLikes.toLocaleString() : reel.likes}
      </span>
    </div>
  );
}

/* ── Mobile like button (inside video overlay) ───────────────────────────── */
function ReelLikeBtnMobile({ reel }: { reel: MappedReel }) {
  const { liked, totalLikes, handleLike } = useLikeDislike({
    contentId: reel.id,
    contentType: reel.contentType,
    initialLikes: reel.totalLikeCount,
    initialDislikes: reel.totalDislikeCount,
    initialReaction: reel.isUserLikeDislike,
  });
  return (
    <div className="rma-item" onClick={handleLike}>
      <div className="rma-btn">
        <HeartSvg liked={liked} size={26} />
      </div>
      <span className="rma-count">
        {totalLikes > 0 ? totalLikes.toLocaleString() : reel.likes}
      </span>
    </div>
  );
}

/* ── Progress bar (isolated) ─────────────────────────────────────────────── */
/* timeupdate fires several times per second; keeping progress state inside
   this memoized leaf means the rest of the page never re-renders for it. */
const ReelProgressBar = memo(function ReelProgressBar({
  reelId,
  register,
  onSeek,
}: {
  reelId: string;
  register: (cb: (p: number, b: number) => void) => () => void;
  onSeek: (fraction: number) => void;
}) {
  const [progress, setProgress] = useState(0); // 0 → 1, playback position
  const [buffered, setBuffered] = useState(0); // 0 → 1, downloaded ahead

  /* reset bars when the reel changes */
  useEffect(() => {
    setProgress(0);
    setBuffered(0);
  }, [reelId]);

  useEffect(
    () =>
      register((p, b) => {
        setProgress(p);
        setBuffered(b);
      }),
    [register],
  );

  return (
    <div
      className="reels-progress"
      onClick={(e) => {
        e.stopPropagation();
        const rect = e.currentTarget.getBoundingClientRect();
        onSeek((e.clientX - rect.left) / rect.width);
      }}
    >
      {/* Downloaded-ahead range (YouTube-style light bar) */}
      <div
        className="reels-progress-buffered"
        style={{ width: `${buffered * 100}%` }}
      />
      <div
        className="reels-progress-fill"
        style={{ width: `${progress * 100}%` }}
      />
    </div>
  );
});

/** Load more reels when this many items remain before the end */
const PRELOAD_THRESHOLD = 2;

/* ── skeleton ────────────────────────────────────────────────────────────── */

function ReelsPageSkeleton() {
  return (
    <div className="reels-stage">
      <div className="reels-reel-col">
        <div className="reels-viewport">
          <div className="reels-unit">
            <div
              className="reels-reel animate-pulse"
              style={{ background: "var(--deep)" }}
            >
              <div
                className="absolute inset-0"
                style={{
                  background:
                    "linear-gradient(110deg, transparent 30%, rgba(255,255,255,0.04) 50%, transparent 70%)",
                  backgroundSize: "200% 100%",
                  animation: "shimmer 1.6s infinite linear",
                }}
              />
              <div className="reels-progress">
                <div
                  className="reels-progress-fill animate-pulse"
                  style={{ width: "42%", background: "rgba(255,255,255,0.2)" }}
                />
              </div>
            </div>

            <div className="reels-meta">
              <div className="reels-creator-row">
                <div
                  className="w-8 h-8 rounded-full animate-pulse"
                  style={{ background: "var(--card)", flexShrink: 0 }}
                />
                <div
                  className="h-3 rounded-full animate-pulse"
                  style={{ background: "var(--card)", width: 96 }}
                />
              </div>
              <div
                className="h-3 rounded-full animate-pulse"
                style={{ background: "var(--card)", width: "85%" }}
              />
              <div
                className="h-2.5 rounded-full animate-pulse"
                style={{ background: "var(--card)", width: 120 }}
              />
            </div>
          </div>
        </div>

        <div className="reels-side-actions">
          {/* Right action bar */}
          <div className="reels-actions">
            {Array.from({ length: 5 }).map((_, i) => (
              <div key={i} className="reels-action-stack">
                <div
                  className="w-10 h-10 rounded-full animate-pulse"
                  style={{ background: "var(--card)" }}
                />
                <div
                  className="h-2.5 w-8 rounded-full animate-pulse mt-1"
                  style={{ background: "var(--card)" }}
                />
              </div>
            ))}
          </div>

          {/* Nav buttons */}
          <div className="reels-nav">
            <div
              className="reels-nav-btn animate-pulse"
              style={{ background: "var(--card)" }}
            />
            <div
              className="reels-nav-btn animate-pulse"
              style={{ background: "var(--card)" }}
            />
          </div>
        </div>
      </div>
    </div>
  );
}

interface ReelsPageProps {
  initialId?: string;
}

export default function ReelsPage({ initialId }: ReelsPageProps) {
  const dispatch = useAppDispatch();
  const router = useRouter();
  const { share, copied: reelCopied } = useShare();

  const goToCreator = useCallback(
    (channelUserId: string) => {
      if (channelUserId) router.push(`/profile/${channelUserId}`);
    },
    [router],
  );

  /* snapshot queue at first render before any effects run */
  const reelQueueSelector = useAppSelector((s) => s.reelQueue);
  const initQueueRef = useRef({
    queue: reelQueueSelector.queue,
    startId: reelQueueSelector.startId,
  });

  /* local reel list — populated from queue or API */
  const [reels, setReels] = useState<MappedReel[]>([]);
  const [apiPage, setApiPage] = useState(0);
  const [apiHasMore, setApiHasMore] = useState(true);
  const [isLoading, setIsLoading] = useState(true);
  const [isLoadingMore, setIsLoadingMore] = useState(false);

  const [idx, setIdx] = useState(0);
  const [playing, setPlaying] = useState(true);
  // Autoplaying unmuted video is silently blocked by browser autoplay
  // policies (no user gesture yet) — start muted like every short-video
  // feed does, so playback actually begins. User can unmute via the button.
  const [muted, setMuted] = useState(true);
  const [commentReelId, setCommentReelId] = useState<string | null>(null);
  const [giftOpen, setGiftOpen] = useState(false);
  const [reelActionsOpen, setReelActionsOpen] = useState(false);
  const stageRef = useRef<HTMLDivElement>(null);
  const videoRef = useRef<HTMLVideoElement | null>(null);

  /* Progress flows player → bar through a ref, bypassing page re-renders. */
  const progressListenerRef = useRef<((p: number, b: number) => void) | null>(
    null,
  );
  const handleProgress = useCallback((p: number, b: number) => {
    progressListenerRef.current?.(p, b);
  }, []);
  const registerProgress = useCallback((cb: (p: number, b: number) => void) => {
    progressListenerRef.current = cb;
    return () => {
      if (progressListenerRef.current === cb)
        progressListenerRef.current = null;
    };
  }, []);
  const handleSeek = useCallback((fraction: number) => {
    const video = videoRef.current;
    if (!video || !video.duration) return;
    video.currentTime = fraction * video.duration;
    if (video.paused) video.play().catch(() => {});
  }, []);
  const frameRef = useRef<HTMLDivElement>(null);
  const touchStartY = useRef(0);
  const touchStartX = useRef(0);
  const touchStartTime = useRef(0);
  const isSwiping = useRef(false);
  const isAnimatingRef = useRef(false);

  /* Vertical drag offset (px) applied to all three virtualized cards via a
     shared MotionValue — during a touch-drag it follows the finger 1:1;
     wheel/keyboard/nav-button steps animate it to a full card-height slide. */
  const dragY = useMotionValue(0);

  /** Snap the drag offset back to rest (swipe didn't clear the threshold). */
  const cancelDrag = useCallback(() => {
    animate(dragY, 0, { type: "spring", stiffness: 420, damping: 42 });
  }, [dragY]);

  /** Animate a full-card slide to the next/prev reel, then commit the index. */
  const commitStep = useCallback(
    (direction: 1 | -1) => {
      if (isAnimatingRef.current) return;
      const nextIdx = idx + direction;
      if (nextIdx < 0 || nextIdx >= reels.length) {
        cancelDrag();
        return;
      }
      const frameHeight =
        frameRef.current?.clientHeight ||
        (typeof window !== "undefined" ? window.innerHeight : 800);
      isAnimatingRef.current = true;
      animate(dragY, direction > 0 ? -frameHeight : frameHeight, {
        type: "tween",
        duration: 0.32,
        ease: [0.22, 1, 0.36, 1],
        onComplete: () => {
          setIdx(nextIdx);
          dragY.set(0);
          isAnimatingRef.current = false;
        },
      });
    },
    [idx, reels.length, dragY, cancelDrag],
  );

  /* fetch a page from the API and append/replace local reels */
  const fetchPage = useCallback(async (page: number) => {
    if (page === 1) setIsLoading(true);
    else setIsLoadingMore(true);
    try {
      const res = await reelsListService.getReelsList(page);
      const mapped = res.result.map(reelsListService.mapReel);
      setReels((prev) => (page === 1 ? mapped : [...prev, ...mapped]));
      setApiPage(res.current_page);
      setApiHasMore(res.more_page);
    } catch {
      /* silently ignore load-more failures */
    } finally {
      setIsLoading(false);
      setIsLoadingMore(false);
    }
  }, []);

  /* mount: use queue if available, otherwise fetch page 1 */
  useEffect(() => {
    const { queue, startId } = initQueueRef.current;
    if (queue.length > 0) {
      setReels(queue);
      setIsLoading(false);
      setApiPage(0); // not fetched from API yet
      setApiHasMore(true);
      const found = startId ? queue.findIndex((r) => r.id === startId) : -1;
      if (found >= 0) setIdx(found);
      dispatch(clearReelQueue());
    } else {
      fetchPage(1);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  /* for direct /reel/[id] URL visits without a queue: seek to initialId once loaded */
  useEffect(() => {
    if (
      !initialId ||
      reels.length === 0 ||
      initQueueRef.current.queue.length > 0
    )
      return;
    const found = reels.findIndex((r) => r.id === initialId);
    if (found >= 0) setIdx(found);
  }, [initialId, reels]);

  /* load more from API when approaching the end of the current list */
  useEffect(() => {
    if (reels.length === 0 || isLoading || isLoadingMore) return;
    if (idx >= reels.length - PRELOAD_THRESHOLD && apiHasMore) {
      const nextPage = apiPage === 0 ? 1 : apiPage + 1;
      fetchPage(nextPage);
    }
  }, [
    idx,
    reels.length,
    apiHasMore,
    apiPage,
    isLoading,
    isLoadingMore,
    fetchPage,
  ]);

  /* keyboard navigation — animated slide, same as a swipe/scroll step */
  useEffect(() => {
    const onKey = (e: KeyboardEvent) => {
      if (e.key === "ArrowDown") commitStep(1);
      else if (e.key === "ArrowUp") commitStep(-1);
      else if (e.key === " ") {
        e.preventDefault();
        setPlaying((p) => !p);
      }
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [commitStep]);

  /* scroll-wheel navigation (desktop) — animated slide, cooldown prevents
     one big trackpad/wheel gesture from queuing multiple steps */
  useEffect(() => {
    const el = stageRef.current;
    if (!el) return;
    let cooldown = false;
    const onWheel = (e: WheelEvent) => {
      if (cooldown || isAnimatingRef.current || Math.abs(e.deltaY) < 20) return;
      cooldown = true;
      setTimeout(() => {
        cooldown = false;
      }, 380);
      commitStep(e.deltaY > 0 ? 1 : -1);
    };
    el.addEventListener("wheel", onWheel, { passive: true });
    return () => el.removeEventListener("wheel", onWheel);
  }, [commitStep]);

  /* touch-swipe navigation — the card follows the finger 1:1 via `dragY`,
     then either finishes the slide into the next/prev reel or snaps back
     to rest, exactly like a native TikTok/Reels feed. */
  useEffect(() => {
    const el = stageRef.current;
    if (!el) return;

    const onTouchStart = (e: TouchEvent) => {
      if (isAnimatingRef.current) return;
      touchStartY.current = e.touches[0].clientY;
      touchStartX.current = e.touches[0].clientX;
      touchStartTime.current = Date.now();
      isSwiping.current = false;
    };

    const onTouchMove = (e: TouchEvent) => {
      if (isAnimatingRef.current) {
        e.preventDefault();
        return;
      }
      const currentY = e.touches[0].clientY;
      const currentX = e.touches[0].clientX;
      const dy = currentY - touchStartY.current;
      const dx = Math.abs(currentX - touchStartX.current);
      // Mark as a vertical swipe once moved enough vertically
      if (Math.abs(dy) > 10 && Math.abs(dy) > dx) isSwiping.current = true;
      // Stop the browser from scrolling/bouncing/pull-to-refreshing on every
      // touchmove inside the stage, not just once isSwiping flips true —
      // waiting for the 10px threshold left the first few pixels of every
      // swipe unprotected, giving in-app WebViews (WhatsApp, Snapchat, etc.)
      // a window to already start their native pull-to-refresh gesture.
      e.preventDefault();
      if (!isSwiping.current) return;

      // dy < 0 (finger moved up) reveals the next card sitting at +100%;
      // dy > 0 (finger moved down) reveals the prev card sitting at -100%.
      // Rubber-band the drag at the ends of the list so it doesn't feel stuck.
      const atFirst = idx === 0;
      const atLast = idx === reels.length - 1 && !apiHasMore;
      const resisted = (dy > 0 && atFirst) || (dy < 0 && atLast);
      dragY.set(resisted ? dy * 0.35 : dy);
    };

    const onTouchEnd = (e: TouchEvent) => {
      if (isAnimatingRef.current) return;
      if (!isSwiping.current) return; // plain tap — handled by onClick
      const endY = e.changedTouches[0].clientY;
      const deltaY = endY - touchStartY.current; // negative = swiped up = next
      const elapsed = Date.now() - touchStartTime.current;
      const dist = Math.abs(deltaY);
      const velocity = dist / Math.max(elapsed, 1); // px/ms
      // Cleared either a min distance or a fast flick
      const cleared = dist > 55 || (velocity > 0.5 && dist > 15);
      if (cleared && deltaY < 0 && idx < reels.length - 1) commitStep(1);
      else if (cleared && deltaY > 0 && idx > 0) commitStep(-1);
      else cancelDrag();
    };

    el.addEventListener("touchstart", onTouchStart, { passive: true });
    // Must be non-passive so preventDefault() above actually takes effect.
    el.addEventListener("touchmove", onTouchMove, { passive: false });
    el.addEventListener("touchend", onTouchEnd, { passive: true });
    return () => {
      el.removeEventListener("touchstart", onTouchStart);
      el.removeEventListener("touchmove", onTouchMove);
      el.removeEventListener("touchend", onTouchEnd);
    };
  }, [idx, reels.length, apiHasMore, dragY, commitStep, cancelDrag]);

  /* Fire add_view whenever the active reel changes — must be before any early returns */
  useAddView(3, reels[idx]?.id);

  /* ── loading / empty states ─────────────────────────────────────────── */

  if (isLoading && reels.length === 0) {
    return <ReelsPageSkeleton />;
  }

  if (!isLoading && reels.length === 0) {
    return (
      <div className="reels-stage flex items-center justify-center">
        <p className="text-sm" style={{ color: "#888" }}>
          No reels available
        </p>
      </div>
    );
  }

  const reel = reels[idx];
  if (!reel) return null;

  return (
    <div className="reels-stage" ref={stageRef}>
      <div className="reels-reel-col">
        {/* Left column (desktop only) — creator/title/sound, bottom-aligned
            beside the video, YouTube Shorts style. Swaps instantly with the
            active reel rather than sliding, like the action rail below. */}
        <div className="reels-meta-col" style={{ marginRight: "10px" }}>
          <div className="reels-creator-row">
            <div
              className="reels-avatar cursor-pointer active:scale-90 transition-transform"
              style={{ background: `hsl(${reel.hue}, 50%, 30%)` }}
              onClick={() => goToCreator(reel.channelUserId)}
            >
              {reel.channelImage ? (
                <img
                  src={reel.channelImage}
                  alt={reel.creator}
                  className="w-full h-full object-cover rounded-full"
                />
              ) : (
                reel.initial
              )}
            </div>
            <span
              className="reels-handle cursor-pointer hover:text-orange-400 transition-colors"
              onClick={() => goToCreator(reel.channelUserId)}
            >
              {reel.creator.startsWith("@") ? reel.creator : `@${reel.creator}`}
            </span>
            <button
              className="reels-connect-btn"
              onClick={() => goToCreator(reel.channelUserId)}
            >
              View
            </button>
          </div>

          <div className="reels-caption">{reel.caption}</div>

          <div className="reels-sound">
            <svg
              className="reels-sound-icon"
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              strokeWidth="2"
              strokeLinecap="round"
              strokeLinejoin="round"
            >
              <path d="M9 18V5l12-2v13" />
              <circle cx="6" cy="18" r="3" />
              <circle cx="18" cy="16" r="3" />
            </svg>
            <span className="reels-sound-text">{reel.sound}</span>
          </div>
        </div>

        {/* Clips the sliding video+meta track only — the icon rail and nav
            arrows below are fixed siblings that never move during a swipe. */}
        <div className="reels-viewport" ref={frameRef}>
          {/* Virtualized window: only prev / current / next stay mounted.
              Everything else is unmounted, which detaches its source and
              aborts its downloads. Neighbours preload metadata only, so a
              swipe starts fast without downloading whole files upfront.
              Each card carries its own video + meta caption so the whole
              thing slides together as one unit, sharing a single `dragY`
              MotionValue so all three move in lockstep. */}
          {[idx - 1, idx, idx + 1]
            .filter((i) => i >= 0 && i < reels.length)
            .map((i) => {
              const r = reels[i];
              const isActive = i === idx;
              return (
                <motion.div
                  key={r.id}
                  className="reels-unit"
                  style={{
                    top: `${(i - idx) * 100}%`,
                    y: dragY,
                    pointerEvents: isActive ? "auto" : "none",
                  }}
                >
                  {/* Video — tap toggles play, swipe navigates */}
                  <div
                    className="reels-reel"
                    onClick={() => {
                      if (isSwiping.current) return; // ignore tap if user was swiping
                      setPlaying((p) => !p);
                    }}
                  >
                    <ReelsPlayer
                      url={r.videoUrl}
                      poster={r.image}
                      active={isActive}
                      isPlaying={isActive && playing}
                      muted={muted}
                      videoRef={videoRef}
                      onProgress={handleProgress}
                    />

                    {/* Dark gradient vignette — mobile only, keeps the
                        overlaid caption/actions legible on the full-bleed
                        video (see .reels-dark-overlay). */}
                    <div className="reels-dark-overlay" />

                    {isActive && (
                      <>
                        {/* Mute button */}
                        <button
                          className="reels-mute-btn"
                          onClick={(e) => {
                            e.stopPropagation();
                            setMuted((m) => !m);
                          }}
                        >
                          {muted ? (
                            <svg
                              width="18"
                              height="18"
                              viewBox="0 0 24 24"
                              fill="none"
                              stroke="#fff"
                              strokeWidth="1.8"
                              strokeLinecap="round"
                              strokeLinejoin="round"
                            >
                              <polygon
                                points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"
                                fill="#fff"
                                stroke="none"
                              />
                              <line x1="22" y1="9" x2="16" y2="15" />
                              <line x1="16" y1="9" x2="22" y2="15" />
                            </svg>
                          ) : (
                            <svg
                              width="18"
                              height="18"
                              viewBox="0 0 24 24"
                              fill="none"
                              stroke="#fff"
                              strokeWidth="1.8"
                              strokeLinecap="round"
                              strokeLinejoin="round"
                            >
                              <polygon
                                points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"
                                fill="#fff"
                                stroke="none"
                              />
                              <path d="M15.5 8.5a5 5 0 0 1 0 7" />
                              <path d="M19 5a9 9 0 0 1 0 14" />
                            </svg>
                          )}
                        </button>

                        {/* Big play overlay */}
                        {!playing && (
                          <div className="reels-bigplay">
                            <svg
                              width="32"
                              height="32"
                              viewBox="0 0 24 24"
                              fill="#fff"
                              style={{ marginLeft: 4 }}
                            >
                              <path d="M8 5v14l11-7z" />
                            </svg>
                          </div>
                        )}

                        {/* Progress bar — isolated so timeupdate never
                            re-renders the page */}
                        <ReelProgressBar
                          reelId={r.id}
                          register={registerProgress}
                          onSeek={handleSeek}
                        />
                      </>
                    )}
                  </div>

                  {/* Meta — below the video, YouTube Shorts style */}
                  <div className="reels-meta">
                    <div className="reels-creator-row">
                      <div
                        className="reels-avatar cursor-pointer active:scale-90 transition-transform"
                        style={{ background: `hsl(${r.hue}, 50%, 30%)` }}
                        onClick={() => goToCreator(r.channelUserId)}
                      >
                        {r.channelImage ? (
                          <img
                            src={r.channelImage}
                            alt={r.creator}
                            className="w-full h-full object-cover rounded-full"
                          />
                        ) : (
                          r.initial
                        )}
                      </div>
                      <span
                        className="reels-handle cursor-pointer hover:text-orange-400 transition-colors"
                        onClick={() => goToCreator(r.channelUserId)}
                      >
                        {r.creator.startsWith("@")
                          ? r.creator
                          : `@${r.creator}`}
                      </span>
                      <button
                        className="reels-connect-btn"
                        onClick={() => goToCreator(r.channelUserId)}
                      >
                        View
                      </button>
                    </div>

                    <div className="reels-caption">{r.caption}</div>

                    <div className="reels-sound">
                      <svg
                        className="reels-sound-icon"
                        viewBox="0 0 24 24"
                        fill="none"
                        stroke="currentColor"
                        strokeWidth="2"
                        strokeLinecap="round"
                        strokeLinejoin="round"
                      >
                        <path d="M9 18V5l12-2v13" />
                        <circle cx="6" cy="18" r="3" />
                        <circle cx="18" cy="16" r="3" />
                      </svg>
                      <span className="reels-sound-text">{r.sound}</span>
                    </div>
                  </div>

                  {/* Mobile-only action overlay (Flutter Stack equivalent) —
                      replaces the desktop icon rail, which has no room on a
                      phone screen. */}
                  <div
                    className="reels-mobile-actions"
                    onClick={(e) => e.stopPropagation()}
                  >
                    {/* Creator avatar */}
                    <div
                      className="rma-item"
                      onClick={() => goToCreator(r.channelUserId)}
                    >
                      <div
                        className="rma-avatar"
                        style={{ background: `hsl(${r.hue}, 50%, 30%)` }}
                      >
                        {r.channelImage ? (
                          <img
                            src={r.channelImage}
                            alt={r.creator}
                            className="w-full h-full object-cover"
                          />
                        ) : (
                          r.initial
                        )}
                      </div>
                    </div>

                    {/* Like — only the active card wires up the live
                        like/dislike hook; neighbours show a static count
                        so a slide-in-progress preview doesn't fire extra
                        API calls for cards the user hasn't landed on. */}
                    {isActive ? (
                      <ReelLikeBtnMobile key={`mob-${r.id}`} reel={r} />
                    ) : (
                      <div className="rma-item">
                        <div className="rma-btn">
                          <HeartSvg liked={false} size={26} />
                        </div>
                        <span className="rma-count">{r.likes}</span>
                      </div>
                    )}

                    {/* Gift */}
                    <div className="rma-item" onClick={() => setGiftOpen(true)}>
                      <div className="rma-btn">
                        <svg
                          width="22"
                          height="22"
                          viewBox="0 0 24 24"
                          fill="none"
                          stroke="#f59e0b"
                          strokeWidth="1.8"
                          strokeLinecap="round"
                          strokeLinejoin="round"
                        >
                          <polyline points="20 12 20 22 4 22 4 12" />
                          <rect x="2" y="7" width="20" height="5" />
                          <line x1="12" y1="22" x2="12" y2="7" />
                          <path d="M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z" />
                          <path d="M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z" />
                        </svg>
                      </div>
                      <span className="rma-label" style={{ color: "#f59e0b" }}>
                        Gift
                      </span>
                    </div>

                    {/* Comment */}
                    <div
                      className="rma-item"
                      onClick={() => setCommentReelId(r.id)}
                    >
                      <div className="rma-btn">
                        <svg
                          width="22"
                          height="22"
                          viewBox="0 0 24 24"
                          fill="none"
                          stroke="#fff"
                          strokeWidth="1.8"
                          strokeLinecap="round"
                          strokeLinejoin="round"
                        >
                          <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
                        </svg>
                      </div>
                      <span className="rma-count">{r.comments}</span>
                    </div>

                    {/* Share */}
                    <div
                      className="rma-item"
                      onClick={() =>
                        share({
                          title: r.caption || r.channelName,
                          path: `/reel/${r.id}`,
                        })
                      }
                    >
                      <div
                        className="rma-btn"
                        style={{
                          color: reelCopied ? "var(--accent)" : undefined,
                        }}
                      >
                        <svg
                          width="22"
                          height="22"
                          viewBox="0 0 24 24"
                          fill="none"
                          stroke={reelCopied ? "var(--accent)" : "#fff"}
                          strokeWidth="1.8"
                          strokeLinecap="round"
                          strokeLinejoin="round"
                        >
                          <path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8" />
                          <polyline points="16 6 12 2 8 6" />
                          <line x1="12" y1="2" x2="12" y2="15" />
                        </svg>
                      </div>
                      <span
                        className="rma-label"
                        style={{
                          color: reelCopied ? "var(--accent)" : undefined,
                        }}
                      >
                        {reelCopied ? "Copied!" : "Share"}
                      </span>
                    </div>

                    {/* More */}
                    <div
                      className="rma-item"
                      onClick={() => setReelActionsOpen(true)}
                    >
                      <div className="rma-btn">
                        <svg
                          width="20"
                          height="20"
                          viewBox="0 0 24 24"
                          fill="#fff"
                        >
                          <circle cx="12" cy="5" r="1.6" />
                          <circle cx="12" cy="12" r="1.6" />
                          <circle cx="12" cy="19" r="1.6" />
                        </svg>
                      </div>
                    </div>
                  </div>
                </motion.div>
              );
            })}
        </div>

        <div className="reels-side-actions">
          {/* Right action bar — fixed beside the video, reflects the active reel */}
          <div className="reels-actions">
            {/* Like */}
            <ReelLikeBtn key={reel.id} reel={reel} />

            {/* Gift */}
            <div
              className="reels-action-stack cursor-pointer"
              onClick={() => setGiftOpen(true)}
            >
              <div className="reels-action-icon">
                <svg
                  width="26"
                  height="26"
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="#fff"
                  strokeWidth="1.8"
                  strokeLinecap="round"
                  strokeLinejoin="round"
                >
                  <polyline points="20 12 20 22 4 22 4 12" />
                  <rect x="2" y="7" width="20" height="5" />
                  <line x1="12" y1="22" x2="12" y2="7" />
                  <path d="M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z" />
                  <path d="M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z" />
                </svg>
              </div>
              <span
                className="reels-action-label"
                style={{ color: "#f59e0b", fontSize: "9px" }}
              >
                Gift
              </span>
            </div>

            {/* Comment */}
            <div
              className="reels-action-stack cursor-pointer"
              onClick={() => setCommentReelId(reel.id)}
            >
              <div className="reels-action-icon">
                <svg
                  width="26"
                  height="26"
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="#fff"
                  strokeWidth="1.8"
                  strokeLinecap="round"
                  strokeLinejoin="round"
                >
                  <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
                </svg>
              </div>
              <span className="reels-action-count">{reel.comments}</span>
            </div>

            {/* Share */}
            <div
              className="reels-action-stack cursor-pointer"
              onClick={() =>
                share({
                  title: reel.caption || reel.channelName,
                  path: `/reel/${reel.id}`,
                })
              }
            >
              <div className="reels-action-icon" style={{ color: "#fff" }}>
                <svg
                  width="24"
                  height="24"
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  strokeWidth="1.8"
                  strokeLinecap="round"
                  strokeLinejoin="round"
                >
                  <path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8" />
                  <polyline points="16 6 12 2 8 6" />
                  <line x1="12" y1="2" x2="12" y2="15" />
                </svg>
              </div>
              <span
                className="reels-action-label"
                style={{ color: reelCopied ? "var(--accent)" : undefined }}
              >
                {reelCopied ? "Copied!" : "Share"}
              </span>
            </div>

            {/* More */}
            <div
              className="reels-action-stack cursor-pointer"
              onClick={() => setReelActionsOpen(true)}
            >
              <div className="reels-action-icon">
                <svg width="22" height="22" viewBox="0 0 24 24" fill="#fff">
                  <circle cx="12" cy="5" r="1.6" />
                  <circle cx="12" cy="12" r="1.6" />
                  <circle cx="12" cy="19" r="1.6" />
                </svg>
              </div>
            </div>

            <div className="reels-vinyl" />
          </div>

          {/* Up / Down nav — desktop only */}
          <div className="reels-nav">
            <button
              className="reels-nav-btn"
              disabled={idx === 0}
              onClick={() => commitStep(-1)}
            >
              <svg
                width="20"
                height="20"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                strokeWidth="2"
                strokeLinecap="round"
                strokeLinejoin="round"
              >
                <polyline points="18 15 12 9 6 15" />
              </svg>
            </button>
            <button
              className="reels-nav-btn"
              disabled={idx === reels.length - 1 && !apiHasMore}
              onClick={() => commitStep(1)}
            >
              <svg
                width="20"
                height="20"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                strokeWidth="2"
                strokeLinecap="round"
                strokeLinejoin="round"
              >
                <polyline points="6 9 12 15 18 9" />
              </svg>
            </button>
          </div>
        </div>
      </div>

      {/* Comment bottom sheet */}
      {commentReelId && (
        <CommentSection
          mode="sheet"
          isOpen={!!commentReelId}
          onClose={() => setCommentReelId(null)}
          contentType={3}
          contentId={commentReelId}
          totalComments={0}
          canComment
        />
      )}

      {/* Gift modal */}
      {giftOpen && reel && (
        <GiftModal target={reel} onClose={() => setGiftOpen(false)} />
      )}

      {/* Content actions modal (Watch Later, Playlist, Report) */}
      {reelActionsOpen && reel && (
        <ContentActionsModal
          context={{
            contentId: reel.id,
            contentType: CT.REEL,
            channelId: reel.channelId,
            channelUserId: reel.channelUserId,
            title: reel.caption,
            thumbnail: reel.image,
            channelName: reel.channelName,
          }}
          onClose={() => setReelActionsOpen(false)}
        />
      )}
    </div>
  );
}
