"use client";

import React, {
  useState,
  useRef,
  useEffect,
  useContext,
  useCallback,
} from "react";
import { Post } from "@/types/types";
import Image from "next/image";
import Link from "next/link";
import { motion, AnimatePresence } from "framer-motion";
import { buildStorageUrl } from "@/components/main/BaseUrl";
import VerificationBadge from "@/components/main/VerificationBadge";
import { useUserById } from "@/hooks/getUserById";
import BoldIcon from "@/components/ui/BoldIcon";
import ReelsPostActions from "./ReelsPostActions";
import ReelsImageCarousel from "./ReelsImageCarousel";
import PostCommentsContent from "./PostCommentsContent";
import ExpandableCaption from "./ExpandableCaption";
import StoryRing, { verifyBadgeToTierColor } from "@/components/stories/StoryRing";
import StoryAvatarOpen from "@/components/stories/StoryAvatarOpen";
import { useStoryMetaForUser } from "@/hooks/useStoryMetaForUser";
import { MutedContext } from "@/components/models/ModelPage/MainModelCardPost";
import Cookies from "js-cookie";
import { trackExploreInteraction } from "@/api/trackExploreInteraction";
import { cn } from "@/lib/utils";
import { resolvePostMediaType } from "@/lib/reelsMediaType";
import { getVideoPoster } from "@/lib/explore/postMedia";
import { getPostVideoSrc, prefetchVideoUrl } from "@/lib/videoPreload";
import { useExploreReelsUi } from "@/contexts/ExploreReelsUiContext";
import { usePostSocialState } from "@/hooks/usePostSocialActions";
import { sharePostToStory } from "@/api/fetchStories";
import { useRequireAuth } from "@/lib/auth/useRequireAuth";
import toast from "react-hot-toast";
import { useTranslation } from "react-i18next";
import {
  reorderCaptionLinksToEnd,
  splitCaptionBodyAndLinks,
} from "@/lib/postLinkCaption";

const HOLD_MS = 220;
const LONG_VIDEO_SEC = 10;
const DOUBLE_TAP_MS = 280;

export type VideoPreloadPriority = "active" | "nearby" | "idle";

function formatVideoTime(seconds: number) {
  const s = Math.max(0, Math.floor(seconds));
  const m = Math.floor(s / 60);
  const r = s % 60;
  return `${m}:${r.toString().padStart(2, "0")}`;
}

function ReelsMediaSkeleton() {
  return (
    <div className="absolute inset-0 z-10 flex flex-col gap-3 bg-black/80 p-6">
      <div className="h-4 w-1/3 animate-pulse rounded-full bg-white/15" />
      <div className="flex-1 animate-pulse rounded-2xl bg-white/10" />
      <div className="h-3 w-2/3 animate-pulse rounded-full bg-white/10" />
    </div>
  );
}

interface ReelsPostCardProps {
  postData: Post;
  isActive?: boolean;
  postPage?: boolean;
  preloadPriority?: VideoPreloadPriority;
}

