import {
  useEffect,
  useState,
  useCallback,
  useRef,
  memo,
  useMemo,
} from "react";
import { motion, AnimatePresence } from "framer-motion";
import {
  Plus,
  ChevronRight,
  Loader2,
  ArrowUp,
  Sparkles,
  Users,
  RefreshCw,
  Share2,
} from "lucide-react";
import { useNavigate } from "react-router-dom";
import { useQueryClient } from "@tanstack/react-query";
import { supabase, createRealtimeChannel } from "@/integrations/supabase/client";
import { useAuth } from "@/hooks/useAuth";
import { useLike } from "@/hooks/useLike";
import AppLayout from "@/components/AppLayout";
import BrandLogo from "@/components/BrandLogo";
import PostCard from "@/components/PostCard";
import StoryCard from "@/components/StoryCard";
import { AdInFeed } from "@/components/AdPost";
import { preloadPage } from "@/lib/preload";
import { cn } from "@/lib/utils";

// ── Public exports ────────────────────────────────────────────────────────────
export const FEED_QUERY_KEY = ["feed-posts"];

/**
 * Fire-and-forget helper to record a share event.
 * Safe to call without awaiting — any RPC errors are swallowed.
 */
export async function trackShare(
  postId: string,
  type: "link" | "native" | "copy" | "story" | string
): Promise<void> {
  try {
    await supabase.rpc("record_post_share", {
      p_post_id: postId,
      p_share_type: type,
    });
  } catch {
    // RPC may not exist yet — silently ignore
  }
}

// ── Constants ─────────────────────────────────────────────────────────────────
/** Number of posts revealed per virtual display window chunk */
const CHUNK_SIZE = 8;
/** ms a post must stay in-viewport before a view event is recorded */
const VIEW_THRESHOLD_MS = 1500;

// ── Types ─────────────────────────────────────────────────────────────────────
interface Story {
  id: string;
  user_id: string;
  image_url: string;
  is_sponsored?: boolean;
  profiles?: any;
}

interface Post {
  id: string;
  user_id: string;
  image_url: string;
  image_urls?: string[] | null;
  caption: string | null;
  likes_count: number;
  comments_count: number;
  created_at: string;
  profiles?: any;
  liked_by_me?: boolean;
  media_type?: "image" | "video" | "audio";
  video_url?: string | null;
  thumbnail_url?: string | null;
  audio_url?: string | null;
  scale_type?: "original" | "square" | "wide" | "tall";
  music_metadata?: any;
  is_sponsored?: boolean;
  sponsor_name?: string;
  sponsor_url?: string;
}

/** Cursor used for keyset / cursor-based pagination */
interface FeedCursor {
  lastPostId: string;
  lastCreatedAt: string;
}

// ── Memoised PostCard ─────────────────────────────────────────────────────────
const MemoPostCard = memo(PostCard);

// ── Skeleton card (shimmer) ───────────────────────────────────────────────────
const FeedPostSkeleton = () => (
  <div className="bg-[#0F172A] rounded-3xl p-5 space-y-4 shadow-sm border border-white/[0.04] overflow-hidden relative">
    {/* shimmer sweep */}
    <div className="absolute inset-0 -translate-x-full animate-[shimmer_2s_infinite] bg-gradient-to-r from-transparent via-white/5 to-transparent z-10 pointer-events-none" />
    {/* header */}
    <div className="flex items-center gap-3">
      <div className="w-10 h-10 rounded-full bg-slate-800/60 shrink-0" />
      <div className="space-y-2 flex-1">
        <div className="h-3 w-32 bg-slate-800/60 rounded-full" />
        <div className="h-2 w-20 bg-slate-800/40 rounded-full" />
      </div>
    </div>
    {/* media placeholder */}
    <div className="h-[320px] sm:h-[400px] w-full bg-slate-800/40 rounded-2xl" />
    {/* action row */}
    <div className="flex items-center gap-4 pt-1">
      <div className="w-6 h-6 rounded-full bg-slate-800/60" />
      <div className="w-6 h-6 rounded-full bg-slate-800/60" />
      <div className="w-6 h-6 rounded-full bg-slate-800/60" />
    </div>
    {/* caption lines */}
    <div className="space-y-2">
      <div className="h-2.5 w-3/4 bg-slate-800/40 rounded-full" />
      <div className="h-2.5 w-1/2 bg-slate-800/30 rounded-full" />
    </div>
  </div>
);

