import { useEffect, useMemo, useRef, useState, useCallback, useLayoutEffect, type TouchEvent } from "react";
import { useNavigate, useParams } from "react-router-dom";
import {
  ArrowLeft, Image as ImageIcon, Mic, Send, Phone, Video, StopCircle,
  Smile, Camera, Eye, X, Pencil, Trash2, Check, Plus, ChevronDown, CornerUpLeft,
  UserX, Tag, MoreVertical, ImagePlus, Copy, Heart, CheckCheck, Play, Palette, Sparkles,
  Search, Pin, PinOff, MessageSquare, PanelRight, Loader2, ArrowUp,
} from "lucide-react";
import { supabase, createRealtimeChannel } from "@/integrations/supabase/client";
import { useAuth } from "@/hooks/useAuth";
import { useUserNickname } from "@/hooks/useUserNickname";
import { useBlockUser } from "@/hooks/useBlockUser";
import Avatar from "@/components/Avatar";
import VerifiedBadge from "@/components/VerifiedBadge";
import ViewOnceImage from "@/components/ViewOnceImage";
import CameraCapture from "@/components/CameraCapture";
import StickerPicker from "@/components/StickerPicker";
import MessageReactions, { ReactionPicker } from "@/components/MessageReactions";
import { useReactionsOptimized } from "@/hooks/useReactionsOptimized";
import { useTyping } from "@/hooks/useTyping";
import { formatLastSeen, isOnline } from "@/hooks/usePresence";
import { toast } from "sonner";
import { cn, fileToPng, profilePath, playNotificationSound } from "@/lib/utils";
import { motion, AnimatePresence } from "framer-motion";
import BrandLogo from "@/components/BrandLogo";
import AudioPlayer from "@/components/AudioPlayer";
import { format, isToday, isYesterday } from "date-fns";
import { ptBR } from "date-fns/locale";
import RGBName from "@/components/RGBName";
import ChatMediaViewer from "@/components/ChatMediaViewer";
import { AttachmentMenuPortal } from "@/components/AttachmentMenuPortal";
import { getMessageReads, markMessagesRead } from "@/lib/chunkedQueries";
import { triggerMessagePushNotification, triggerCallPushNotification } from "@/lib/pushNotifications";
import { uploadChatMedia } from "@/lib/r2Storage";
import ChatSearchHeader from "@/components/chat/ChatSearchHeader";
import PinnedMessageBar from "@/components/chat/PinnedMessageBar";
import VoiceRecorderWaveform from "@/components/chat/VoiceRecorderWaveform";
import ChatPasteDropOverlay from "@/components/chat/ChatPasteDropOverlay";
import ChatSidebar from "@/components/chat/ChatSidebar";
import ChatDetailsSidebar from "@/components/chat/ChatDetailsSidebar";
import ChatContextMenu from "@/components/chat/ChatContextMenu";
import ChatDesktopEmptyState from "@/components/chat/ChatDesktopEmptyState";
import { instantCache } from "@/lib/instantCache";

/* ─── types ─────────────────────────────────────────── */
interface Message {
  id: string;
  conversation_id: string;
  sender_id: string;
  type: string;
  content: string | null;
  media_url: string | null;
  sticker_id: string | null;
  duration_seconds: number | null;
  is_view_once?: boolean;
  viewed_at?: string | null;
  viewed_by?: string | null;
  edited_at?: string | null;
  reply_to_message_id?: string;
  created_at: string;
  location_lat?: number;
  location_lng?: number;
}

const EDIT_WINDOW_MS = 5 * 60 * 1000;

const formatDateSeparator = (date: string) => {
  const d = new Date(date);
  if (isToday(d)) return "Hoje";
  if (isYesterday(d)) return "Ontem";
  return format(d, "d 'de' MMMM", { locale: ptBR });
};