export default function ReelsPostCard({
  postData,
  isActive = false,
  postPage = false,
  preloadPriority = "idle",
}: ReelsPostCardProps) {
  const { t } = useTranslation("common");
  const {
    user_id,
    user_name,
    first_name,
    last_name,
    caption,
    files,
    type: postType,
  } = postData;

  const type = resolvePostMediaType(postData) ?? postType;
  const videoPoster = type === "video" ? getVideoPoster(postData) : undefined;
  const videoSrc = type === "video" ? getPostVideoSrc(postData) : undefined;

  const videoPreload =
    preloadPriority === "active" || preloadPriority === "nearby"
      ? "auto"
      : preloadPriority === "idle"
        ? "metadata"
        : "none";

  const user = useUserById(user_id);
  const storyMeta = useStoryMetaForUser(user_id);
  const profile_image = user?.profile_image;
  const verify_badge = user?.verify_badge;

  const [captionExpanded, setCaptionExpanded] = useState(false);
  const orderedCaption = reorderCaptionLinksToEnd(caption || "");
  const { body: captionBody, links: captionLinks } =
    splitCaptionBodyAndLinks(orderedCaption);

  useEffect(() => {
    setCaptionExpanded(false);
  }, [postData._id]);
  const [imageLoading, setImageLoading] = useState(() => (files?.length ?? 0) > 0);
  const [commentsOpen, setCommentsOpen] = useState(false);
  const [uiHidden, setUiHidden] = useState(false);
  const [likeBurstKey, setLikeBurstKey] = useState<number | null>(null);
  const [videoDuration, setVideoDuration] = useState(0);
  const [videoCurrent, setVideoCurrent] = useState(0);
  const [bufferedEnd, setBufferedEnd] = useState(0);
  const [videoReady, setVideoReady] = useState(false);
  const [videoPaused, setVideoPaused] = useState(false);
  const [sharingStory, setSharingStory] = useState(false);

  const videoRef = useRef<HTMLVideoElement | null>(null);
  const containerRef = useRef<HTMLElement | null>(null);
  const viewStartedAtRef = useRef<number | null>(null);
  const watchCompleteTrackedRef = useRef(false);
  const holdTimerRef = useRef<number | null>(null);
  const holdTriggeredRef = useRef(false);
  const singleTapTimerRef = useRef<number | null>(null);

  const { muted, setMuted } = useContext(MutedContext);
  const [videoMuted, setVideoMuted] = useState(true);
  const exploreUi = useExploreReelsUi();
  const social = usePostSocialState(postData);
  const requireAuth = useRequireAuth();
  const chromeHidden = exploreUi ? exploreUi.chromeHidden : uiHidden;
  const allowSave = postData.author_allow_save !== false;

  const useCommentsSheet = !postPage;
  const showLongVideoBar =
    type === "video" && videoDuration > LONG_VIDEO_SEC && isActive && !chromeHidden;

  const mediaFiles =
    files?.map((file) => ({
      ...file,
      src: buildStorageUrl(file.path),
    })) || [];

  const imageFiles = mediaFiles.filter((file) => file.type !== "video");

  const clearHoldTimer = useCallback(() => {
    if (holdTimerRef.current) {
      window.clearTimeout(holdTimerRef.current);
      holdTimerRef.current = null;
    }
  }, []);

  const handleMediaPointerDown = useCallback(
    (e: React.PointerEvent) => {
      if (commentsOpen || !isActive) return;
      if (e.pointerType === "mouse" && e.button !== 0) return;
      holdTriggeredRef.current = false;
      clearHoldTimer();
      holdTimerRef.current = window.setTimeout(() => {
        holdTriggeredRef.current = true;
        if (exploreUi) {
          exploreUi.setChromeHidden(true);
        } else {
          setUiHidden(true);
        }
      }, HOLD_MS);
    },
    [commentsOpen, isActive, clearHoldTimer, exploreUi]
  );

  const handleMediaPointerUp = useCallback(() => {
    clearHoldTimer();
    if (exploreUi) {
      exploreUi.setChromeHidden(false);
    } else {
      setUiHidden(false);
    }
    holdTriggeredRef.current = false;
  }, [clearHoldTimer, exploreUi]);

  const handleMediaClick = useCallback(
    (e: React.MouseEvent) => {
      if (postPage || commentsOpen || !isActive) return;
      if (singleTapTimerRef.current) {
        window.clearTimeout(singleTapTimerRef.current);
      }
      singleTapTimerRef.current = window.setTimeout(() => {
        singleTapTimerRef.current = null;
        if (exploreUi?.chromeHidden) {
          exploreUi.setChromeHidden(false);
          return;
        }
        if (e.target === e.currentTarget) {
          // tap on empty overlay only
        }
      }, DOUBLE_TAP_MS);
    },
    [postPage, commentsOpen, isActive, exploreUi]
  );

  const handleMediaDoubleClick = useCallback(
    (e: React.MouseEvent) => {
      if (postPage || commentsOpen || !isActive) return;
      e.stopPropagation();
      if (singleTapTimerRef.current) {
        window.clearTimeout(singleTapTimerRef.current);
        singleTapTimerRef.current = null;
      }
      if (!social.liked) {
        void social.toggleLike();
      }
      setLikeBurstKey(Date.now());
      window.setTimeout(() => setLikeBurstKey(null), 900);
    },
    [postPage, commentsOpen, isActive, social]
  );

  const handleVideoClick = (e: React.MouseEvent<HTMLVideoElement>) => {
    if (holdTriggeredRef.current || e.detail > 1) return;
    e.stopPropagation();
    const v = videoRef.current;
    if (!v) return;

    if (v.paused) {
      void v.play().catch(() => {});
      setVideoPaused(false);
    } else {
      v.pause();
      setVideoPaused(true);
    }
  };

  const toggleVideoMute = (e: React.MouseEvent) => {
    e.stopPropagation();
    const v = videoRef.current;
    if (!v) return;
    v.muted = !v.muted;
    setVideoMuted(v.muted);
    setMuted(v.muted);
    if (!v.muted && v.paused) {
      void v.play().catch(() => {});
      setVideoPaused(false);
    }
  };

  const resumeVideo = (e: React.MouseEvent) => {
    e.stopPropagation();
    const v = videoRef.current;
    if (!v) return;
    void v.play().catch(() => {});
    setVideoPaused(false);
  };

  const handleShareToStory = async () => {
    if (!requireAuth()) return;
    const token = Cookies.get("token") || "";
    if (!token) return;
    setSharingStory(true);
    try {
      await sharePostToStory(postData._id, token);
      toast.success(t("posts.sharedToStory"));
    } catch (err) {
      toast.error(err instanceof Error ? err.message : t("posts.shareToStoryError"));
    } finally {
      setSharingStory(false);
    }
  };

  const handleVideoTimeUpdate = () => {
    const v = videoRef.current;
    if (!v) return;
    setVideoCurrent(v.currentTime);
    if (v.buffered.length > 0) {
      setBufferedEnd(v.buffered.end(v.buffered.length - 1));
    }
  };

  useEffect(() => {
    setVideoReady(false);
    setVideoPaused(false);
  }, [videoSrc]);

  useEffect(() => {
    if (type !== "video" || !videoSrc) return;
    if (preloadPriority === "active" || preloadPriority === "nearby") {
      prefetchVideoUrl(videoSrc, "high");
    }
  }, [type, videoSrc, preloadPriority]);

  useEffect(() => {
    const video = videoRef.current;
    if (!video || type !== "video") return;

    if (isActive && !commentsOpen && !videoPaused) {
      video.play().catch(() => {});
      video.muted = muted;
      setVideoMuted(muted);
    } else {
      video.pause();
    }
  }, [isActive, muted, type, commentsOpen, videoPaused]);

  useEffect(() => {
    if (!isActive) {
      setCommentsOpen(false);
      if (!exploreUi) {
        setUiHidden(false);
      }
    }
  }, [isActive, exploreUi]);

  useEffect(() => {
    const token = Cookies.get("token") || "";
    const payload = {
      targetType: "post" as const,
      targetId: postData._id,
      authorId: postData.user_id,
      contentType: (postData.type === "video" ? "video" : "image") as
        | "video"
        | "image",
    };

    if (!isActive) {
      if (viewStartedAtRef.current && token) {
        const dwellMs = Date.now() - viewStartedAtRef.current;
        if (dwellMs < 2500) {
          trackExploreInteraction({ ...payload, action: "skip", dwellMs }, token);
        } else if (!watchCompleteTrackedRef.current && dwellMs >= 5000) {
          trackExploreInteraction({ ...payload, action: "dwell", dwellMs }, token);
        }
      }
      viewStartedAtRef.current = null;
      watchCompleteTrackedRef.current = false;
      return;
    }

    viewStartedAtRef.current = Date.now();
    watchCompleteTrackedRef.current = false;

    if (token) {
      trackExploreInteraction({ ...payload, action: "view" }, token);
    }

    const completeDelay =
      type === "video"
        ? Math.min(9000, Math.max(4000, (videoRef.current?.duration || 12) * 750))
        : 3500;

    const completeTimer = window.setTimeout(() => {
      if (!token || watchCompleteTrackedRef.current) return;
      watchCompleteTrackedRef.current = true;
      trackExploreInteraction(
        { ...payload, action: "watch_complete", dwellMs: completeDelay },
        token
      );
    }, completeDelay);

    return () => window.clearTimeout(completeTimer);
  }, [isActive, postData._id, postData.user_id, postData.type, type]);

  const bufferPct =
    videoDuration > 0 ? Math.min(100, (bufferedEnd / videoDuration) * 100) : 0;
  const progressPct =
    videoDuration > 0 ? Math.min(100, (videoCurrent / videoDuration) * 100) : 0;
  const remaining = Math.max(0, videoDuration - videoCurrent);

  return (
    <article
      ref={containerRef}
      className="relative flex h-full min-h-0 w-full flex-col overflow-hidden bg-black"
    >
      <motion.div
        className={cn(
          "relative w-full shrink-0 overflow-hidden",
          commentsOpen && useCommentsSheet && "mx-2 rounded-3xl"
        )}
        animate={{ height: commentsOpen && useCommentsSheet ? "50%" : "100%" }}
        transition={{ duration: 0.32, ease: [0.25, 0.46, 0.45, 0.94] }}
        onPointerDown={handleMediaPointerDown}
        onPointerUp={handleMediaPointerUp}
        onPointerLeave={handleMediaPointerUp}
        onPointerCancel={handleMediaPointerUp}
        onClick={handleMediaClick}
        onDoubleClick={handleMediaDoubleClick}
      >
        <div className="absolute inset-0 flex items-center justify-center">
          {type !== "video" && imageFiles.length > 0 && (
            <ReelsImageCarousel
              mediaFiles={imageFiles}
              isActive={isActive && !commentsOpen}
              priority={isActive}
              onLoadingComplete={() => setImageLoading(false)}
            />
          )}

          {type === "video" && (videoSrc || mediaFiles.length > 0) && (
            <>
              {videoPoster && !videoReady && (
                <Image
                  src={videoPoster}
                  alt=""
                  fill
                  className="object-contain"
                  unoptimized
                  priority={isActive || preloadPriority === "nearby"}
                />
              )}
              <video
                ref={videoRef}
                src={videoSrc ?? mediaFiles[0]?.src}
                poster={videoPoster}
                loop
                playsInline
                preload={videoPreload}
                className={cn(
                  "h-full w-full object-contain",
                  videoPoster && !videoReady && "opacity-0"
                )}
                onClick={handleVideoClick}
                onLoadedData={() => {
                  setImageLoading(false);
                  setVideoReady(true);
                }}
                onCanPlay={() => {
                  setImageLoading(false);
                  setVideoReady(true);
                }}
                onLoadedMetadata={(e) =>
                  setVideoDuration(e.currentTarget.duration || 0)
                }
                onTimeUpdate={handleVideoTimeUpdate}
                onProgress={handleVideoTimeUpdate}
                onPlay={() => setVideoPaused(false)}
                onPause={() => setVideoPaused(true)}
                muted={muted}
              />
              {videoPaused && isActive && !commentsOpen && (
                <div className="pointer-events-none absolute inset-0 z-[25] flex flex-col items-center justify-center gap-4">
                  <button
                    type="button"
                    onClick={toggleVideoMute}
                    className="pointer-events-auto flex h-11 w-11 items-center justify-center rounded-full bg-black/55 text-white backdrop-blur-md"
                    aria-label={videoMuted ? t("posts.unmute") : t("posts.mute")}
                  >
                    {videoMuted ? (
                      <BoldIcon name="volume-slash" size={22} tinted className="text-white" />
                    ) : (
                      <BoldIcon name="volume-high" size={22} tinted className="text-white" />
                    )}
                  </button>
                  <button
                    type="button"
                    onClick={resumeVideo}
                    className="pointer-events-auto flex h-16 w-16 items-center justify-center rounded-full bg-black/55 text-white backdrop-blur-md"
                    aria-label={t("posts.playVideo")}
                  >
                    <BoldIcon name="play" size={30} tinted className="text-white" />
                  </button>
                </div>
              )}
            </>
          )}

          {imageLoading && isActive && !commentsOpen && <ReelsMediaSkeleton />}

          {likeBurstKey ? (
            <div className="pointer-events-none absolute inset-0 z-30 flex items-center justify-center">
              <motion.div
                key={likeBurstKey}
                initial={{ scale: 0, opacity: 0.9 }}
                animate={{ scale: 1.15, opacity: 0 }}
                transition={{ duration: 0.75, ease: "easeOut" }}
              >
                <Image
                  src="/images/icons/red-heart.svg"
                  alt=""
                  width={96}
                  height={96}
                  className="drop-shadow-2xl"
                />
              </motion.div>
            </div>
          ) : null}
        </div>

        {showLongVideoBar && (
          <div className="pointer-events-none absolute inset-x-0 bottom-[calc(5.5rem+env(safe-area-inset-bottom))] z-30 px-3">
            <div className="relative h-0.5 overflow-hidden rounded-full bg-white/25">
              <div
                className="absolute inset-y-0 left-0 rounded-full bg-white/35"
                style={{ width: `${bufferPct}%` }}
              />
              <div
                className="absolute inset-y-0 left-0 rounded-full bg-white"
                style={{ width: `${progressPct}%` }}
              />
            </div>
            <p className="mt-1 text-right text-[10px] tabular-nums text-white/85">
              {formatVideoTime(remaining)}
            </p>
          </div>
        )}

        <AnimatePresence>
          {!chromeHidden && !commentsOpen && (
            <>
              <motion.div
                initial={{ opacity: 0 }}
                animate={{ opacity: 1 }}
                exit={{ opacity: 0 }}
                className={cn(
                  "pointer-events-none absolute inset-x-0 bottom-0 z-20 bg-gradient-to-t from-black/90 via-black/60 to-transparent px-4 pb-[calc(1.25rem+env(safe-area-inset-bottom))] pt-16"
                )}
              >
                <div className="pointer-events-auto flex items-center gap-3">
                  <StoryAvatarOpen userId={user_id} className="shrink-0">
                    <StoryRing
                      hasStory={storyMeta.hasStory}
                      hasUnviewed={storyMeta.hasUnviewed}
                      tierColor={verifyBadgeToTierColor(verify_badge)}
                      rounded="full"
                      avatarSize={40}
                    >
                      <div className="relative h-10 w-10 shrink-0 overflow-hidden rounded-full">
                        <Image
                          src={
                            profile_image
                              ? buildStorageUrl(profile_image)
                              : "/images/fake-avatar.png"
                          }
                          alt={user_name}
                          fill
                          className="rounded-full object-cover"
                          unoptimized
                        />
                      </div>
                    </StoryRing>
                  </StoryAvatarOpen>
                  <Link
                    href={`/users/${user_name}`}
                    className="flex min-w-0 flex-1 items-center gap-2.5"
                  >
                    <div className="min-w-0 flex-1 text-white">
                      <div className="flex items-center gap-1 truncate text-sm font-semibold">
                        <span className="truncate">{user_name}</span>
                        <VerificationBadge verifyBadge={verify_badge} />
                      </div>
                      <p className="truncate text-xs text-white/80">
                        {first_name} {last_name}
                      </p>
                    </div>
                  </Link>
                </div>
                {(captionBody || captionLinks) && (
                  <div className="pointer-events-auto mt-2">
                    <ExpandableCaption
                      body={captionBody}
                      links={captionLinks}
                      expanded={captionExpanded}
                      onToggle={() => setCaptionExpanded((v) => !v)}
                      variant="reels"
                      scrollWhenExpanded
                    />
                  </div>
                )}
              </motion.div>
            </>
          )}
        </AnimatePresence>
      </motion.div>

      {!chromeHidden && !commentsOpen && (
        <ReelsPostActions
          postData={postData}
          social={social}
          allowSave={allowSave}
          alwaysVisible={false}
          sharingStory={sharingStory}
          onShareToStory={() => void handleShareToStory()}
          onCommentClick={
            useCommentsSheet ? () => setCommentsOpen(true) : undefined
          }
        />
      )}

      <AnimatePresence>
        {commentsOpen && useCommentsSheet && (
          <motion.div
            key="comments-sheet"
            initial={{ height: 0, opacity: 0 }}
            animate={{ height: "50dvh", opacity: 1 }}
            exit={{ height: 0, opacity: 0 }}
            transition={{ duration: 0.32, ease: [0.25, 0.46, 0.45, 0.94] }}
            className={cn(
              "glass-modal-panel relative z-40 flex min-h-0 flex-col overflow-hidden rounded-t-3xl"
            )}
          >
            <PostCommentsContent
              userId={user_id}
              postId={postData._id}
              variant="sheet"
              onClose={() => setCommentsOpen(false)}
              className="h-full"
            />
          </motion.div>
        )}
      </AnimatePresence>
    </article>
  );
}