// ── Story skeleton ────────────────────────────────────────────────────────────
const StorySkeleton = () => (
  <div className="flex flex-col items-center gap-1.5 shrink-0 animate-pulse">
    <div className="w-16 h-16 rounded-full bg-slate-800/60" />
    <div className="w-12 h-2 rounded-full bg-slate-800/40" />
  </div>
);

// ── Main Feed component ───────────────────────────────────────────────────────
export default function Feed() {
  const navigate = useNavigate();
  const { user } = useAuth();
  const { toggleLike } = useLike();
  const queryClient = useQueryClient();

  // ── UI state ────────────────────────────────────────────────────────────────
  const [feedMode, setFeedMode] = useState<"for-you" | "following">("for-you");
  const [stories, setStories] = useState<Story[]>([]);
  const [storiesLoading, setStoriesLoading] = useState(true);
  const [posts, setPosts] = useState<Post[]>([]);
  const [followingUserIds, setFollowingUserIds] = useState<Set<string>>(new Set());
  const [loading, setLoading] = useState(true);
  const [loadingMore, setLoadingMore] = useState(false);
  const [displayCount, setDisplayCount] = useState(CHUNK_SIZE);
  const [newPostsCount, setNewPostsCount] = useState(0);
  const [showScrollTop, setShowScrollTop] = useState(false);
  const [hasNextPage, setHasNextPage] = useState(true);

  // ── Refs ─────────────────────────────────────────────────────────────────────
  const storyScrollRef = useRef<HTMLDivElement>(null);
  const lastFeedTimestampRef = useRef<string | null>(null);
  const sentinelRef = useRef<HTMLDivElement>(null);
  const cursorRef = useRef<FeedCursor | null>(null);
  /** Posts whose view has already been recorded this session */
  const viewedPostsRef = useRef<Set<string>>(new Set());
  /** Per-post view timers: postId → setTimeout handle */
  const viewTimersRef = useRef<Map<string, ReturnType<typeof setTimeout>>>(new Map());
  const prefetchingRef = useRef(false);

  // ── Preload adjacent pages ───────────────────────────────────────────────────
  useEffect(() => {
    preloadPage("/messages");
    preloadPage("/notifications");
    preloadPage("/profile");
    preloadPage("/search");
  }, []);

  // ── Ranking algorithm ────────────────────────────────────────────────────────
  const rankPosts = useCallback((rawPosts: Post[], followedIds: Set<string>): Post[] => {
    return [...rawPosts].sort((a, b) => {
      // Sponsored posts always bubble to top
      if (a.is_sponsored && !b.is_sponsored) return -1;
      if (!a.is_sponsored && b.is_sponsored) return 1;

      const ageHoursA = Math.max(0.1, (Date.now() - new Date(a.created_at).getTime()) / 3_600_000);
      const ageHoursB = Math.max(0.1, (Date.now() - new Date(b.created_at).getTime()) / 3_600_000);

      const followedBonusA = a.user_id && followedIds.has(a.user_id) ? 35 : 0;
      const followedBonusB = b.user_id && followedIds.has(b.user_id) ? 35 : 0;
      const verifiedBonusA = a.profiles?.is_verified ? 15 : 0;
      const verifiedBonusB = b.profiles?.is_verified ? 15 : 0;

      // Hacker News–style gravity formula
      const scoreA =
        ((a.likes_count || 0) * 3.5 + (a.comments_count || 0) * 6.0 + followedBonusA + verifiedBonusA) /
        Math.pow(ageHoursA + 2, 1.35);
      const scoreB =
        ((b.likes_count || 0) * 3.5 + (b.comments_count || 0) * 6.0 + followedBonusB + verifiedBonusB) /
        Math.pow(ageHoursB + 2, 1.35);

      return scoreB - scoreA;
    });
  }, []);

  // ── Mark posts as seen (fire and forget) ────────────────────────────────────
  const markPostsSeen = useCallback(
    (postIds: string[]) => {
      if (!user || postIds.length === 0) return;
      supabase
        .rpc("mark_posts_seen", { p_user_id: user.id, p_post_ids: postIds })
        .then()
        .catch(() => {/* RPC may not exist yet */});
    },
    [user]
  );

  // ── Client-side post fetch (fallback / pagination) ───────────────────────────
  const fetchPostsClientSide = useCallback(
    async (followedSet: Set<string>, cursor?: FeedCursor): Promise<Post[]> => {
      let query = supabase
        .from("posts")
        .select(
          "*, profiles!posts_user_id_fkey(display_name,photo_url,username,is_verified,profile_theme)"
        )
        .order("created_at", { ascending: false })
        .limit(60);

      if (cursor) {
        query = query.lt("created_at", cursor.lastCreatedAt);
      }

      const [postsRes, likesRes] = await Promise.all([
        query,
        user
          ? supabase.from("post_likes").select("post_id").eq("user_id", user.id)
          : Promise.resolve({ data: [] as { post_id: string }[] }),
      ]);

      if (!postsRes.data) return [];

      const likedSet = new Set(
        ((likesRes as any)?.data || []).map((l: any) => l.post_id)
      );

      return (postsRes.data as any[]).map((x) => ({
        ...x,
        liked_by_me: likedSet.has(x.id),
      }));
    },
    [user]
  );

  // ── Initial feed load ────────────────────────────────────────────────────────
  const load = useCallback(async () => {
    // Show cached data immediately while re-fetching fresh data
    const cached = queryClient.getQueryData<Post[]>(FEED_QUERY_KEY);
    if (cached && cached.length > 0) {
      setPosts(cached);
      setLoading(false);
    } else {
      setLoading(true);
    }

    try {
      // 1. Fetch followed-user IDs
      let followedSet = new Set<string>();
      if (user) {
        const { data: followRows } = await supabase
          .from("follows")
          .select("following_id")
          .eq("follower_id", user.id);
        if (followRows) {
          followedSet = new Set(followRows.map((f) => f.following_id));
          setFollowingUserIds(followedSet);
        }
      }

      // 2. Fetch stories asynchronously (non-blocking)
      setStoriesLoading(true);
      supabase
        .from("stories")
        .select(
          "id,user_id,image_url,is_sponsored,profiles!stories_user_id_fkey(display_name,photo_url,username,is_verified,profile_theme)"
        )
        .gt("expires_at", new Date().toISOString())
        .order("created_at", { ascending: false })
        .limit(30)
        .then(({ data }) => {
          if (data) setStories(data as any);
          setStoriesLoading(false);
        });

      // 3. Try server-side personalised feed RPC first
      let rawPosts: Post[] = [];
      let usedRpc = false;

      if (user) {
        try {
          const { data: rpcData, error: rpcErr } = await supabase.rpc(
            "get_personalized_feed",
            { p_user_id: user.id, p_limit: 20, p_offset: 0 }
          );
          if (!rpcErr && rpcData && Array.isArray(rpcData)) {
            const { data: likeRows } = await supabase
              .from("post_likes")
              .select("post_id")
              .eq("user_id", user.id);
            const likedSet = new Set((likeRows || []).map((l) => l.post_id));
            rawPosts = (rpcData as any[]).map((x: any) => ({
              ...x,
              liked_by_me: likedSet.has(x.id),
            }));
            usedRpc = true;
          }
        } catch {
          // RPC doesn't exist yet — fall through to client-side
        }
      }

      if (!usedRpc) {
        rawPosts = await fetchPostsClientSide(followedSet);
      }

      const ranked = rankPosts(rawPosts, followedSet);
      setPosts(ranked);
      queryClient.setQueryData(FEED_QUERY_KEY, ranked);
      setHasNextPage(rawPosts.length >= 20);

      if (ranked.length > 0) {
        lastFeedTimestampRef.current = ranked[0].created_at;
        cursorRef.current = {
          lastPostId: ranked[ranked.length - 1].id,
          lastCreatedAt: ranked[ranked.length - 1].created_at,
        };
      }

      // Mark loaded posts as seen (fire-and-forget)
      markPostsSeen(ranked.map((p) => p.id));
    } catch (err) {
      console.error("[Feed] Load error:", err);
    } finally {
      setDisplayCount(CHUNK_SIZE);
      setNewPostsCount(0);
      setLoading(false);
    }
  }, [user, queryClient, rankPosts, fetchPostsClientSide, markPostsSeen]);

  useEffect(() => {
    load();
  }, [load]);

  // ── Realtime: new inserts / like-count updates ───────────────────────────────
  useEffect(() => {
    const channel = createRealtimeChannel(`feed-posts-${user?.id || "anon"}`);
    channel
      .on("postgres_changes", { event: "INSERT", schema: "public", table: "posts" }, () => {
        if (lastFeedTimestampRef.current) {
          setNewPostsCount((prev) => prev + 1);
        }
      })
      .on("postgres_changes", { event: "UPDATE", schema: "public", table: "posts" }, (payload) => {
        const { new: newRecord } = payload;
        setPosts((prev) =>
          prev.map((p) =>
            p.id === newRecord.id && newRecord.likes_count !== undefined
              ? { ...p, likes_count: newRecord.likes_count }
              : p
          )
        );
      })
      .subscribe();

    return () => {
      supabase.removeChannel(channel);
    };
  }, [user?.id]);

  // ── Scroll-to-top button visibility ─────────────────────────────────────────
  useEffect(() => {
    const handleScroll = () => setShowScrollTop(window.scrollY > 400);
    window.addEventListener("scroll", handleScroll, { passive: true });
    return () => window.removeEventListener("scroll", handleScroll);
  }, []);

  const scrollToTop = useCallback(() => {
    window.scrollTo({ top: 0, behavior: "smooth" });
  }, []);

  // ── Load new realtime posts ──────────────────────────────────────────────────
  const loadNewPosts = useCallback(async () => {
    if (!lastFeedTimestampRef.current) return;
    const { data: newPosts } = await supabase
      .from("posts")
      .select(
        "*, profiles!posts_user_id_fkey(display_name,photo_url,username,is_verified,profile_theme)"
      )
      .gt("created_at", lastFeedTimestampRef.current)
      .order("created_at", { ascending: false });

    if (!newPosts?.length) return;

    let enriched: Post[] = newPosts as any[];
    if (user) {
      const { data: likes } = await supabase
        .from("post_likes")
        .select("post_id")
        .eq("user_id", user.id);
      const likedSet = new Set((likes || []).map((l) => l.post_id));
      enriched = (newPosts as any[]).map((x) => ({
        ...x,
        liked_by_me: likedSet.has(x.id),
      }));
    }

    setPosts((prev) => {
      const ranked = rankPosts([...enriched, ...prev], followingUserIds);
      queryClient.setQueryData(FEED_QUERY_KEY, ranked);
      return ranked;
    });
    setDisplayCount(CHUNK_SIZE);
    setNewPostsCount(0);
    if (newPosts.length > 0) {
      lastFeedTimestampRef.current = newPosts[0].created_at;
    }
    markPostsSeen(enriched.map((p) => p.id));
  }, [user, rankPosts, followingUserIds, queryClient, markPostsSeen]);

  // ── Cursor-based "load more" ─────────────────────────────────────────────────
  const loadMore = useCallback(async () => {
    if (loadingMore || !hasNextPage) return;

    // If we still have posts in local buffer, just reveal the next chunk
    const filtered =
      feedMode === "following"
        ? posts.filter((p) => p.user_id && followingUserIds.has(p.user_id))
        : posts;

    if (displayCount < filtered.length) {
      setDisplayCount((prev) => Math.min(prev + CHUNK_SIZE, filtered.length));
      return;
    }

    // Fetch the next page from the server using cursor
    if (!cursorRef.current) return;
    setLoadingMore(true);

    try {
      const cursor = cursorRef.current;
      let nextPosts: Post[] = [];
      let usedRpc = false;

      if (user) {
        try {
          const { data: rpcData, error: rpcErr } = await (supabase.rpc as any)(
            "get_personalized_feed",
            {
              p_user_id: user.id,
              p_limit: 20,
              p_cursor_post_id: cursor.lastPostId,
              p_cursor_created_at: cursor.lastCreatedAt,
            }
          );
          if (!rpcErr && rpcData && Array.isArray(rpcData)) {
            const { data: likeRows } = await supabase
              .from("post_likes")
              .select("post_id")
              .eq("user_id", user.id);
            const likedSet = new Set((likeRows || []).map((l: any) => l.post_id));
            nextPosts = (rpcData as any[]).map((x: any) => ({
              ...x,
              liked_by_me: likedSet.has(x.id),
            }));
            usedRpc = true;
          }
        } catch {
          /* fall through to client-side */
        }
      }

      if (!usedRpc) {
        nextPosts = await fetchPostsClientSide(followingUserIds, cursor);
      }

      if (nextPosts.length === 0) {
        setHasNextPage(false);
        return;
      }

      // Deduplicate by id before merging
      const existingIds = new Set(posts.map((p) => p.id));
      const fresh = nextPosts.filter((p) => !existingIds.has(p.id));

      if (fresh.length === 0) {
        setHasNextPage(false);
        return;
      }

      const merged = [...posts, ...fresh];
      setPosts(merged);
      queryClient.setQueryData(FEED_QUERY_KEY, merged);
      setDisplayCount((prev) => prev + CHUNK_SIZE);
      setHasNextPage(fresh.length >= 20);

      const lastPost = fresh[fresh.length - 1];
      cursorRef.current = {
        lastPostId: lastPost.id,
        lastCreatedAt: lastPost.created_at,
      };

      markPostsSeen(fresh.map((p) => p.id));
    } catch (err) {
      console.error("[Feed] loadMore error:", err);
    } finally {
      setLoadingMore(false);
    }
  }, [
    loadingMore,
    hasNextPage,
    displayCount,
    feedMode,
    posts,
    followingUserIds,
    user,
    queryClient,
    fetchPostsClientSide,
    markPostsSeen,
  ]);

  // ── IntersectionObserver — sentinel drives pagination ────────────────────────
  useEffect(() => {
    if (!sentinelRef.current || loading) return;
    const observer = new IntersectionObserver(
      (entries) => {
        if (entries[0].isIntersecting) loadMore();
      },
      { rootMargin: "400px" }
    );
    observer.observe(sentinelRef.current);
    return () => observer.disconnect();
  }, [loading, loadMore]);

  // ── Prefetch next page silently when 80% of buffer is displayed ───────────────
  useEffect(() => {
    const filtered =
      feedMode === "following"
        ? posts.filter((p) => p.user_id && followingUserIds.has(p.user_id))
        : posts;

    const threshold = filtered.length * 0.8;
    if (
      displayCount >= threshold &&
      hasNextPage &&
      !loadingMore &&
      !prefetchingRef.current &&
      cursorRef.current
    ) {
      prefetchingRef.current = true;
      const cursor = cursorRef.current;

      fetchPostsClientSide(followingUserIds, cursor)
        .then((nextPosts) => {
          if (nextPosts.length === 0) {
            setHasNextPage(false);
            return;
          }
          const existingIds = new Set(posts.map((p) => p.id));
          const fresh = nextPosts.filter((p) => !existingIds.has(p.id));
          if (fresh.length > 0) {
            const merged = [...posts, ...fresh];
            setPosts(merged);
            queryClient.setQueryData(FEED_QUERY_KEY, merged);
            const lastPost = fresh[fresh.length - 1];
            cursorRef.current = {
              lastPostId: lastPost.id,
              lastCreatedAt: lastPost.created_at,
            };
            setHasNextPage(fresh.length >= 20);
          }
        })
        .catch(() => {/* silently ignore prefetch errors */})
        .finally(() => {
          prefetchingRef.current = false;
        });
    }
  }, [
    displayCount,
    posts,
    followingUserIds,
    feedMode,
    hasNextPage,
    loadingMore,
    fetchPostsClientSide,
    queryClient,
  ]);

  // ── View tracking via IntersectionObserver ────────────────────────────────────
  useEffect(() => {
    if (!user || loading) return;

    // Map from observed element → post id
    const observedEls = new Map<Element, string>();

    const observer = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          const postId = observedEls.get(entry.target);
          if (!postId) return;

          if (entry.isIntersecting) {
            // Skip if already viewed this session
            if (viewedPostsRef.current.has(postId)) return;

            const timer = setTimeout(() => {
              if (!viewedPostsRef.current.has(postId)) {
                viewedPostsRef.current.add(postId);
                // Fire-and-forget view RPC
                supabase
                  .rpc("record_post_view", {
                    p_post_id: postId,
                    p_view_duration_ms: VIEW_THRESHOLD_MS,
                  })
                  .then()
                  .catch(() => {/* RPC may not exist yet */});
              }
              viewTimersRef.current.delete(postId);
            }, VIEW_THRESHOLD_MS);

            viewTimersRef.current.set(postId, timer);
          } else {
            // Post left viewport before threshold — cancel the timer
            const existingTimer = viewTimersRef.current.get(postId);
            if (existingTimer) {
              clearTimeout(existingTimer);
              viewTimersRef.current.delete(postId);
            }
          }
        });
      },
      { threshold: 0.5 }
    );

    // Observe all [data-post-id] elements in the DOM
    document.querySelectorAll("[data-post-id]").forEach((el) => {
      const postId = el.getAttribute("data-post-id");
      if (postId) {
        observedEls.set(el, postId);
        observer.observe(el);
      }
    });

    return () => {
      observer.disconnect();
      // Clear all pending view timers on cleanup
      viewTimersRef.current.forEach((timer) => clearTimeout(timer));
      viewTimersRef.current.clear();
    };
  }, [user, loading, displayCount, feedMode]);

  // ── Toggle like (optimistic) ─────────────────────────────────────────────────
  const handleToggleLike = useCallback(
    (post: Post) => {
      if (!user) return;
      const wasLiked = !!post.liked_by_me;
      setPosts((prev) =>
        prev.map((x) =>
          x.id === post.id
            ? {
                ...x,
                liked_by_me: !wasLiked,
                likes_count: wasLiked
                  ? Math.max(0, (x.likes_count || 0) - 1)
                  : (x.likes_count || 0) + 1,
              }
            : x
        )
      );
      toggleLike(post.id, wasLiked);
    },
    [user, toggleLike]
  );

  // ── Filtered posts for the active tab ────────────────────────────────────────
  const displayedPosts = useMemo(() => {
    if (feedMode === "following") {
      return posts.filter((p) => p.user_id && followingUserIds.has(p.user_id));
    }
    return posts;
  }, [feedMode, posts, followingUserIds]);

  // Deduplicate stories: one entry per user
  const storyGroups = useMemo(
    () =>
      Array.from(
        stories
          .reduce((map, s) => {
            if (!map.has(s.user_id)) map.set(s.user_id, s);
            return map;
          }, new Map<string, Story>())
          .values()
      ),
    [stories]
  );

  // ── Render ───────────────────────────────────────────────────────────────────
  return (
    <AppLayout>
      <div className="w-full space-y-6 pb-8">

        {/* ── Feed Mode Tabs (Para Você / Seguindo) ───────────────────────── */}
        <div className="sticky top-0 z-20 bg-[#070C1A]/90 backdrop-blur-2xl border-b border-white/[0.06] -mx-4 px-4 sm:mx-0 sm:px-0 sm:rounded-2xl pt-2 pb-0 flex items-center justify-center">
          <div className="relative flex items-center gap-1 bg-white/[0.04] rounded-full p-1">
            {/* Sliding pill indicator */}
            <motion.div
              layout
              transition={{ type: "spring", stiffness: 380, damping: 32 }}
              className={cn(
                "absolute inset-y-1 rounded-full bg-sky-600 shadow-lg shadow-sky-600/30",
                feedMode === "for-you"
                  ? "left-1 right-[calc(50%+2px)]"
                  : "left-[calc(50%+2px)] right-1"
              )}
            />

            <button
              onClick={() => setFeedMode("for-you")}
              className={cn(
                "relative z-10 px-5 py-2 rounded-full text-xs font-bold transition-colors flex items-center gap-1.5 min-w-[108px] justify-center min-h-[44px]",
                feedMode === "for-you" ? "text-white" : "text-slate-400 hover:text-white"
              )}
            >
              <Sparkles className="w-3.5 h-3.5" />
              Para Você
            </button>

            <button
              onClick={() => setFeedMode("following")}
              className={cn(
                "relative z-10 px-5 py-2 rounded-full text-xs font-bold transition-colors flex items-center gap-1.5 min-w-[108px] justify-center min-h-[44px]",
                feedMode === "following" ? "text-white" : "text-slate-400 hover:text-white"
              )}
            >
              <Users className="w-3.5 h-3.5" />
              Seguindo
              {followingUserIds.size > 0 && (
                <span className="text-[10px] opacity-75 font-mono tabular-nums">
                  ({followingUserIds.size})
                </span>
              )}
            </button>
          </div>

          {/* Bottom accent line */}
          <div className="absolute bottom-0 left-1/2 -translate-x-1/2 w-10 h-0.5 rounded-full bg-sky-500/60" />
        </div>

        {/* ── Stories Horizontal Bar ──────────────────────────────────────── */}
        <div className="space-y-2.5">
          <div className="flex items-center justify-between px-1">
            <h2 className="text-xs font-bold text-slate-400 tracking-wider uppercase flex items-center gap-2">
              <span className="w-1.5 h-4 rounded-full bg-sky-400" />
              Stories
            </h2>
            <button
              onClick={() => navigate("/create-story")}
              className="text-xs font-bold text-sky-400 hover:text-sky-300 transition-colors flex items-center gap-1 min-h-[44px]"
            >
              Criar <ChevronRight className="w-3.5 h-3.5" />
            </button>
          </div>

          {/* Scroll row with left/right edge-fade indicators */}
          <div className="relative -mx-4 sm:-mx-0">
            {/* Left fade */}
            <div className="absolute left-0 top-0 bottom-2 w-8 bg-gradient-to-r from-[#090D16] to-transparent z-10 pointer-events-none sm:hidden" />
            {/* Right fade */}
            <div className="absolute right-0 top-0 bottom-2 w-10 bg-gradient-to-l from-[#090D16] to-transparent z-10 pointer-events-none" />

            <div
              ref={storyScrollRef}
              className="flex gap-3 overflow-x-auto pb-2 px-4 sm:px-0 scrollbar-hide select-none"
            >
              {/* Create Story button */}
              <motion.button
                whileTap={{ scale: 0.94 }}
                onClick={() => navigate("/create-story")}
                className="flex flex-col items-center gap-1.5 shrink-0 group min-h-[44px]"
              >
                <div className="relative w-16 h-16 rounded-full p-0.5 bg-gradient-to-tr from-sky-500 to-blue-600 shadow-md">
                  <div className="w-full h-full rounded-full bg-slate-950 flex items-center justify-center overflow-hidden">
                    {user?.user_metadata?.avatar_url ? (
                      <img
                        src={user.user_metadata.avatar_url}
                        alt="Seu avatar"
                        className="w-full h-full object-cover opacity-80 group-hover:opacity-100 transition-opacity"
                      />
                    ) : (
                      <BrandLogo size={28} />
                    )}
                  </div>
                  <span className="absolute bottom-0 right-0 w-5 h-5 rounded-full bg-sky-500 text-white flex items-center justify-center ring-2 ring-slate-950 shadow-sm">
                    <Plus className="w-3.5 h-3.5 stroke-[3px]" />
                  </span>
                </div>
                <span className="text-[11px] text-slate-300 font-semibold truncate max-w-[64px]">
                  Seu story
                </span>
              </motion.button>

              {/* Story cards or skeletons */}
              {storiesLoading ? (
                [1, 2, 3, 4].map((i) => <StorySkeleton key={i} />)
              ) : (
                storyGroups.map((s) => (
                  <StoryCard
                    key={s.user_id}
                    user_id={s.user_id}
                    profiles={s.profiles}
                    is_sponsored={s.is_sponsored}
                  />
                ))
              )}
            </div>
          </div>
        </div>

        {/* ── Realtime New Posts Floating Pill ────────────────────────────── */}
        <AnimatePresence>
          {newPostsCount > 0 && (
            <motion.div
              initial={{ opacity: 0, y: -20 }}
              animate={{ opacity: 1, y: 0 }}
              exit={{ opacity: 0, y: -20 }}
              className="sticky top-14 z-30 flex justify-center pointer-events-none"
            >
              <button
                onClick={() => {
                  loadNewPosts();
                  scrollToTop();
                }}
                className="pointer-events-auto flex items-center gap-2 px-5 py-2.5 rounded-full bg-sky-600 hover:bg-sky-500 text-white text-xs font-bold shadow-xl shadow-sky-600/40 transition-all active:scale-95"
              >
                <RefreshCw className="w-3.5 h-3.5 animate-spin" />
                {newPostsCount} nova{newPostsCount > 1 ? "s" : ""} publicação
                {newPostsCount > 1 ? "ões" : ""}
                <ArrowUp className="w-3.5 h-3.5" />
              </button>
            </motion.div>
          )}
        </AnimatePresence>

        {/* ── Posts Feed List ─────────────────────────────────────────────── */}
        {loading ? (
          // 5 shimmer skeleton cards
          <div className="space-y-6">
            {[1, 2, 3, 4, 5].map((i) => (
              <FeedPostSkeleton key={i} />
            ))}
          </div>
        ) : displayedPosts.length === 0 ? (
          /* ── Improved animated empty state ── */
          <motion.div
            initial={{ opacity: 0, y: 16 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ type: "spring", stiffness: 280, damping: 24 }}
            className="py-20 space-y-6 text-center"
          >
            <motion.div
              animate={{ scale: [1, 1.08, 1], rotate: [0, -8, 8, 0] }}
              transition={{ duration: 3, repeat: Infinity, ease: "easeInOut" }}
              className="w-20 h-20 mx-auto rounded-3xl bg-slate-900/80 border border-white/[0.08] flex items-center justify-center text-sky-400 shadow-xl shadow-sky-500/10"
            >
              {feedMode === "following" ? (
                <Users className="w-9 h-9" />
              ) : (
                <Sparkles className="w-9 h-9" />
              )}
            </motion.div>

            <div>
              <p className="text-lg font-bold text-white">
                {feedMode === "following"
                  ? "Nenhuma publicação dos que você segue"
                  : "Tudo pronto para decolar 🚀"}
              </p>
              <p className="text-xs text-slate-400 mt-2 max-w-xs mx-auto leading-relaxed">
                {feedMode === "following"
                  ? "Siga criadores na aba Comunidade para ver suas postagens aqui!"
                  : "Seja o primeiro a compartilhar uma foto ou vídeo com a comunidade!"}
              </p>
            </div>

            <div className="flex gap-2 justify-center flex-wrap">
              {feedMode === "following" ? (
                <button
                  onClick={() => navigate("/community")}
                  className="px-6 py-2.5 rounded-full bg-sky-600 hover:bg-sky-500 text-white text-xs font-bold transition-all shadow-md shadow-sky-600/30 min-h-[44px]"
                >
                  Explorar Criadores
                </button>
              ) : (
                <>
                  <button
                    onClick={() => navigate("/create-post")}
                    className="px-6 py-2.5 rounded-full bg-sky-600 hover:bg-sky-500 text-white text-xs font-bold transition-all shadow-md shadow-sky-600/30 flex items-center gap-1.5 min-h-[44px]"
                  >
                    <Plus className="w-4 h-4" /> Criar publicação
                  </button>
                  <button
                    onClick={() => navigate("/community")}
                    className="px-6 py-2.5 rounded-full bg-white/[0.06] hover:bg-white/[0.1] border border-white/[0.08] text-white text-xs font-bold transition-all min-h-[44px]"
                  >
                    Explorar Comunidade
                  </button>
                </>
              )}
            </div>
          </motion.div>
        ) : (
          <div className="space-y-7">
            <AnimatePresence mode="popLayout">
              {(() => {
                const visiblePosts = displayedPosts.slice(0, displayCount);
                const items: JSX.Element[] = [];
                const adPositions =
                  visiblePosts.length >= 10
                    ? [3, 7]
                    : visiblePosts.length >= 5
                    ? [Math.floor(visiblePosts.length / 2)]
                    : [];

                visiblePosts.forEach((post, i) => {
                  items.push(
                    <motion.div
                      key={post.id}
                      // data-post-id consumed by view-tracking IntersectionObserver
                      data-post-id={post.id}
                      initial={{ opacity: 0, y: 14 }}
                      animate={{ opacity: 1, y: 0 }}
                      transition={{
                        delay: i * 0.02,
                        type: "spring",
                        stiffness: 320,
                        damping: 26,
                      }}
                      layout
                    >
                      <MemoPostCard
                        {...post}
                        onToggleLike={handleToggleLike}
                        index={i}
                      />
                    </motion.div>
                  );

                  if (adPositions.includes(i)) {
                    items.push(
                      <motion.div
                        key={`ad-${i}`}
                        initial={{ opacity: 0, y: 14 }}
                        animate={{ opacity: 1, y: 0 }}
                        transition={{ delay: (i + 0.5) * 0.02 }}
                      >
                        <AdInFeed />
                      </motion.div>
                    );
                  }
                });

                return items;
              })()}
            </AnimatePresence>

            {/* ── Infinite scroll sentinel ─────────────────────────────── */}
            <div ref={sentinelRef} className="flex items-center justify-center py-6">
              {loadingMore ? (
                <div className="flex items-center gap-2 text-slate-400 text-xs font-semibold">
                  <Loader2 className="w-4 h-4 text-sky-400 animate-spin" />
                  Carregando mais…
                </div>
              ) : !hasNextPage && displayCount >= displayedPosts.length ? (
                <div className="flex flex-col items-center gap-2 text-slate-500 text-xs">
                  <Share2 className="w-5 h-5 opacity-40" />
                  <span>Você viu tudo por enquanto!</span>
                </div>
              ) : null}
            </div>
          </div>
        )}

        {/* ── Scroll-to-top FAB ────────────────────────────────────────────── */}
        <AnimatePresence>
          {showScrollTop && (
            <motion.button
              initial={{ opacity: 0, scale: 0.8 }}
              animate={{ opacity: 1, scale: 1 }}
              exit={{ opacity: 0, scale: 0.8 }}
              onClick={scrollToTop}
              className="fixed bottom-20 right-6 z-40 w-11 h-11 rounded-2xl bg-slate-900/90 border border-white/[0.1] text-sky-400 shadow-2xl flex items-center justify-center hover:bg-slate-800 transition-all active:scale-90"
              aria-label="Voltar ao topo"
            >
              <ArrowUp className="w-5 h-5 stroke-[2.5px]" />
            </motion.button>
          )}
        </AnimatePresence>
      </div>
    </AppLayout>
  );
}