/* ─── Componente principal (Instagram Direct Redesign) ─────────────────────── */
export default function Chat() {
  const { id } = useParams();
  const navigate = useNavigate();
  const { user, profile, isAdmin, loading: authLoading } = useAuth();

  // InstantCache synchronous hydration (0ms initial render)
  const cachedMessages = useMemo(() => (id ? instantCache.get<Message[]>(`chat_msgs_v2_${id}`) || [] : []), [id]);
  const cachedOther = useMemo(() => (id ? instantCache.get<any>(`chat_partner_${id}`) || null : null), [id]);
  const cachedBg = useMemo(() => (id ? instantCache.get<any>(`chat_bg_${id}`) || null : null), [id]);

  const [messages, setMessages] = useState<Message[]>(cachedMessages);
  const [text, setText] = useState("");
  const [other, setOther] = useState<any>(cachedOther);
  const [showStickers, setShowStickers] = useState(false);

  const [recording, setRecording] = useState(false);
  const [viewOnceMode, setViewOnceMode] = useState(false);
  const [showAttachMenu, setShowAttachMenu] = useState(false);
  const [replyTo, setReplyTo] = useState<Message | null>(null);
  const [cameraOpen, setCameraOpen] = useState(false);
  const [showJumpToBottom, setShowJumpToBottom] = useState(false);
  const [actionFor, setActionFor] = useState<Message | null>(null);
  const [editingId, setEditingId] = useState<string | null>(null);
  const [editText, setEditText] = useState("");
  const [pressingId, setPressingId] = useState<string | null>(null);
  const [mediaViewer, setMediaViewer] = useState<{ src: string; type: "image" | "video" } | null>(null);
  const [isLoadingOlder, setIsLoadingOlder] = useState(false);
  const [hasMoreOlder, setHasMoreOlder] = useState(false);
  const [isLoadingMessages, setIsLoadingMessages] = useState(cachedMessages.length === 0);
  const [swipeState, setSwipeState] = useState<{ msgId: string; dx: number } | null>(null);
  const [readMessageIds, setReadMessageIds] = useState<Set<string>>(new Set());
  const [bgImage, setBgImage] = useState<string | null>(cachedBg?.image || null);
  const [bgGradient, setBgGradient] = useState<string | null>(cachedBg?.gradient || null);
  const [bgBubbleColor, setBgBubbleColor] = useState(cachedBg?.bubbleColor || "rgba(255,255,255,0.08)");
  const [bgBubbleMineColor, setBgBubbleMineColor] = useState(cachedBg?.bubbleMineColor || "rgba(2,132,199,0.95)");
  const [bgTextColor, setBgTextColor] = useState(cachedBg?.textColor || "#ffffff");

  // Sync cache on conversation change for instant 0ms swap
  useEffect(() => {
    if (!id) return;
    initialScrollDone.current = false;
    userScrolledUp.current = false;
    setShowJumpToBottom(false);
    setHasMoreOlder(false);

    const cm = instantCache.get<Message[]>(`chat_msgs_v2_${id}`);
    const co = instantCache.get<any>(`chat_partner_${id}`);
    const cb = instantCache.get<any>(`chat_bg_${id}`);
    if (cm && cm.length > 0) {
      setMessages(cm);
      setIsLoadingMessages(false);
    } else {
      setMessages([]);
      setIsLoadingMessages(true);
    }
    setOther(co || null);
    if (cb) {
      setBgImage(cb.image || null);
      setBgGradient(cb.gradient || null);
      setBgBubbleColor(cb.bubbleColor || "rgba(255,255,255,0.08)");
      setBgBubbleMineColor(cb.bubbleMineColor || "rgba(2,132,199,0.95)");
      setBgTextColor(cb.textColor || "#ffffff");
    }
  }, [id]);
  const [availableBgs, setAvailableBgs] = useState<any[]>([]);
  const [showBgPicker, setShowBgPicker] = useState(false);
  const [showMobileMenu, setShowMobileMenu] = useState(false);
  const [showNicknameInput, setShowNicknameInput] = useState(false);
  const [nicknameInputVal, setNicknameInputVal] = useState("");
  const [heartAnimId, setHeartAnimId] = useState<string | null>(null);

  const [highlightMsgId, setHighlightMsgId] = useState<string | null>(null);
  const [audioPreview, setAudioPreview] = useState<{ blob: Blob; url: string; duration: number } | null>(null);
  const [deliveredIds, setDeliveredIds] = useState<Set<string>>(new Set());
  const [inputFocused, setInputFocused] = useState(false);

  // In-chat search state
  const [searchOpen, setSearchOpen] = useState(false);
  const [searchQuery, setSearchQuery] = useState("");
  const [searchMatchIndex, setSearchMatchIndex] = useState(0);

  // Pinned message state
  const [pinnedMessageId, setPinnedMessageId] = useState<string | null>(null);

  // Desktop specific states
  const [showDetailsSidebar, setShowDetailsSidebar] = useState(false);
  const [contextMenu, setContextMenu] = useState<{ x: number; y: number; message: Message } | null>(null);
  const textareaRef = useRef<HTMLTextAreaElement>(null);

  // Global desktop keyboard shortcuts (Ctrl+F for search, Esc to close modals)
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "f") {
        e.preventDefault();
        setSearchOpen(true);
      }
      if (e.key === "Escape") {
        if (contextMenu) setContextMenu(null);
        if (searchOpen) setSearchOpen(false);
        if (actionFor) setActionFor(null);
        if (showDetailsSidebar) setShowDetailsSidebar(false);
        if (replyTo) setReplyTo(null);
        if (editingId) setEditingId(null);
      }
    };
    window.addEventListener("keydown", handleKeyDown);
    return () => window.removeEventListener("keydown", handleKeyDown);
  }, [contextMenu, searchOpen, actionFor, showDetailsSidebar, replyTo, editingId]);

  const deliveredTimersRef = useRef<Map<string, ReturnType<typeof setTimeout>>>(new Map());
  const lastClickTime = useRef<Map<string, number>>(new Map());
  const recorderRef = useRef<MediaRecorder | null>(null);
  const chunksRef = useRef<Blob[]>([]);
  const startedAtRef = useRef<number>(0);
  const scrollRef = useRef<HTMLDivElement>(null);
  const bottomAnchorRef = useRef<HTMLDivElement>(null);
  const messagesInnerRef = useRef<HTMLDivElement>(null);
  const fileInputRef = useRef<HTMLInputElement>(null);
  const longPressTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
  const attachButtonRef = useRef<HTMLButtonElement>(null);
  const swipeStartXRef = useRef<number>(0);
  const SWIPE_THRESHOLD = 60;
  const initialScrollDone = useRef(false);
  const userScrolledUp = useRef(false);
  const msgsLenRef = useRef(0);

  const otherId = other?.id;
  const { nickname: otherNickname, setNickname: setNicknameForUser } = useUserNickname(otherId);
  const { blockUser } = useBlockUser();

  const messageIds = useMemo(() => messages.map((m) => m.id), [messages]);
  const { getReactions, toggleReaction, reload: reloadReactions } = useReactionsOptimized(messageIds);
  const { isTyping: isOtherTyping, sendTyping } = useTyping(id, other?.id);

  const onlineNow = useMemo(() => isOnline(other?.last_seen_at || other?.last_seen), [other?.last_seen_at, other?.last_seen]);
  const presenceLabel = useMemo(() => formatLastSeen(other?.last_seen_at || other?.last_seen), [other?.last_seen_at, other?.last_seen]);

  const messageById = useMemo(() => {
    const map = new Map<string, Message>();
    for (const m of messages) map.set(m.id, m);
    return map;
  }, [messages]);

  // Jump to specific message with highlight animation
  const jumpToMessage = useCallback((msgId: string) => {
    const el = document.querySelector(`[data-message-id="${msgId}"]`);
    if (el) {
      el.scrollIntoView({ behavior: "smooth", block: "center" });
      setHighlightMsgId(msgId);
      setTimeout(() => setHighlightMsgId(null), 2500);
    } else {
      toast.info("Mensagem não encontrada no histórico carregado");
    }
  }, []);

  // Search matches computed
  const searchMatches = useMemo(() => {
    if (!searchQuery.trim()) return [];
    const q = searchQuery.toLowerCase();
    return messages.filter((m) => m.content && m.content.toLowerCase().includes(q));
  }, [messages, searchQuery]);

  const handleSearchNext = useCallback(() => {
    if (searchMatches.length === 0) return;
    const nextIdx = (searchMatchIndex + 1) % searchMatches.length;
    setSearchMatchIndex(nextIdx);
    jumpToMessage(searchMatches[nextIdx].id);
  }, [searchMatches, searchMatchIndex, jumpToMessage]);

  const handleSearchPrev = useCallback(() => {
    if (searchMatches.length === 0) return;
    const prevIdx = (searchMatchIndex - 1 + searchMatches.length) % searchMatches.length;
    setSearchMatchIndex(prevIdx);
    jumpToMessage(searchMatches[prevIdx].id);
  }, [searchMatches, searchMatchIndex, jumpToMessage]);

  useEffect(() => {
    setSearchMatchIndex(0);
    if (searchMatches.length > 0) {
      jumpToMessage(searchMatches[0].id);
    }
  }, [searchQuery]);

  // Pinned message memo & handlers
  const pinnedMessage = useMemo(() => {
    if (!pinnedMessageId) return null;
    return messageById.get(pinnedMessageId) || null;
  }, [pinnedMessageId, messageById]);

  const handleUnpinMessage = async () => {
    if (!id) return;
    const { error } = await supabase.from("conversations").update({ pinned_message_id: null }).eq("id", id);
    if (error) {
      toast.error("Erro ao desfixar");
    } else {
      setPinnedMessageId(null);
      toast.success("Mensagem desfixada");
    }
  };

  const handlePinMessage = async (m: Message) => {
    if (!id) return;
    setActionFor(null);
    const { error } = await supabase.from("conversations").update({ pinned_message_id: m.id }).eq("id", id);
    if (error) {
      toast.error("Erro ao fixar mensagem");
    } else {
      setPinnedMessageId(m.id);
      toast.success("Mensagem fixada no topo!");
    }
  };

  // ── Scroll Helpers & Pagination ──────────────────────────────────────────────
  const scrollToBottom = useCallback((smooth = false) => {
    if (bottomAnchorRef.current) {
      bottomAnchorRef.current.scrollIntoView({ behavior: smooth ? "smooth" : "auto", block: "end" });
    } else if (scrollRef.current) {
      const el = scrollRef.current;
      if (smooth) {
        el.scrollTo({ top: el.scrollHeight, behavior: "smooth" });
      } else {
        el.scrollTop = el.scrollHeight;
      }
    }
  }, []);

  const loadOlderMessages = useCallback(async () => {
    if (!id || isLoadingOlder || !hasMoreOlder || messages.length === 0) return;
    const oldestMsg = messages[0];
    if (!oldestMsg) return;

    setIsLoadingOlder(true);
    const container = scrollRef.current;
    const prevHeight = container ? container.scrollHeight : 0;
    const prevTop = container ? container.scrollTop : 0;

    try {
      const { data: olderData, error } = await supabase
        .from("messages")
        .select("*")
        .eq("conversation_id", id)
        .lt("created_at", oldestMsg.created_at)
        .order("created_at", { ascending: false })
        .limit(60);

      if (error) throw error;

      if (olderData && olderData.length > 0) {
        const chronOlder = (olderData as Message[]).slice().reverse();
        setMessages((prev) => [...chronOlder, ...prev]);
        if (olderData.length < 60) {
          setHasMoreOlder(false);
        }

        // Maintain viewport position so newly loaded messages smoothly appear on top
        requestAnimationFrame(() => {
          if (scrollRef.current) {
            const newHeight = scrollRef.current.scrollHeight;
            scrollRef.current.scrollTop = newHeight - prevHeight + prevTop;
          }
        });
      } else {
        setHasMoreOlder(false);
      }
    } catch (err) {
      console.error("[Chat] Error loading older messages:", err);
    } finally {
      setIsLoadingOlder(false);
    }
  }, [id, isLoadingOlder, hasMoreOlder, messages]);

  const handleScroll = useCallback(() => {
    if (!scrollRef.current) return;
    const { scrollTop, scrollHeight, clientHeight } = scrollRef.current;
    const distanceFromBottom = scrollHeight - scrollTop - clientHeight;

    const isUp = distanceFromBottom > 120;
    userScrolledUp.current = isUp;
    setShowJumpToBottom(isUp);

    // Auto load older messages when user scrolls near top
    if (scrollTop < 80 && hasMoreOlder && !isLoadingOlder) {
      loadOlderMessages();
    }
  }, [hasMoreOlder, isLoadingOlder, loadOlderMessages]);

  // ── Read Receipts ───────────────────────────────────────────────────────────
  const markVisibleAsRead = useCallback(async () => {
    if (!user || !id || messages.length === 0) return;
    const unread = messages.filter((m) => m.sender_id !== user.id && !readMessageIds.has(m.id));
    if (unread.length === 0) return;

    const unreadIds = unread.map((m) => m.id);
    try {
      await markMessagesRead(id, user.id, unreadIds);
      setReadMessageIds((prev) => {
        const next = new Set(prev);
        for (const mid of unreadIds) next.add(mid);
        return next;
      });
    } catch (e) {
      console.warn("[Chat] Error marking messages read:", e);
    }
  }, [user, id, messages, readMessageIds]);

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

  // ── Mobile Keyboard Avoidance (PWA / iOS / Android visualViewport) ──────────
  useEffect(() => {
    if (typeof window === "undefined") return;
    const vv = window.visualViewport;
    if (!vv) return;

    const updateLayout = () => {
      const keyboardH = Math.max(0, window.innerHeight - vv.height - vv.offsetTop);
      document.documentElement.style.setProperty("--keyboard-height", `${keyboardH}px`);
    };

    vv.addEventListener("resize", updateLayout);
    vv.addEventListener("scroll", updateLayout);
    updateLayout();

    return () => {
      vv.removeEventListener("resize", updateLayout);
      vv.removeEventListener("scroll", updateLayout);
      document.documentElement.style.removeProperty("--keyboard-height");
    };
  }, []);

  // ── Load Conversation & Partner ─────────────────────────────────────────────
  useEffect(() => {
    if (!id || !user) return;
    let isSubscribed = true;

    const loadConv = async () => {
      // Keep showing cached messages if available, only set loading if empty
      const hasCachedMsgs = instantCache.get<Message[]>(`chat_msgs_v2_${id}`);
      if (!hasCachedMsgs || hasCachedMsgs.length === 0) {
        setIsLoadingMessages(true);
      }

      try {
        // Stage 1: Load participants, background, conversation metadata, and recent messages in parallel!
        const [partsRes, bgRes, convRes, msgRes] = await Promise.all([
          supabase
            .from("conversation_participants")
            .select("user_id")
            .eq("conversation_id", id),
          supabase
            .from("conversation_backgrounds")
            .select("*, chat_backgrounds(*)")
            .eq("conversation_id", id)
            .maybeSingle(),
          supabase
            .from("conversations")
            .select("id, pinned_message_id")
            .eq("id", id)
            .maybeSingle(),
          supabase
            .from("messages")
            .select("*")
            .eq("conversation_id", id)
            .order("created_at", { ascending: false })
            .limit(100),
        ]);

        if (!isSubscribed) return;

        // Process Background
        const bgData = bgRes.data;
        if (bgData) {
          let bgObj: any = {};
          if (bgData.chat_backgrounds) {
            bgObj = {
              image: bgData.chat_backgrounds.image_url || null,
              gradient: bgData.chat_backgrounds.gradient_css || null,
              bubbleColor: bgData.chat_backgrounds.chat_bubble_color || "rgba(255,255,255,0.08)",
              bubbleMineColor: bgData.chat_backgrounds.chat_bubble_mine_color || "rgba(2,132,199,0.95)",
              textColor: bgData.chat_backgrounds.chat_text_color || "#ffffff",
            };
          } else if (bgData.custom_image_url) {
            bgObj = { image: bgData.custom_image_url, gradient: null, bubbleColor: "rgba(255,255,255,0.08)", bubbleMineColor: "rgba(2,132,199,0.95)", textColor: "#ffffff" };
          } else if (bgData.custom_gradient) {
            bgObj = { image: null, gradient: bgData.custom_gradient, bubbleColor: "rgba(255,255,255,0.08)", bubbleMineColor: "rgba(2,132,199,0.95)", textColor: "#ffffff" };
          }
          setBgImage(bgObj.image || null);
          setBgGradient(bgObj.gradient || null);
          setBgBubbleColor(bgObj.bubbleColor || "rgba(255,255,255,0.08)");
          setBgBubbleMineColor(bgObj.bubbleMineColor || "rgba(2,132,199,0.95)");
          setBgTextColor(bgObj.textColor || "#ffffff");
          instantCache.set(`chat_bg_${id}`, bgObj, 30 * 60 * 1000);
        }

        // Process Conversation Metadata
        if (convRes.data?.pinned_message_id) {
          setPinnedMessageId(convRes.data.pinned_message_id);
        }

        // Process Messages (100 most recent reversed into chronological order)
        const rawMsgs = msgRes.data;
        if (rawMsgs) {
          const chronMsgs = (rawMsgs as Message[]).slice().reverse();
          setMessages(chronMsgs);
          msgsLenRef.current = chronMsgs.length;
          setHasMoreOlder(rawMsgs.length >= 100);
          instantCache.set(`chat_msgs_v2_${id}`, chronMsgs, 15 * 60 * 1000);
        }

        // Stage 2: Partner Profile & Message Reads in Parallel
        const otherPart = (partsRes.data || []).find((p: any) => p.user_id !== user.id);
        const targetId = otherPart?.user_id;

        const profPromise = targetId
          ? supabase
              .from("profiles")
              .select("id, display_name, username, photo_url, is_verified, last_seen_at, profile_theme")
              .eq("id", targetId)
              .maybeSingle()
          : Promise.resolve({ data: null });

        const mids = (rawMsgs || []).map((m: any) => m.id);
        const readsPromise = mids.length > 0
          ? getMessageReads(supabase, user.id, mids)
          : Promise.resolve([]);

        const [profRes, reads] = await Promise.all([profPromise, readsPromise]);

        if (isSubscribed) {
          if (profRes.data) {
            setOther(profRes.data);
            instantCache.set(`chat_partner_${id}`, profRes.data, 15 * 60 * 1000);
          }
          if (reads.length > 0) {
            setReadMessageIds(new Set(reads));
          }
        }
      } catch (err) {
        console.error("[Chat] Error loading conversation:", err);
      } finally {
        if (isSubscribed) setIsLoadingMessages(false);
      }
    };

    loadConv();

    return () => {
      isSubscribed = false;
    };
  }, [id, user]);

  // ── Instant Synchronous Pre-Paint Bottom Anchoring (0ms) ───────────────────
  useLayoutEffect(() => {
    if (!scrollRef.current) return;
    if (!userScrolledUp.current) {
      scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
    }
  }, [id, messages.length]);

  // Keep bottom anchored if media or fonts cause messages to expand
  useEffect(() => {
    const target = messagesInnerRef.current;
    if (!target) return;

    const observer = new ResizeObserver(() => {
      if (!userScrolledUp.current && scrollRef.current) {
        scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
      }
    });

    observer.observe(target);
    return () => observer.disconnect();
  }, []);

  // ── Realtime Messages Listener ──────────────────────────────────────────────
  useEffect(() => {
    if (!id || !user) return;
    const channel = createRealtimeChannel(`chat-messages-${id}`);

    channel
      .on("postgres_changes", { event: "INSERT", schema: "public", table: "messages", filter: `conversation_id=eq.${id}` }, (payload) => {
        const newMsg = payload.new as Message;
        setMessages((prev) => {
          if (prev.some((m) => m.id === newMsg.id)) return prev;
          return [...prev, newMsg];
        });

        if (newMsg.sender_id !== user.id) {
          playNotificationSound();
          markVisibleAsRead();
        }

        if (!userScrolledUp.current) {
          requestAnimationFrame(() => scrollToBottom(false));
        } else {
          setShowJumpToBottom(true);
        }
      })
      .on("postgres_changes", { event: "UPDATE", schema: "public", table: "messages", filter: `conversation_id=eq.${id}` }, (payload) => {
        const updated = payload.new as Message;
        setMessages((prev) => prev.map((m) => (m.id === updated.id ? updated : m)));
      })
      .on("postgres_changes", { event: "DELETE", schema: "public", table: "messages", filter: `conversation_id=eq.${id}` }, (payload) => {
        const deletedId = (payload.old as any).id;
        setMessages((prev) => prev.filter((m) => m.id !== deletedId));
      })
      .on("postgres_changes", { event: "UPDATE", schema: "public", table: "conversations", filter: `id=eq.${id}` }, (payload) => {
        const updated = payload.new as any;
        if (updated) {
          setPinnedMessageId(updated.pinned_message_id || null);
        }
      })
      .subscribe();

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

  // ── Actions ─────────────────────────────────────────────────────────────────
  const send = async (overrides?: Partial<Message>) => {
    if (!user || !id) return;
    const tempId = crypto.randomUUID();
    const payload: any = {
      id: tempId,
      conversation_id: id,
      sender_id: user.id,
      type: "text",
      content: text.trim() || null,
      ...overrides,
    };

    if (replyTo) payload.reply_to_message_id = replyTo.id;
    if (payload.type === "text" && !payload.content) return;

    const inputText = text;
    setText("");
    setReplyTo(null);

    const optimisticMessage: Message = {
      id: tempId,
      conversation_id: id,
      sender_id: user.id,
      type: payload.type,
      content: payload.content || null,
      media_url: payload.media_url || null,
      sticker_id: payload.sticker_id || null,
      duration_seconds: payload.duration_seconds || null,
      is_view_once: payload.is_view_once || false,
      reply_to_message_id: payload.reply_to_message_id || null,
      location_lat: payload.location_lat,
      location_lng: payload.location_lng,
      created_at: new Date().toISOString(),
    };

    setMessages((prev) => [...prev, optimisticMessage]);
    setDeliveredIds((prev) => {
      const n = new Set(prev);
      n.add(tempId);
      return n;
    });

    userScrolledUp.current = false;
    setShowJumpToBottom(false);
    requestAnimationFrame(() => scrollToBottom(false));

    try {
      const { data, error } = await supabase.from("messages").insert(payload).select().single();
      if (error) {
        setMessages((prev) => prev.filter((m) => m.id !== tempId));
        if (payload.type === "text") setText(inputText);
        toast.error(error.message || "Falha ao enviar");
        return;
      }
      if (data) {
        setMessages((prev) => prev.map((m) => (m.id === tempId ? (data as Message) : m)));
        const timer = setTimeout(() => {
          setDeliveredIds((prev) => {
            const n = new Set(prev);
            n.add(data.id);
            return n;
          });
          deliveredTimersRef.current.delete(data.id);
        }, 1200);
        deliveredTimersRef.current.set(data.id, timer);

        if (other?.id) {
          triggerMessagePushNotification({
            targetUserId: other.id,
            senderId: user.id,
            senderName: profile?.display_name || user.email || "Usuário BEKMORA",
            senderPhoto: profile?.photo_url,
            messageContent:
              payload.content || (payload.type === "image" ? "📷 Foto" : payload.type === "audio" ? "🎙️ Áudio" : "Mensagem"),
            conversationId: id,
          });
        }
      }
    } catch (err: any) {
      setMessages((prev) => prev.filter((m) => m.id !== tempId));
      if (payload.type === "text") setText(inputText);
      toast.error(err.message || "Falha ao enviar");
    }
  };

  const sendImage = async (file: File, viewOnce = false, caption?: string) => {
    if (!user || !id) return;
    if (file.size > 15 * 1024 * 1024) return toast.error("Imagem muito grande (máx 15MB)");

    const toastId = toast.loading("Enviando imagem...");
    try {
      const publicUrl = await uploadChatMedia(file);
      await send({
        type: "image",
        media_url: publicUrl,
        content: caption || null,
        is_view_once: viewOnce,
      } as any);
      setViewOnceMode(false);
      toast.success("Imagem enviada!", { id: toastId });
    } catch (err: any) {
      console.error("[Chat] sendImage error:", err);
      toast.error("Falha no upload da imagem", { id: toastId });
    }
  };

  const sendVideo = async (file: File, caption?: string) => {
    if (!user || !id) return;
    if (file.size > 100 * 1024 * 1024) return toast.error("Vídeo muito grande (máx 100MB)");

    const toastId = toast.loading("Enviando vídeo...");
    try {
      const publicUrl = await uploadChatMedia(file);

      const video = document.createElement("video");
      video.preload = "metadata";
      const dur = await new Promise<number>((resolve) => {
        video.onloadedmetadata = () => resolve(Math.round(video.duration));
        video.onerror = () => resolve(0);
        video.src = publicUrl;
      });

      await send({
        type: "video",
        media_url: publicUrl,
        content: caption || null,
        duration_seconds: dur,
      } as any);
      toast.success("Vídeo enviado!", { id: toastId });
    } catch (err: any) {
      console.error("[Chat] sendVideo error:", err);
      toast.error("Falha no upload do vídeo", { id: toastId });
    }
  };

  const handleSendAudioWaveform = async (file: File, durationSeconds: number) => {
    if (!user || !id) return;
    const toastId = toast.loading("Enviando áudio...");
    try {
      const publicUrl = await uploadChatMedia(file);
      await send({
        type: "audio",
        media_url: publicUrl,
        duration_seconds: durationSeconds,
        content: null,
      } as any);
      toast.success("Áudio enviado!", { id: toastId });
    } catch (err: any) {
      console.error("[Chat] audio upload error:", err);
      toast.error("Falha ao enviar áudio", { id: toastId });
      throw err;
    }
  };

  const handleDropOrPasteFile = async (file: File, caption?: string, viewOnce?: boolean) => {
    if (file.type.startsWith("video/")) {
      await sendVideo(file, caption);
    } else {
      await sendImage(file, !!viewOnce, caption);
    }
  };

  const sendInstantHeart = () => {
    send({ type: "text", content: "❤️" });
  };

  // ── Call Initiation ─────────────────────────────────────────────────────────
  const startCall = async (type: "audio" | "video") => {
    if (!user || !other) return;
    const { data, error } = await supabase
      .from("calls")
      .insert({ caller_id: user.id, callee_id: other.id, type, status: "ringing" })
      .select()
      .single();

    if (error || !data) return toast.error("Falha ao iniciar chamada");

    triggerCallPushNotification({
      targetUserId: other.id,
      senderId: user.id,
      senderName: profile?.display_name || user.email || "Usuário BEKMORA",
      senderPhoto: profile?.photo_url,
      callId: data.id,
    });

    navigate(`/call/${data.id}`);
  };

  // ── Double Tap to Heart (Instagram Micro-interaction) ────────────────────────
  const handleDoubleTap = (msg: Message) => {
    setHeartAnimId(msg.id);
    toggleReaction(msg.id, "❤️");
    setTimeout(() => setHeartAnimId(null), 900);
  };

  const handleMessageClick = (msg: Message) => {
    const now = Date.now();
    const last = lastClickTime.current.get(msg.id) || 0;
    if (now - last < 300) {
      handleDoubleTap(msg);
      lastClickTime.current.set(msg.id, 0);
    } else {
      lastClickTime.current.set(msg.id, now);
    }
  };

  // ── Long Press & Swipe to Reply ─────────────────────────────────────────────
  const handlePressStart = (msg: Message) => {
    setPressingId(msg.id);
    longPressTimer.current = setTimeout(() => {
      setActionFor(msg);
      setPressingId(null);
      if ("vibrate" in navigator) navigator.vibrate(15);
    }, 420);
  };

  const handlePressEnd = () => {
    setPressingId(null);
    if (longPressTimer.current) {
      clearTimeout(longPressTimer.current);
      longPressTimer.current = null;
    }
  };

  const handleTouchStartForReply = (e: TouchEvent, msg: Message) => {
    swipeStartXRef.current = e.touches[0].clientX;
    handlePressStart(msg);
  };

  const handleTouchMoveForReply = (e: TouchEvent, msg: Message) => {
    const currentX = e.touches[0].clientX;
    const diff = currentX - swipeStartXRef.current;
    if (Math.abs(diff) > 10) handlePressEnd();
    if (diff > 0 && diff < 100) {
      setSwipeState({ msgId: msg.id, dx: diff });
    }
  };

  const handleTouchEndForReply = (msg: Message) => {
    if (swipeState?.msgId === msg.id && swipeState.dx > SWIPE_THRESHOLD) {
      setReplyTo(msg);
      if ("vibrate" in navigator) navigator.vibrate(10);
    }
    setSwipeState(null);
  };

  // ── Wallpapers & Custom Theme ───────────────────────────────────────────────
  const loadAvailableBgs = async () => {
    const { data } = await supabase.from("chat_backgrounds").select("*").order("created_at", { ascending: false });
    if (data) setAvailableBgs(data);
  };

  const setWallpaper = async (bgId: string | null, customUrl?: string) => {
    if (!id || !user) return;
    if (bgId) {
      const bg = availableBgs.find((b: any) => b.id === bgId);
      if (bg) {
        setBgImage(bg.image_url || null);
        setBgGradient(bg.gradient_css || null);
        setBgBubbleColor(bg.chat_bubble_color);
        setBgBubbleMineColor(bg.chat_bubble_mine_color);
        setBgTextColor(bg.chat_text_color);
      }
    } else {
      setBgImage(customUrl || null);
      setBgGradient(null);
    }
    await supabase.from("conversation_backgrounds").upsert(
      { conversation_id: id, background_id: bgId, custom_image_url: customUrl || null, set_by: user.id },
      { onConflict: "conversation_id" }
    );
    setShowBgPicker(false);
  };

  const removeWallpaper = async () => {
    if (!id) return;
    await supabase.from("conversation_backgrounds").delete().eq("conversation_id", id);
    setBgImage(null);
    setBgGradient(null);
    setBgBubbleColor("rgba(255,255,255,0.08)");
    setBgBubbleMineColor("rgba(2,132,199,0.95)");
    setBgTextColor("#ffffff");
    setShowBgPicker(false);
  };

  // ── Edit & Delete ───────────────────────────────────────────────────────────
  const canEdit = (m: Message) =>
    m.sender_id === user?.id && m.type === "text" && Date.now() - new Date(m.created_at).getTime() < EDIT_WINDOW_MS;

  const startEdit = (m: Message) => {
    setEditingId(m.id);
    setEditText(m.content || "");
    setActionFor(null);
  };

  const saveEdit = async () => {
    if (!editingId || !editText.trim()) return;
    const { error } = await supabase
      .from("messages")
      .update({ content: editText.trim(), edited_at: new Date().toISOString() })
      .eq("id", editingId);
    if (error) toast.error("Falha ao salvar edição");
    else toast.success("Mensagem editada");
    setEditingId(null);
    setEditText("");
  };

  const deleteMsg = async (m: Message) => {
    setActionFor(null);
    const { error } = await supabase.from("messages").delete().eq("id", m.id);
    if (error) toast.error("Falha ao apagar mensagem");
    else toast.success("Mensagem apagada");
  };

  return (
    <div className="relative flex h-dvh w-full bg-[#070C1A] text-slate-100 overflow-hidden select-none">
      {/* Drag & Drop and Clipboard Paste Overlay */}
      {id && <ChatPasteDropOverlay onSendFile={handleDropOrPasteFile} />}

      {/* ── DESKTOP SIDEBAR (visible on md:flex, or full screen on mobile when !id) ── */}
      <aside
        className={cn(
          "border-r border-white/[0.08] bg-slate-950/95 shrink-0 flex-col h-full z-20 transition-all",
          id ? "hidden md:flex md:w-80 lg:w-96" : "flex w-full md:w-80 lg:w-96"
        )}
      >
        <ChatSidebar activeConvId={id} />
      </aside>

      {/* ── CONVERSATION PANE (Right on desktop, full screen on mobile when id is open) ── */}
      <main
        className={cn(
          "relative flex-1 flex-col h-full min-w-0 overflow-hidden bg-[#070C1A]",
          id ? "flex" : "hidden md:flex"
        )}
      >
        {id ? (
          <div className="flex h-full w-full overflow-hidden bg-[#070C1A]">
            <div className="flex-1 flex flex-col h-full min-w-0 overflow-hidden relative">

            {/* ════════════════════════════════════════════════════════════════════
                1. INSTAGRAM DIRECT HEADER
               ════════════════════════════════════════════════════════════════════ */}
            <header className="relative shrink-0 z-30 bg-slate-950/90 border-b border-white/[0.06] backdrop-blur-2xl px-4 py-2.5 sm:px-6">
              {/* In-Chat Search Bar Overlay */}
              <ChatSearchHeader
                isOpen={searchOpen}
                onClose={() => {
                  setSearchOpen(false);
                  setSearchQuery("");
                }}
                query={searchQuery}
                onQueryChange={setSearchQuery}
                matchCount={searchMatches.length}
                currentMatchIndex={searchMatchIndex}
                onNext={handleSearchNext}
                onPrev={handleSearchPrev}
              />

              <div className="flex items-center justify-between gap-3">

                {/* Back Button & User Info */}
                <div className="flex items-center gap-2.5 min-w-0">
                  <button
                    onClick={() => navigate("/chat")}
                    aria-label="Voltar"
                    className="shrink-0 flex items-center justify-center w-9 h-9 rounded-2xl bg-white/[0.04] hover:bg-white/[0.08] active:scale-95 text-slate-300 hover:text-white transition-all"
                  >
                    <ArrowLeft className="w-4 h-4" />
                  </button>

                {other && (
                  <button
                    onClick={() => navigate(profilePath(other.id, other.username))}
                    className="flex items-center gap-3 min-w-0 text-left group"
                  >
                    {/* Avatar with Live Indicator */}
                    <div className="relative shrink-0">
                      <div
                        className={cn(
                          "rounded-full p-0.5 transition-all",
                          onlineNow ? "bg-gradient-to-tr from-sky-400 to-blue-600" : "bg-white/[0.08]"
                        )}
                      >
                        <Avatar
                          url={other.photo_url}
                          name={other.display_name || other.username}
                          size="sm"
                        />
                      </div>
                      {onlineNow && (
                        <span className="absolute bottom-0 right-0 w-3 h-3 rounded-full bg-emerald-500 ring-2 ring-slate-950 shadow-sm" />
                      )}
                    </div>

                    <div className="min-w-0">
                      <div className="flex items-center gap-1.5 truncate">
                        <RGBName
                          name={otherNickname || other.display_name || other.username || "Usuário"}
                          profile_theme={other.profile_theme}
                          className="text-sm font-bold text-white truncate"
                        />
                        {other.is_verified && <VerifiedBadge size="xxs" />}
                      </div>
                      <p className="text-[11px] font-medium truncate text-slate-400 leading-tight">
                        {isOtherTyping ? (
                          <span className="text-sky-400 font-semibold animate-pulse">digitando...</span>
                        ) : onlineNow ? (
                          <span className="text-emerald-400 font-semibold">Online agora</span>
                        ) : (
                          presenceLabel || `@${other.username || "perfil"}`
                        )}
                      </p>
                    </div>
                  </button>
                )}
              </div>

              {/* Action Buttons: Search, Call, Video, Theme, Options */}
              {other && (
                <div className="flex items-center gap-1.5 shrink-0">
                  <button
                    onClick={() => setSearchOpen((prev) => !prev)}
                    aria-label="Pesquisar mensagens"
                    title="Pesquisar mensagens"
                    className={cn(
                      "w-9 h-9 rounded-2xl bg-white/[0.04] hover:bg-white/[0.08] active:scale-95 text-slate-300 hover:text-white flex items-center justify-center transition-all",
                      searchOpen && "bg-sky-600/20 text-sky-400 border border-sky-500/30"
                    )}
                  >
                    <Search className="w-4 h-4" />
                  </button>
                  <button
                    onClick={() => startCall("audio")}
                    aria-label="Chamada de Voz"
                    className="w-9 h-9 rounded-2xl bg-white/[0.04] hover:bg-white/[0.08] active:scale-95 text-sky-400 flex items-center justify-center transition-all"
                  >
                    <Phone className="w-4 h-4" />
                  </button>
                  <button
                    onClick={() => startCall("video")}
                    aria-label="Chamada de Vídeo"
                    className="w-9 h-9 rounded-2xl bg-white/[0.04] hover:bg-white/[0.08] active:scale-95 text-sky-400 flex items-center justify-center transition-all"
                  >
                    <Video className="w-4 h-4" />
                  </button>
                  <button
                    onClick={() => {
                      loadAvailableBgs();
                      setShowBgPicker(true);
                    }}
                    aria-label="Temas e Fundos"
                    className={cn(
                      "w-9 h-9 rounded-2xl bg-white/[0.04] hover:bg-white/[0.08] active:scale-95 text-slate-300 hover:text-white flex items-center justify-center transition-all",
                      (bgImage || bgGradient) ? "bg-sky-600/20 text-sky-400 border border-sky-500/30" : ""
                    )}
                  >
                    <Palette className="w-4 h-4" />
                  </button>
                  <button
                    onClick={() => setShowDetailsSidebar((prev) => !prev)}
                    aria-label="Dados da Conversa"
                    title="Dados da conversa e mídias compartilhadas"
                    className={cn(
                      "hidden md:flex w-9 h-9 rounded-2xl transition-all active:scale-95 items-center justify-center cursor-pointer",
                      showDetailsSidebar
                        ? "bg-sky-600/25 text-sky-400 border border-sky-500/40 shadow-sm shadow-sky-950"
                        : "bg-white/[0.04] hover:bg-white/[0.08] text-slate-300 hover:text-white"
                    )}
                  >
                    <PanelRight className="w-4 h-4" />
                  </button>
                  <button
                    onClick={() => setShowMobileMenu(!showMobileMenu)}
                    aria-label="Opções"
                    className="md:hidden w-9 h-9 rounded-2xl bg-white/[0.04] hover:bg-white/[0.08] active:scale-95 text-slate-300 hover:text-white flex items-center justify-center transition-all"
                  >
                    <MoreVertical className="w-4 h-4" />
                  </button>
                </div>
              )}
            </div>

            {/* Mobile Sheet for Chat Actions */}
            <AnimatePresence>
              {showMobileMenu && (
                <>
                  <motion.div
                    initial={{ opacity: 0 }}
                    animate={{ opacity: 1 }}
                    exit={{ opacity: 0 }}
                    className="fixed inset-0 z-50 bg-black/70 backdrop-blur-sm"
                    onClick={() => setShowMobileMenu(false)}
                  />
                  <motion.div
                    initial={{ y: "100%", opacity: 0 }}
                    animate={{ y: 0, opacity: 1 }}
                    exit={{ y: "100%", opacity: 0 }}
                    transition={{ type: "spring", damping: 30, stiffness: 350 }}
                    className="fixed bottom-0 left-0 right-0 z-50 mx-auto rounded-t-3xl p-5 bg-slate-900 border border-white/[0.08] max-w-lg space-y-4"
                  >
                    <div className="w-10 h-1 rounded-full mx-auto bg-white/20" />
                    <p className="text-xs font-bold uppercase tracking-wider text-slate-400">Opções da Conversa</p>

                    <div className="grid grid-cols-5 gap-1.5">
                      <button
                        onClick={() => {
                          setSearchOpen(true);
                          setShowMobileMenu(false);
                        }}
                        className="flex flex-col items-center gap-1.5 p-2 rounded-2xl bg-white/[0.04] hover:bg-white/[0.08] active:scale-95"
                      >
                        <div className="w-9 h-9 rounded-xl bg-blue-500/20 text-blue-400 flex items-center justify-center">
                          <Search className="w-4 h-4" />
                        </div>
                        <span className="text-[10px] font-semibold text-slate-300">Buscar</span>
                      </button>

                      <button
                        onClick={() => {
                          startCall("audio");
                          setShowMobileMenu(false);
                        }}
                        className="flex flex-col items-center gap-1.5 p-2 rounded-2xl bg-white/[0.04] hover:bg-white/[0.08] active:scale-95"
                      >
                        <div className="w-9 h-9 rounded-xl bg-emerald-500/20 text-emerald-400 flex items-center justify-center">
                          <Phone className="w-4 h-4" />
                        </div>
                        <span className="text-[10px] font-semibold text-slate-300">Voz</span>
                      </button>

                      <button
                        onClick={() => {
                          startCall("video");
                          setShowMobileMenu(false);
                        }}
                        className="flex flex-col items-center gap-1.5 p-2 rounded-2xl bg-white/[0.04] hover:bg-white/[0.08] active:scale-95"
                      >
                        <div className="w-9 h-9 rounded-xl bg-sky-500/20 text-sky-400 flex items-center justify-center">
                          <Video className="w-4 h-4" />
                        </div>
                        <span className="text-[10px] font-semibold text-slate-300">Vídeo</span>
                      </button>

                      <button
                        onClick={() => {
                          loadAvailableBgs();
                          setShowBgPicker(true);
                          setShowMobileMenu(false);
                        }}
                        className="flex flex-col items-center gap-1.5 p-2 rounded-2xl bg-white/[0.04] hover:bg-white/[0.08] active:scale-95"
                      >
                        <div className="w-9 h-9 rounded-xl bg-purple-500/20 text-purple-400 flex items-center justify-center">
                          <Palette className="w-4 h-4" />
                        </div>
                        <span className="text-[10px] font-semibold text-slate-300">Tema</span>
                      </button>

                      <button
                        onClick={() => {
                          setNicknameInputVal(otherNickname || "");
                          setShowNicknameInput(true);
                          setShowMobileMenu(false);
                        }}
                        className="flex flex-col items-center gap-1.5 p-2 rounded-2xl bg-white/[0.04] hover:bg-white/[0.08] active:scale-95"
                      >
                        <div className="w-9 h-9 rounded-xl bg-amber-500/20 text-amber-400 flex items-center justify-center">
                          <Tag className="w-4 h-4" />
                        </div>
                        <span className="text-[10px] font-semibold text-slate-300">Apelido</span>
                      </button>
                    </div>

                    <button
                      onClick={() => setShowMobileMenu(false)}
                      className="w-full py-3 rounded-2xl text-xs font-bold text-slate-400 hover:text-white bg-white/[0.04] transition-all"
                    >
                      Fechar
                    </button>
                  </motion.div>
                </>
              )}
            </AnimatePresence>
          </header>

          {/* Pinned Message Bar */}
          <PinnedMessageBar
            pinnedMessage={
              pinnedMessage
                ? {
                    id: pinnedMessage.id,
                    senderName:
                      pinnedMessage.sender_id === user?.id
                        ? "Você"
                        : other?.display_name || other?.username || "Usuário",
                    content: pinnedMessage.content,
                    type: pinnedMessage.type,
                  }
                : null
            }
            onJump={jumpToMessage}
            onUnpin={handleUnpinMessage}
          />

          {/* ════════════════════════════════════════════════════════════════════
              2. MESSAGES STREAM (INSTAGRAM DIRECT BUBBLES)
             ════════════════════════════════════════════════════════════════════ */}
          <div className="relative min-h-0 flex-1 flex flex-col overflow-hidden">

            {/* Custom Chat Wallpaper */}
            {(bgImage || bgGradient) && (
              <div
                aria-hidden
                className="absolute inset-0 z-0 pointer-events-none"
                style={{
                  ...(bgImage
                    ? { backgroundImage: `url(${bgImage})`, backgroundSize: "cover", backgroundPosition: "center" }
                    : { background: bgGradient! }),
                }}
              />
            )}

            {/* Scrollable Message List */}
            <div
              ref={scrollRef}
              onScroll={handleScroll}
              style={{ overflowAnchor: "auto" }}
              className="scrollbar-hide relative z-10 flex-1 overflow-y-auto overscroll-y-contain px-4 pt-4 pb-3"
            >
              <div ref={messagesInnerRef} className="space-y-3 min-h-full flex flex-col">
                {/* Spacer to push messages naturally to bottom if few messages */}
                <div className="flex-1 min-h-0" />

                {/* Load older messages button / spinner */}
                {hasMoreOlder && (
                  <div className="flex justify-center py-2 shrink-0">
                    <button
                      type="button"
                      onClick={loadOlderMessages}
                      disabled={isLoadingOlder}
                      className="px-3.5 py-1.5 rounded-full bg-slate-900/90 border border-white/10 text-xs font-medium text-slate-300 hover:text-white hover:bg-slate-800 active:scale-95 transition-all flex items-center gap-1.5 shadow-lg backdrop-blur-md"
                    >
                      {isLoadingOlder ? (
                        <>
                          <Loader2 className="w-3.5 h-3.5 animate-spin text-sky-400" />
                          <span>Carregando mensagens anteriores...</span>
                        </>
                      ) : (
                        <>
                          <ArrowUp className="w-3.5 h-3.5 text-sky-400" />
                          <span>Carregar mensagens anteriores</span>
                        </>
                      )}
                    </button>
                  </div>
                )}
              {/* Empty state */}
              {messages.length === 0 && !isLoadingMessages && other && (
                <div className="flex flex-col items-center justify-center py-20 gap-3 text-center">
                  <div className="w-20 h-20 rounded-full p-1 bg-gradient-to-tr from-sky-500 to-blue-600 shadow-xl">
                    <div className="w-full h-full rounded-full bg-slate-950 overflow-hidden flex items-center justify-center">
                      <Avatar url={other.photo_url} name={other.display_name || other.username} size="lg" />
                    </div>
                  </div>
                  <div>
                    <RGBName
                      name={otherNickname || other.display_name || other.username || "Usuário"}
                      profile_theme={other.profile_theme}
                      className="text-base font-bold text-white block"
                    />
                    <p className="text-xs text-slate-400 mt-0.5">@{other.username || "bekmora"}</p>
                  </div>
                  <p className="text-[11px] text-slate-500 max-w-xs mt-2">
                    Início da conversa com @{other.username}. Envie uma mensagem ou toque duas vezes para curtir!
                  </p>
                </div>
              )}

              {/* Messages Array */}
              {messages.map((m, idx) => {
                const mine = m.sender_id === user?.id;
                const replyMessage = m.reply_to_message_id ? messageById.get(m.reply_to_message_id) || null : null;
                const isEditing = editingId === m.id;
                const prevMsg = idx > 0 ? messages[idx - 1] : null;
                const nextMsg = idx < messages.length - 1 ? messages[idx + 1] : null;

                const showDateSep =
                  !prevMsg || new Date(prevMsg.created_at).toDateString() !== new Date(m.created_at).toDateString();
                const isLastInGroup =
                  !nextMsg || nextMsg.sender_id !== m.sender_id || new Date(nextMsg.created_at).toDateString() !== new Date(m.created_at).toDateString();

                return (
                  <div
                    key={m.id}
                    data-message-id={m.id}
                    onContextMenu={(e) => {
                      e.preventDefault();
                      setContextMenu({ x: e.clientX, y: e.clientY, message: m });
                    }}
                    className="relative group"
                  >
                    {/* Date Separator */}
                    {showDateSep && (
                      <div className="flex items-center justify-center my-4">
                        <span className="px-3.5 py-1 text-[10px] font-bold uppercase tracking-wider text-slate-400 bg-slate-900/80 rounded-full border border-white/[0.06] backdrop-blur-md">
                          {formatDateSeparator(m.created_at)}
                        </span>
                      </div>
                    )}

                    {/* Message Row */}
                    <motion.div
                      initial={{ opacity: 0, y: 8, scale: 0.98 }}
                      animate={{ opacity: 1, y: 0, scale: 1 }}
                      transition={{ duration: 0.15 }}
                      className={cn("flex items-end gap-2", mine ? "justify-end" : "justify-start")}
                    >
                      {/* Other Avatar on group end */}
                      {!mine && (
                        <div className="w-7 h-7 shrink-0 mb-1">
                          {isLastInGroup ? (
                            <Avatar url={other?.photo_url} name={other?.display_name || other?.username} size="xs" />
                          ) : (
                            <div className="w-7 h-7" />
                          )}
                        </div>
                      )}

                      {/* Bubble Container */}
                      <div className={cn("relative max-w-[82%] sm:max-w-[70%]", m.type === "sticker" && "max-w-none")}>

                        {/* Desktop Hover Quick Reactions Bar */}
                        <div
                          className={cn(
                            "absolute -top-7 z-20 hidden md:group-hover:flex items-center gap-0.5 px-2 py-0.5 rounded-full bg-slate-900/95 border border-white/10 backdrop-blur-md shadow-xl transition-all duration-150",
                            mine ? "right-0" : "left-0"
                          )}
                        >
                          {["❤️", "👍", "😂", "😮", "😢", "🔥"].map((emoji) => (
                            <button
                              key={emoji}
                              type="button"
                              onClick={(e) => {
                                e.stopPropagation();
                                toggleReaction(m.id, emoji);
                              }}
                              className="w-6 h-6 flex items-center justify-center text-xs hover:scale-125 active:scale-95 transition-transform"
                            >
                              {emoji}
                            </button>
                          ))}
                          <div className="w-[1px] h-3 bg-white/15 mx-0.5" />
                          <button
                            type="button"
                            onClick={(e) => {
                              e.stopPropagation();
                              setReplyTo(m);
                            }}
                            title="Responder"
                            className="w-5 h-5 flex items-center justify-center text-slate-400 hover:text-white rounded-full hover:bg-white/10 transition-colors"
                          >
                            <CornerUpLeft className="w-3 h-3" />
                          </button>
                          <button
                            type="button"
                            onClick={(e) => {
                              e.stopPropagation();
                              setActionFor(m);
                            }}
                            title="Mais opções"
                            className="w-5 h-5 flex items-center justify-center text-slate-400 hover:text-white rounded-full hover:bg-white/10 transition-colors"
                          >
                            <MoreVertical className="w-3 h-3" />
                          </button>
                        </div>

                        {/* Double-tap Floating Heart Animation */}
                        <AnimatePresence>
                          {heartAnimId === m.id && (
                            <motion.div
                              initial={{ scale: 0, opacity: 0, y: 0 }}
                              animate={{ scale: 1.5, opacity: 1, y: -30 }}
                              exit={{ scale: 0.5, opacity: 0, y: -50 }}
                              transition={{ type: "spring", stiffness: 400, damping: 20 }}
                              className="absolute inset-0 flex items-center justify-center z-30 pointer-events-none"
                            >
                              <Heart className="w-12 h-12 text-rose-500 fill-rose-500 drop-shadow-lg" />
                            </motion.div>
                          )}
                        </AnimatePresence>

                        {/* Bubble Body */}
                        <div
                          onClick={() => handleMessageClick(m)}
                          onPointerDown={() => handlePressStart(m)}
                          onPointerUp={handlePressEnd}
                          onPointerLeave={handlePressEnd}
                          onContextMenu={(e) => {
                            e.preventDefault();
                            setActionFor(m);
                          }}
                          onTouchStart={(e) => handleTouchStartForReply(e, m)}
                          onTouchMove={(e) => handleTouchMoveForReply(e, m)}
                          onTouchEnd={() => {
                            handlePressEnd();
                            handleTouchEndForReply(m);
                          }}
                          className={cn(
                            "relative transition-all select-none overflow-hidden",
                            highlightMsgId === m.id && "ring-2 ring-sky-400 ring-offset-2 ring-offset-slate-950 scale-[1.02] shadow-lg shadow-sky-500/40",
                            m.type === "sticker" ? "bg-transparent p-0 shadow-none" : "px-4 py-2.5 rounded-3xl",
                            m.type !== "sticker" && (
                              mine
                                ? (bgGradient || bgImage
                                    ? "text-white shadow-md"
                                    : "bg-gradient-to-tr from-sky-600 to-blue-600 text-white rounded-br-sm shadow-md shadow-sky-600/20")
                                : (bgGradient || bgImage
                                    ? "shadow-md"
                                    : "bg-slate-800/90 text-slate-100 border border-white/[0.06] rounded-bl-sm")
                            ),
                            pressingId === m.id && "scale-95 brightness-90"
                          )}
                          style={{
                            ...(m.type !== "sticker" && (bgGradient || bgImage)
                              ? {
                                  background: mine ? bgBubbleMineColor : bgBubbleColor,
                                  color: bgTextColor,
                                }
                              : {}),
                          }}
                        >
                          {/* Reply Quote Header */}
                          {replyMessage && (
                            <div
                              onClick={(e) => {
                                e.stopPropagation();
                                jumpToMessage(replyMessage.id);
                              }}
                              className={cn(
                                "mb-2 p-2 rounded-2xl text-xs backdrop-blur-md cursor-pointer border-l-2 hover:opacity-90 transition-opacity",
                                mine
                                  ? "bg-black/20 border-white/60 text-white/80"
                                  : "bg-white/10 border-sky-400 text-slate-300"
                              )}
                            >
                              <p className="font-bold text-[10px] uppercase tracking-wider text-sky-300">
                                {replyMessage.sender_id === user?.id ? "Você" : other?.display_name || "Usuário"}
                              </p>
                              <p className="truncate text-[11px] mt-0.5 opacity-80">
                                {replyMessage.type === "text"
                                  ? replyMessage.content
                                  : replyMessage.type === "image"
                                  ? "📷 Foto"
                                  : replyMessage.type === "video"
                                  ? "🎬 Vídeo"
                                  : replyMessage.type === "audio"
                                  ? "🎙️ Áudio"
                                  : "Sticker"}
                              </p>
                            </div>
                          )}

                          {/* TEXT MESSAGE */}
                          {m.type === "text" && !isEditing && (
                            <p className="text-sm leading-relaxed whitespace-pre-wrap break-words">{m.content}</p>
                          )}

                          {/* EDIT INLINE */}
                          {m.type === "text" && isEditing && (
                            <div className="flex items-center gap-2 bg-slate-900/90 rounded-2xl p-2 border border-white/20">
                              <input
                                autoFocus
                                value={editText}
                                onChange={(e) => setEditText(e.target.value)}
                                onKeyDown={(e) => {
                                  if (e.key === "Enter") saveEdit();
                                  if (e.key === "Escape") setEditingId(null);
                                }}
                                className="flex-1 bg-transparent text-xs text-white outline-none"
                              />
                              <button onClick={saveEdit} className="p-1.5 rounded-lg bg-sky-600 text-white">
                                <Check className="w-3.5 h-3.5" />
                              </button>
                              <button onClick={() => setEditingId(null)} className="p-1.5 rounded-lg bg-white/10 text-slate-400">
                                <X className="w-3.5 h-3.5" />
                              </button>
                            </div>
                          )}

                          {/* IMAGE MESSAGE */}
                          {m.type === "image" && m.media_url && (
                            <div className="rounded-2xl overflow-hidden -mx-4 -my-2.5">
                              {m.is_view_once ? (
                                <ViewOnceImage
                                  messageId={m.id}
                                  mediaUrl={m.media_url}
                                  isMine={mine}
                                  isAdmin={isAdmin}
                                  viewedAt={m.viewed_at || null}
                                />
                              ) : (
                                <img
                                  src={m.media_url}
                                  alt="Mídia"
                                  loading="eager"
                                  decoding="async"
                                  onLoad={() => {
                                    if (!userScrolledUp.current && scrollRef.current) {
                                      scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
                                    }
                                  }}
                                  className="max-h-80 w-full object-cover cursor-pointer hover:opacity-95 transition-opacity"
                                  onClick={() => setMediaViewer({ src: m.media_url!, type: "image" })}
                                />
                              )}
                            </div>
                          )}

                          {/* VIDEO MESSAGE */}
                          {m.type === "video" && m.media_url && (
                            <div
                              onClick={() => setMediaViewer({ src: m.media_url!, type: "video" })}
                              className="relative rounded-2xl overflow-hidden cursor-pointer group -mx-4 -my-2.5"
                            >
                              <video
                                src={m.media_url}
                                className="max-h-80 w-full object-cover"
                                preload="metadata"
                                playsInline
                                muted
                              />
                              <div className="absolute inset-0 flex items-center justify-center bg-black/20 group-hover:bg-black/30 transition-all">
                                <div className="w-12 h-12 rounded-full bg-black/60 backdrop-blur-md flex items-center justify-center text-white shadow-xl group-hover:scale-110 transition-transform">
                                  <Play className="w-5 h-5 fill-white ml-0.5" />
                                </div>
                              </div>
                            </div>
                          )}

                          {/* STICKER */}
                          {m.type === "sticker" && m.media_url && (
                            <img
                              src={m.media_url}
                              alt="Sticker"
                              loading="eager"
                              decoding="async"
                              onLoad={() => {
                                if (!userScrolledUp.current && scrollRef.current) {
                                  scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
                                }
                              }}
                              className="w-32 h-32 object-contain drop-shadow-xl select-none"
                            />
                          )}

                          {/* AUDIO MESSAGE */}
                          {m.type === "audio" && m.media_url && (
                            <AudioPlayer url={m.media_url} duration={m.duration_seconds || 0} isMine={mine} />
                          )}

                          {/* Reactions Display */}
                          {m.type !== "sticker" && getReactions(m.id).length > 0 && (
                            <div className="mt-1">
                              <MessageReactions
                                messageId={m.id}
                                reactions={getReactions(m.id)}
                                onChange={() => reloadReactions()}
                                align={mine ? "end" : "start"}
                              />
                            </div>
                          )}

                          {/* Timestamp & Status (Read Receipts) */}
                          {m.type !== "sticker" && (
                            <div className={cn("flex items-center gap-1 mt-1 text-[10px]", mine ? "justify-end text-white/70" : "justify-start text-slate-400")}>
                              <span>
                                {new Date(m.created_at).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })}
                              </span>
                              {m.edited_at && <span className="opacity-60">· editado</span>}

                              {/* Read Receipts */}
                              {mine && (
                                <span className="ml-0.5">
                                  {readMessageIds.has(m.id) ? (
                                    <CheckCheck className="w-3.5 h-3.5 text-sky-300 stroke-[2.5px]" />
                                  ) : deliveredIds.has(m.id) ? (
                                    <CheckCheck className="w-3.5 h-3.5 text-white/60 stroke-[2px]" />
                                  ) : (
                                    <Check className="w-3.5 h-3.5 text-white/40 stroke-[2px]" />
                                  )}
                                </span>
                              )}
                            </div>
                          )}
                        </div>
                      </div>
                    </motion.div>
                  </div>
                );
              })}

                {/* Other user is typing indicator */}
                {isOtherTyping && (
                  <motion.div
                    initial={{ opacity: 0, y: 6 }}
                    animate={{ opacity: 1, y: 0 }}
                    exit={{ opacity: 0, y: 6 }}
                    className="flex items-end gap-2 text-slate-400 py-1"
                  >
                    <div className="w-7 h-7 shrink-0 mb-1">
                      <Avatar url={other?.photo_url} name={other?.display_name || other?.username} size="xs" />
                    </div>
                    <div className="px-4 py-2.5 rounded-3xl rounded-bl-sm bg-slate-800/90 border border-white/[0.06] flex items-center gap-1.5 shadow-md">
                      <span className="w-1.5 h-1.5 rounded-full bg-sky-400 animate-bounce [animation-delay:-0.3s]" />
                      <span className="w-1.5 h-1.5 rounded-full bg-sky-400 animate-bounce [animation-delay:-0.15s]" />
                      <span className="w-1.5 h-1.5 rounded-full bg-sky-400 animate-bounce" />
                    </div>
                  </motion.div>
                )}

                {/* Bottom Anchor Sentinel */}
                <div ref={bottomAnchorRef} className="h-px w-full shrink-0 -mt-px pointer-events-none" />
              </div>
            </div>

            {/* Jump to bottom floating button */}
            <AnimatePresence>
              {showJumpToBottom && (
                <motion.button
                  type="button"
                  initial={{ opacity: 0, scale: 0.8, y: 12 }}
                  animate={{ opacity: 1, scale: 1, y: 0 }}
                  exit={{ opacity: 0, scale: 0.8, y: 12 }}
                  transition={{ duration: 0.15 }}
                  onClick={() => {
                    userScrolledUp.current = false;
                    setShowJumpToBottom(false);
                    scrollToBottom(true);
                  }}
                  className="absolute right-5 bottom-4 z-30 p-2.5 rounded-full bg-slate-900/95 text-sky-400 border border-white/10 shadow-2xl backdrop-blur-md hover:bg-slate-800 active:scale-95 transition-all flex items-center justify-center group"
                  title="Ir para mensagens recentes"
                >
                  <ChevronDown className="w-5 h-5 group-hover:translate-y-0.5 transition-transform" />
                </motion.button>
              )}
            </AnimatePresence>
          </div>

          {/* ════════════════════════════════════════════════════════════════════
              3. INSTAGRAM DIRECT INPUT CAPSULE
             ════════════════════════════════════════════════════════════════════ */}
          <div className="shrink-0 bg-slate-950/90 border-t border-white/[0.06] backdrop-blur-2xl px-4 py-3 sm:px-6">
            <input
              ref={fileInputRef}
              type="file"
              accept="image/*,video/*"
              className="hidden"
              onChange={(e) => {
                const f = e.target.files?.[0];
                if (f) {
                  f.type.startsWith("video/") ? sendVideo(f) : sendImage(f, viewOnceMode);
                }
                e.currentTarget.value = "";
              }}
            />



            {/* Reply Bar */}
            <AnimatePresence>
              {replyTo && (
                <motion.div
                  initial={{ opacity: 0, height: 0 }}
                  animate={{ opacity: 1, height: "auto" }}
                  exit={{ opacity: 0, height: 0 }}
                  className="overflow-hidden mb-2.5"
                >
                  <div className="flex items-center justify-between px-3.5 py-2 rounded-2xl bg-slate-900 border border-white/[0.08]">
                    <div className="flex items-center gap-2 min-w-0">
                      <CornerUpLeft className="w-4 h-4 text-sky-400 shrink-0" />
                      <div className="min-w-0">
                        <p className="text-[10px] font-bold text-sky-400 uppercase tracking-wider">
                          Respondendo a {replyTo.sender_id === user?.id ? "você" : other?.display_name || "usuário"}
                        </p>
                        <p className="text-xs text-slate-300 truncate">{replyTo.content || "Mídia"}</p>
                      </div>
                    </div>
                    <button onClick={() => setReplyTo(null)} className="p-1 rounded-lg text-slate-400 hover:text-white">
                      <X className="w-4 h-4" />
                    </button>
                  </div>
                </motion.div>
              )}
            </AnimatePresence>

            {/* View Once Indicator */}
            <AnimatePresence>
              {viewOnceMode && (
                <motion.div
                  initial={{ opacity: 0, height: 0 }}
                  animate={{ opacity: 1, height: "auto" }}
                  exit={{ opacity: 0, height: 0 }}
                  className="overflow-hidden mb-2.5"
                >
                  <div className="flex items-center justify-between px-3.5 py-1.5 rounded-2xl bg-amber-500/15 border border-amber-500/30 text-amber-400 text-xs font-bold">
                    <div className="flex items-center gap-1.5">
                      <Eye className="w-4 h-4" />
                      <span>Modo Visualização Única Ativado</span>
                    </div>
                    <button onClick={() => setViewOnceMode(false)}>
                      <X className="w-3.5 h-3.5" />
                    </button>
                  </div>
                </motion.div>
              )}
            </AnimatePresence>

            {/* Sticker Drawer */}
            <AnimatePresence>
              {showStickers && (
                <StickerPicker
                  onSelect={(s) => {
                    setShowStickers(false);
                    send({ type: "sticker", sticker_id: s.id, media_url: s.image_url, content: null });
                  }}
                  onClose={() => setShowStickers(false)}
                />
              )}
            </AnimatePresence>

            {/* Main Capsule Row */}
            <div className="flex items-center gap-2">
              {recording ? (
                <div className="flex-1 flex items-center">
                  <VoiceRecorderWaveform
                    isRecording={recording}
                    onStartRecording={() => setRecording(true)}
                    onCancelRecording={() => setRecording(false)}
                    onSendAudio={handleSendAudioWaveform}
                    className="w-full"
                  />
                </div>
              ) : (
                /* Input Capsule Container */
                <div
                  className={cn(
                    "flex-1 flex items-center gap-2.5 rounded-full bg-slate-900/90 border border-white/[0.08] px-3.5 py-1.5 transition-all shadow-md",
                    inputFocused ? "border-sky-500/50 ring-2 ring-sky-500/20" : ""
                  )}
                >
                  {/* Plus / Attachment Menu */}
                  <button
                    ref={attachButtonRef}
                    onClick={() => setShowAttachMenu((v) => !v)}
                    className="w-8 h-8 rounded-full bg-white/[0.06] hover:bg-white/[0.1] text-sky-400 flex items-center justify-center shrink-0 transition-all active:scale-90"
                  >
                    <Plus className="w-4 h-4" />
                  </button>
                  <AttachmentMenuPortal
                    isOpen={showAttachMenu}
                    onClose={() => setShowAttachMenu(false)}
                    onCamera={() => setCameraOpen(true)}
                    onGallery={() => fileInputRef.current?.click()}
                    onVideo={() => fileInputRef.current?.click()}
                    onViewOnce={() => {
                      setViewOnceMode(true);
                      fileInputRef.current?.click();
                    }}
                    triggerRef={attachButtonRef}
                  />

                  {/* Stickers / Emoji Button */}
                  <button
                    onClick={() => setShowStickers((v) => !v)}
                    className={cn(
                      "w-8 h-8 rounded-full flex items-center justify-center shrink-0 transition-all active:scale-90",
                      showStickers ? "bg-sky-600/20 text-sky-400" : "text-slate-400 hover:text-white"
                    )}
                  >
                    <Smile className="w-5 h-5" />
                  </button>

                  {/* Auto-expanding Desktop & Mobile Input */}
                  <textarea
                    ref={textareaRef}
                    rows={1}
                    value={text}
                    placeholder={other ? `Mensagem para ${otherNickname || other.display_name || other.username}...` : "Mensagem..."}
                    className="flex-1 resize-none bg-transparent border-none outline-none text-sm leading-relaxed text-white placeholder:text-slate-500 px-1 py-1 max-h-28 scrollbar-hide"
                    onFocus={() => setInputFocused(true)}
                    onBlur={() => setInputFocused(false)}
                    onChange={(e) => {
                      setText(e.target.value);
                      sendTyping();
                      e.target.style.height = "auto";
                      e.target.style.height = `${Math.min(e.target.scrollHeight, 120)}px`;
                    }}
                    onKeyDown={(e) => {
                      if (e.key === "Enter" && !e.shiftKey) {
                        e.preventDefault();
                        send();
                        if (textareaRef.current) textareaRef.current.style.height = "auto";
                      } else if (e.key === "ArrowUp" && !text.trim()) {
                        const myLast = [...messages].reverse().find((m) => m.sender_id === user?.id && m.type === "text");
                        if (myLast && Date.now() - new Date(myLast.created_at).getTime() < EDIT_WINDOW_MS) {
                          setEditingId(myLast.id);
                          setEditText(myLast.content || "");
                        }
                      }
                    }}
                  />

                  {/* Right side actions inside capsule when text is empty */}
                  {!text.trim() && (
                    <div className="flex items-center gap-1 shrink-0">
                      {/* Modern Voice Waveform Recorder Button */}
                      <VoiceRecorderWaveform
                        isRecording={false}
                        onStartRecording={() => setRecording(true)}
                        onCancelRecording={() => setRecording(false)}
                        onSendAudio={handleSendAudioWaveform}
                      />

                      {/* Gallery Button */}
                      <button
                        onClick={() => fileInputRef.current?.click()}
                        className="w-8 h-8 rounded-full flex items-center justify-center text-slate-400 hover:text-white transition-all active:scale-90"
                      >
                        <ImageIcon className="w-4 h-4" />
                      </button>

                      {/* Quick Heart Send (Instagram Love) */}
                      <button
                        onClick={sendInstantHeart}
                        className="w-8 h-8 rounded-full flex items-center justify-center text-rose-500 hover:scale-110 transition-all active:scale-90"
                      >
                        <Heart className="w-4 h-4 fill-rose-500" />
                      </button>
                    </div>
                  )}
                </div>
              )}

              {/* Bold Send Button when typing */}
              <AnimatePresence>
                {text.trim() && !recording && (
                  <motion.button
                    initial={{ scale: 0.8, opacity: 0 }}
                    animate={{ scale: 1, opacity: 1 }}
                    exit={{ scale: 0.8, opacity: 0 }}
                    onClick={() => send()}
                    className="px-4 py-2 rounded-full bg-sky-600 hover:bg-sky-500 text-white text-xs font-bold shadow-md shadow-sky-600/30 transition-all active:scale-95 shrink-0 flex items-center gap-1"
                  >
                    <span>Enviar</span>
                    <Send className="w-3.5 h-3.5 ml-0.5" />
                  </motion.button>
                )}
              </AnimatePresence>
            </div>
          </div>
            </div>

            {/* Desktop Right Details Inspector Sidebar */}
            <ChatDetailsSidebar
              isOpen={showDetailsSidebar}
              onClose={() => setShowDetailsSidebar(false)}
              otherUser={other}
              otherNickname={otherNickname}
              messages={messages}
              pinnedMessage={pinnedMessage}
              onStartCall={startCall}
              onOpenSearch={() => setSearchOpen(true)}
              onOpenBgPicker={() => {
                loadAvailableBgs();
                setShowBgPicker(true);
              }}
              onOpenNicknameModal={() => {
                setNicknameInputVal(otherNickname || "");
                setShowNicknameInput(true);
              }}
              onJumpToMessage={jumpToMessage}
              onOpenMedia={(src, type) => setMediaViewer({ src, type })}
            />
          </div>
        ) : (
          <ChatDesktopEmptyState onNewChat={() => navigate("/messages")} />
        )}
      </main>

      {/* Desktop Right-Click Context Menu */}
      {contextMenu && (
        <ChatContextMenu
          x={contextMenu.x}
          y={contextMenu.y}
          message={contextMenu.message}
          isMine={contextMenu.message.sender_id === user?.id}
          isPinned={pinnedMessageId === contextMenu.message.id}
          canEdit={
            contextMenu.message.sender_id === user?.id &&
            Date.now() - new Date(contextMenu.message.created_at).getTime() < EDIT_WINDOW_MS
          }
          onClose={() => setContextMenu(null)}
          onReply={() => setReplyTo(contextMenu.message)}
          onCopy={() => {
            if (contextMenu.message.content) {
              navigator.clipboard.writeText(contextMenu.message.content);
              toast.success("Texto copiado!");
            }
          }}
          onPin={() => {
            if (pinnedMessageId === contextMenu.message.id) handleUnpinMessage();
            else handlePinMessage(contextMenu.message);
          }}
          onEdit={() => {
            setEditingId(contextMenu.message.id);
            setEditText(contextMenu.message.content || "");
          }}
          onDelete={() => deleteMsg(contextMenu.message)}
          onReact={(emoji) => toggleReaction(contextMenu.message.id, emoji)}
        />
      )}

      {/* ════════════════════════════════════════════════════════════════════
          4. ACTION SHEET & MODALS
         ════════════════════════════════════════════════════════════════════ */}
      <AnimatePresence>
        {actionFor && (
          <>
            <motion.div
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              exit={{ opacity: 0 }}
              onClick={() => setActionFor(null)}
              className="fixed inset-0 z-50 bg-black/70 backdrop-blur-sm"
            />
            <motion.div
              initial={{ y: "100%", opacity: 0 }}
              animate={{ y: 0, opacity: 1 }}
              exit={{ y: "100%", opacity: 0 }}
              transition={{ type: "spring", damping: 30, stiffness: 350 }}
              className="fixed bottom-0 left-0 right-0 z-50 mx-auto rounded-t-3xl p-5 bg-slate-900 border border-white/[0.08] max-w-lg space-y-4"
            >
              <div className="w-10 h-1 rounded-full mx-auto bg-white/20" />

              {/* Reaction Bar */}
              <div className="space-y-1.5">
                <p className="text-[10px] font-bold uppercase tracking-wider text-slate-400">Reagir</p>
                <ReactionPicker
                  messageId={actionFor.id}
                  onClose={() => setActionFor(null)}
                  onReacted={() => {
                    reloadReactions();
                    setActionFor(null);
                  }}
                />
              </div>

              <div className="h-px bg-white/[0.06]" />

              {/* Actions Grid */}
              <div className="grid grid-cols-5 gap-2">
                <button
                  onClick={() => {
                    setReplyTo(actionFor);
                    setActionFor(null);
                  }}
                  className="flex flex-col items-center gap-1.5 p-3 rounded-2xl bg-white/[0.04] hover:bg-white/[0.08]"
                >
                  <div className="w-10 h-10 rounded-xl bg-sky-500/20 text-sky-400 flex items-center justify-center">
                    <CornerUpLeft className="w-5 h-5" />
                  </div>
                  <span className="text-[11px] font-semibold text-slate-300">Responder</span>
                </button>

                <button
                  onClick={() => {
                    if (pinnedMessageId === actionFor.id) {
                      handleUnpinMessage();
                      setActionFor(null);
                    } else {
                      handlePinMessage(actionFor);
                    }
                  }}
                  className="flex flex-col items-center gap-1.5 p-3 rounded-2xl bg-white/[0.04] hover:bg-white/[0.08]"
                >
                  <div className="w-10 h-10 rounded-xl bg-amber-500/20 text-amber-400 flex items-center justify-center">
                    {pinnedMessageId === actionFor.id ? <PinOff className="w-5 h-5" /> : <Pin className="w-5 h-5" />}
                  </div>
                  <span className="text-[11px] font-semibold text-slate-300">
                    {pinnedMessageId === actionFor.id ? "Desfixar" : "Fixar"}
                  </span>
                </button>

                {actionFor.type === "text" && actionFor.content && (
                  <button
                    onClick={() => {
                      navigator.clipboard.writeText(actionFor.content || "");
                      toast.success("Mensagem copiada!");
                      setActionFor(null);
                    }}
                    className="flex flex-col items-center gap-1.5 p-3 rounded-2xl bg-white/[0.04] hover:bg-white/[0.08]"
                  >
                    <div className="w-10 h-10 rounded-xl bg-emerald-500/20 text-emerald-400 flex items-center justify-center">
                      <Copy className="w-5 h-5" />
                    </div>
                    <span className="text-[11px] font-semibold text-slate-300">Copiar</span>
                  </button>
                )}

                {canEdit(actionFor) && (
                  <button
                    onClick={() => startEdit(actionFor)}
                    className="flex flex-col items-center gap-1.5 p-3 rounded-2xl bg-white/[0.04] hover:bg-white/[0.08]"
                  >
                    <div className="w-10 h-10 rounded-xl bg-purple-500/20 text-purple-400 flex items-center justify-center">
                      <Pencil className="w-5 h-5" />
                    </div>
                    <span className="text-[11px] font-semibold text-slate-300">Editar</span>
                  </button>
                )}

                {actionFor.sender_id === user?.id && (
                  <button
                    onClick={() => deleteMsg(actionFor)}
                    className="flex flex-col items-center gap-1.5 p-3 rounded-2xl bg-white/[0.04] hover:bg-white/[0.08]"
                  >
                    <div className="w-10 h-10 rounded-xl bg-rose-500/20 text-rose-400 flex items-center justify-center">
                      <Trash2 className="w-5 h-5" />
                    </div>
                    <span className="text-[11px] font-semibold text-slate-300">Apagar</span>
                  </button>
                )}
              </div>

              <button
                onClick={() => setActionFor(null)}
                className="w-full py-3 rounded-2xl text-xs font-bold text-slate-400 hover:text-white bg-white/[0.04] transition-all"
              >
                Cancelar
              </button>
            </motion.div>
          </>
        )}
      </AnimatePresence>

      {/* Nickname Modal */}
      <AnimatePresence>
        {showNicknameInput && (
          <>
            <motion.div
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              exit={{ opacity: 0 }}
              onClick={() => setShowNicknameInput(false)}
              className="fixed inset-0 z-50 bg-black/70 backdrop-blur-sm"
            />
            <motion.div
              initial={{ y: "100%", opacity: 0 }}
              animate={{ y: 0, opacity: 1 }}
              exit={{ y: "100%", opacity: 0 }}
              transition={{ type: "spring", damping: 30, stiffness: 350 }}
              className="fixed bottom-0 left-0 right-0 z-50 mx-auto rounded-t-3xl p-5 bg-slate-900 border border-white/[0.08] max-w-lg space-y-4"
            >
              <div className="w-10 h-1 rounded-full mx-auto bg-white/20" />
              <div className="flex items-center gap-3">
                <div className="w-10 h-10 rounded-2xl bg-amber-500/20 text-amber-400 flex items-center justify-center">
                  <Tag className="w-5 h-5" />
                </div>
                <div>
                  <p className="text-sm font-bold text-white">Definir Apelido</p>
                  <p className="text-xs text-slate-400">Apenas você verá esse apelido no chat</p>
                </div>
              </div>

              <div className="flex gap-2">
                <input
                  value={nicknameInputVal}
                  onChange={(e) => setNicknameInputVal(e.target.value.slice(0, 40))}
                  placeholder="Novo apelido..."
                  autoFocus
                  className="flex-1 px-4 py-2.5 rounded-2xl bg-white/[0.06] border border-white/[0.08] text-sm text-white outline-none focus:border-sky-500"
                />
                <button
                  onClick={() => {
                    setNicknameForUser(nicknameInputVal.trim() || null);
                    setShowNicknameInput(false);
                    toast.success("Apelido salvo!");
                  }}
                  className="px-5 py-2.5 rounded-2xl bg-sky-600 hover:bg-sky-500 text-white text-xs font-bold transition-all"
                >
                  Salvar
                </button>
              </div>

              {otherNickname && (
                <button
                  onClick={() => {
                    setNicknameForUser(null);
                    setShowNicknameInput(false);
                    toast.success("Apelido removido");
                  }}
                  className="w-full py-2.5 rounded-2xl text-xs font-bold text-rose-400 bg-rose-500/10 hover:bg-rose-500/20 transition-all"
                >
                  Remover Apelido
                </button>
              )}

              <button
                onClick={() => setShowNicknameInput(false)}
                className="w-full py-2.5 rounded-2xl text-xs font-bold text-slate-400 hover:text-white bg-white/[0.04] transition-all"
              >
                Cancelar
              </button>
            </motion.div>
          </>
        )}
      </AnimatePresence>

      {/* Wallpaper Picker Modal */}
      <AnimatePresence>
        {showBgPicker && (
          <>
            <motion.div
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              exit={{ opacity: 0 }}
              onClick={() => setShowBgPicker(false)}
              className="fixed inset-0 z-50 bg-black/70 backdrop-blur-sm"
            />
            <motion.div
              initial={{ y: "100%", opacity: 0 }}
              animate={{ y: 0, opacity: 1 }}
              exit={{ y: "100%", opacity: 0 }}
              transition={{ type: "spring", damping: 30, stiffness: 350 }}
              className="fixed bottom-0 left-0 right-0 z-50 mx-auto rounded-t-3xl p-5 bg-slate-900 border border-white/[0.08] max-w-lg space-y-4 max-h-[85vh] overflow-y-auto"
            >
              <div className="w-10 h-1 rounded-full mx-auto bg-white/20" />
              <div className="flex items-center gap-3">
                <div className="w-10 h-10 rounded-2xl bg-purple-500/20 text-purple-400 flex items-center justify-center">
                  <Palette className="w-5 h-5" />
                </div>
                <div>
                  <p className="text-sm font-bold text-white">Tema do Chat</p>
                  <p className="text-xs text-slate-400">Personalize cores e imagem de fundo da conversa</p>
                </div>
              </div>

              {/* Gradient Presets */}
              <div className="space-y-2">
                <p className="text-[10px] font-bold uppercase tracking-wider text-slate-400">Gradientes</p>
                <div className="flex flex-wrap gap-2">
                  {[
                    "linear-gradient(135deg, #0284c7 0%, #2563eb 100%)",
                    "linear-gradient(135deg, #059669 0%, #10b981 100%)",
                    "linear-gradient(135deg, #7c3aed 0%, #9333ea 100%)",
                    "linear-gradient(135deg, #e11d48 0%, #f43f5e 100%)",
                    "linear-gradient(135deg, #d97706 0%, #f59e0b 100%)",
                    "linear-gradient(135deg, #0f172a 0%, #1e293b 100%)",
                  ].map((grad, i) => (
                    <button
                      key={i}
                      onClick={() => {
                        setBgGradient(grad);
                        setBgImage(null);
                        if (id && user) {
                          supabase.from("conversation_backgrounds").upsert(
                            { conversation_id: id, background_id: null, custom_gradient: grad, set_by: user.id },
                            { onConflict: "conversation_id" }
                          );
                        }
                        setShowBgPicker(false);
                      }}
                      className="w-11 h-11 rounded-2xl border border-white/10 hover:scale-105 transition-all"
                      style={{ background: grad }}
                    />
                  ))}
                </div>
              </div>

              {/* Reset to Default */}
              <button
                onClick={removeWallpaper}
                className="w-full py-2.5 rounded-2xl text-xs font-bold text-rose-400 bg-rose-500/10 hover:bg-rose-500/20 transition-all"
              >
                Restaurar Tema Padrão
              </button>

              <button
                onClick={() => setShowBgPicker(false)}
                className="w-full py-2.5 rounded-2xl text-xs font-bold text-slate-400 hover:text-white bg-white/[0.04] transition-all"
              >
                Fechar
              </button>
            </motion.div>
          </>
        )}
      </AnimatePresence>

      <CameraCapture
        open={cameraOpen}
        onClose={() => setCameraOpen(false)}
        onCapture={(file) => {
          file.type.startsWith("video/") ? sendVideo(file) : sendImage(file, viewOnceMode);
        }}
      />

      <ChatMediaViewer
        src={mediaViewer?.src || null}
        type={mediaViewer?.type || "image"}
        onClose={() => setMediaViewer(null)}
      />
    </div>
  );
}
