import { useEffect, useState, useCallback, useRef, useMemo } from "react";
import { useNavigate } from "react-router-dom";
import { Search, Loader2, MessageSquare, Trash2, PenLine, Sparkles, Check, CheckCheck } from "lucide-react";
import { motion, AnimatePresence } from "framer-motion";
import { useQueryClient } from "@tanstack/react-query";
import { supabase } from "@/integrations/supabase/client";
import { useAuth } from "@/hooks/useAuth";
import AppLayout from "@/components/AppLayout";
import Avatar from "@/components/Avatar";
import RGBName from "@/components/RGBName";
import VerifiedBadge from "@/components/VerifiedBadge";
import NotesBar from "@/components/NotesBar";
import { isOnline } from "@/hooks/usePresence";
import { formatDistanceToNow } from "date-fns";
import { ptBR } from "date-fns/locale";
import { queryInChunksByField, getUnreadCountsByIds } from "@/lib/chunkedQueries";
import { toast } from "sonner";
import { cn } from "@/lib/utils";

export const MESSAGES_QUERY_KEY = ["messages-convs"];

interface ProfileLite {
  id: string;
  display_name: string | null;
  photo_url: string | null;
  username: string | null;
  last_seen_at?: string | null;
  show_activity?: boolean | null;
  is_verified?: boolean;
  profile_theme?: any;
}

interface ConvRow {
  id: string;
  last_message_at: string | null;
  other: ProfileLite | null;
  last: { content: string | null; type: string; sender_id: string; created_at: string } | null;
  unread: number;
}

interface ConvMeta {
  id: string;
  last_message_at: string | null;
}

const chunkArray = <T,>(arr: T[], size: number): T[][] => {
  const chunks: T[][] = [];
  for (let i = 0; i < arr.length; i += size) chunks.push(arr.slice(i, i + size));
  return chunks;
};

export default function Messages() {
  const navigate = useNavigate();
  const { user } = useAuth();
  const [convs, setConvs] = useState<ConvRow[]>([]);
  const [loading, setLoading] = useState(true);
  const [search, setSearch] = useState("");
  const [users, setUsers] = useState<ProfileLite[]>([]);
  const [searching, setSearching] = useState(false);
  const [filterTab, setFilterTab] = useState<"all" | "unread">("all");
  const searchTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  const queryClient = useQueryClient();

  const load = useCallback(
    async (isSilent = false) => {
      if (!user) return;
      const cached = queryClient.getQueryData<ConvRow[]>(MESSAGES_QUERY_KEY);
      if (cached && cached.length > 0) {
        setConvs(cached);
        setLoading(false);
      } else if (!isSilent) {
        setLoading(true);
      }

      try {
        const { data: myParts } = await supabase
          .from("conversation_participants")
          .select("conversation_id")
          .eq("user_id", user.id);
        const convIds = (myParts || []).map((p) => p.conversation_id);
        if (!convIds.length) {
          setConvs([]);
          setLoading(false);
          return;
        }

        const [convData, unreadMap, { data: hiddenData }, otherParts] = await Promise.all([
          queryInChunksByField<any>(supabase, "conversations", "id", convIds, {
            select: "id, last_message_at",
            chunkSize: 200,
          }),
          getUnreadCountsByIds(supabase, user.id, convIds),
          supabase.from("conversation_hidden").select("conversation_id").eq("user_id", user.id),
          queryInChunksByField<any>(supabase, "conversation_participants", "conversation_id", convIds, {
            select: "conversation_id, user_id",
            chunkSize: 200,
          }),
        ]);

        if (!convData?.length) {
          setConvs([]);
          setLoading(false);
          return;
        }

        const hiddenSet = new Set((hiddenData || []).map((h: any) => h.conversation_id));
        const filteredParts = (otherParts || []).filter((p: any) => p.user_id !== user.id);
        const otherIdByConv = new Map<string, string>();
        for (const row of filteredParts) {
          if (!otherIdByConv.has(row.conversation_id)) otherIdByConv.set(row.conversation_id, row.user_id);
        }
        const otherIds = Array.from(new Set(Array.from(otherIdByConv.values())));

        const lastChunks = chunkArray(convIds, 100);
        const [lastResults, profileRows] = await Promise.all([
          Promise.all(
            lastChunks.map((chunk) =>
              supabase
                .from("messages")
                .select("id, conversation_id, content, type, sender_id, created_at")
                .in("conversation_id", chunk)
                .order("created_at", { ascending: false })
                .limit(chunk.length * 2)
                .then(({ data }) => data || [])
            )
          ).then((chunks) => chunks.flat()),
          otherIds.length
            ? queryInChunksByField<ProfileLite>(supabase, "profiles", "id", otherIds, {
                select: "id, display_name, photo_url, username, last_seen_at, show_activity, is_verified, profile_theme",
                chunkSize: 200,
              })
            : Promise.resolve([]),
        ]);

        const lastByConv = new Map<string, ConvRow["last"]>();
        for (const msg of lastResults) {
          if (!lastByConv.has(msg.conversation_id)) {
            lastByConv.set(msg.conversation_id, msg);
          }
        }

        const profileById = new Map<string, ProfileLite>();
        for (const p of profileRows) profileById.set(p.id, p);

        const rows: ConvRow[] = convData
          .filter((c: any) => !hiddenSet.has(c.id))
          .map((c: any) => {
            const oId = otherIdByConv.get(c.id);
            const otherProf = oId ? profileById.get(oId) || null : null;
            return {
              id: c.id,
              last_message_at: c.last_message_at,
              other: otherProf,
              last: lastByConv.get(c.id) || null,
              unread: unreadMap.get(c.id) || 0,
            };
          })
          .sort((a, b) => {
            const timeA = a.last_message_at ? new Date(a.last_message_at).getTime() : 0;
            const timeB = b.last_message_at ? new Date(b.last_message_at).getTime() : 0;
            return timeB - timeA;
          });

        setConvs(rows);
        queryClient.setQueryData(MESSAGES_QUERY_KEY, rows);
      } catch (err) {
        console.error("[Messages] Load error:", err);
      } finally {
        setLoading(false);
      }
    },
    [user, queryClient]
  );

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

  // ── Search Users ────────────────────────────────────────────────────────────
  const doSearch = (query: string) => {
    setSearch(query);
    if (searchTimeoutRef.current) clearTimeout(searchTimeoutRef.current);
    if (!query.trim()) {
      setUsers([]);
      setSearching(false);
      return;
    }
    setSearching(true);
    searchTimeoutRef.current = setTimeout(async () => {
      const q = query.trim();
      const { data } = await supabase
        .from("profiles")
        .select("id, display_name, photo_url, username, last_seen_at, show_activity, is_verified, profile_theme")
        .or(`username.ilike.%${q}%,display_name.ilike.%${q}%`)
        .limit(10);
      setUsers((data as ProfileLite[]) || []);
      setSearching(false);
    }, 250);
  };

  const startConv = async (targetId: string) => {
    if (!user) return;
    try {
      // Find existing
      const existing = convs.find((c) => c.other?.id === targetId);
      if (existing) {
        navigate(`/chat/${existing.id}`);
        return;
      }
      // Create new conversation
      const { data: conv, error } = await supabase
        .from("conversations")
        .insert({ user1_id: user.id, user2_id: targetId })
        .select()
        .single();
      if (error || !conv) throw error;

      await supabase.from("conversation_participants").insert([
        { conversation_id: conv.id, user_id: user.id },
        { conversation_id: conv.id, user_id: targetId },
      ]);

      navigate(`/chat/${conv.id}`);
    } catch (e: any) {
      toast.error(e.message || "Erro ao iniciar conversa");
    }
  };

  const hideConv = async (convId: string) => {
    if (!user) return;
    try {
      setConvs((prev) => prev.filter((c) => c.id !== convId));
      await supabase.from("conversation_hidden").insert({ conversation_id: convId, user_id: user.id });
      toast.success("Conversa removida");
    } catch (e: any) {
      toast.error(e.message || "Erro ao remover");
    }
  };

  const filteredConvs = useMemo(() => {
    let list = convs;
    if (filterTab === "unread") {
      list = list.filter((c) => c.unread > 0);
    }
    if (search.trim()) {
      const q = search.toLowerCase();
      list = list.filter(
        (c) =>
          c.other?.display_name?.toLowerCase().includes(q) ||
          c.other?.username?.toLowerCase().includes(q) ||
          c.last?.content?.toLowerCase().includes(q)
      );
    }
    return list;
  }, [convs, filterTab, search]);

  const preview = (c: ConvRow) => {
    if (!c.last) return "Nova conversa";
    const prefix = c.last.sender_id === user?.id ? "Você: " : "";
    switch (c.last.type) {
      case "image":
        return `${prefix}📷 Foto`;
      case "video":
        return `${prefix}🎬 Vídeo`;
      case "audio":
        return `${prefix}🎙️ Mensagem de voz`;
      case "sticker":
        return `${prefix}💫 Sticker`;
      default:
        return `${prefix}${c.last.content || "Mensagem"}`;
    }
  };

  return (
    <AppLayout>
      <div className="w-full space-y-5 pb-12">

        {/* ── Top Header with Actions ───────────────────────────────────── */}
        <div className="flex items-center justify-between px-1">
          <div>
            <h1 className="text-xl font-extrabold text-white tracking-tight flex items-center gap-2">
              Mensagens
              {convs.length > 0 && (
                <span className="px-2.5 py-0.5 rounded-full bg-sky-600/20 text-sky-400 text-xs font-bold border border-sky-500/30">
                  {convs.length}
                </span>
              )}
            </h1>
            <p className="text-xs text-slate-400 mt-0.5">Suas conversas diretas e em grupo</p>
          </div>

          <button
            onClick={() => {
              const el = document.getElementById("chat-search-input");
              el?.focus();
            }}
            className="flex items-center gap-2 px-4 py-2 rounded-2xl bg-sky-600 hover:bg-sky-500 text-white text-xs font-bold transition-all shadow-md shadow-sky-600/25 active:scale-95"
          >
            <PenLine className="w-4 h-4" />
            <span>Nova Mensagem</span>
          </button>
        </div>

        {/* ── Search Bar ────────────────────────────────────────────────── */}
        <div className="relative">
          <Search className="absolute left-4 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-400" />
          <input
            id="chat-search-input"
            value={search}
            onChange={(e) => doSearch(e.target.value)}
            placeholder="Buscar conversas ou pessoas..."
            className="w-full h-11 pl-11 pr-4 rounded-2xl bg-slate-900/90 border border-white/[0.08] text-xs text-white placeholder:text-slate-500 outline-none focus:border-sky-500/50 focus:ring-2 focus:ring-sky-500/20 transition-all"
          />
        </div>

        {/* ── Search Results Dropdown ───────────────────────────────────── */}
        <AnimatePresence>
          {search && users.length > 0 && (
            <motion.div
              initial={{ opacity: 0, y: -6 }}
              animate={{ opacity: 1, y: 0 }}
              exit={{ opacity: 0, y: -6 }}
              className="bg-slate-900 rounded-2xl border border-white/[0.08] overflow-hidden shadow-2xl p-2 space-y-1"
            >
              <p className="text-[10px] font-bold uppercase tracking-wider text-slate-400 px-3 py-1.5">
                Usuários Encontrados
              </p>
              {users.map((u) => (
                <button
                  key={u.id}
                  onClick={() => {
                    setSearch("");
                    setUsers([]);
                    startConv(u.id);
                  }}
                  className="flex items-center gap-3 w-full p-2.5 rounded-xl text-left hover:bg-white/[0.05] transition-all"
                >
                  <Avatar url={u.photo_url} name={u.display_name || u.username} size="sm" />
                  <div className="min-w-0 flex-1">
                    <p className="text-xs font-bold text-white truncate flex items-center gap-1">
                      <RGBName name={u.display_name || u.username || "Usuário"} profile_theme={u.profile_theme} />
                      {u.is_verified && <VerifiedBadge size="xxs" />}
                    </p>
                    <p className="text-[11px] text-slate-400 truncate">@{u.username || "perfil"}</p>
                  </div>
                </button>
              ))}
            </motion.div>
          )}
        </AnimatePresence>

        {/* ── Notes Horizontal Bar ──────────────────────────────────────── */}
        <div className="space-y-1">
          <NotesBar />
        </div>

        {/* ── Filter Tabs (Todas / Não Lidas) ───────────────────────────── */}
        <div className="flex items-center gap-2">
          <button
            onClick={() => setFilterTab("all")}
            className={cn(
              "px-4 py-1.5 rounded-xl text-xs font-bold transition-all",
              filterTab === "all"
                ? "bg-sky-600 text-white shadow-md shadow-sky-600/30"
                : "text-slate-400 hover:text-white bg-white/[0.04] hover:bg-white/[0.08]"
            )}
          >
            Todas
          </button>
          <button
            onClick={() => setFilterTab("unread")}
            className={cn(
              "flex items-center gap-1.5 px-4 py-1.5 rounded-xl text-xs font-bold transition-all",
              filterTab === "unread"
                ? "bg-sky-600 text-white shadow-md shadow-sky-600/30"
                : "text-slate-400 hover:text-white bg-white/[0.04] hover:bg-white/[0.08]"
            )}
          >
            <span>Não Lidas</span>
            {convs.filter((c) => c.unread > 0).length > 0 && (
              <span className="px-1.5 py-0.2 rounded-full bg-white text-sky-600 font-bold text-[10px]">
                {convs.filter((c) => c.unread > 0).length}
              </span>
            )}
          </button>
        </div>

        {/* ── Conversation Rows ─────────────────────────────────────────── */}
        {loading ? (
          <div className="flex flex-col items-center justify-center py-20 gap-3">
            <Loader2 className="w-7 h-7 text-sky-400 animate-spin" />
            <p className="text-xs text-slate-400">Carregando mensagens...</p>
          </div>
        ) : filteredConvs.length === 0 ? (
          <div className="text-center py-16 space-y-3">
            <div className="w-14 h-14 mx-auto rounded-3xl bg-slate-900 border border-white/[0.08] flex items-center justify-center text-sky-400">
              <MessageSquare className="w-7 h-7" />
            </div>
            <div>
              <p className="text-sm font-bold text-white">
                {filterTab === "unread" ? "Tudo em dia!" : "Nenhuma conversa ainda"}
              </p>
              <p className="text-xs text-slate-400 max-w-xs mx-auto mt-1">
                {filterTab === "unread"
                  ? "Você leu todas as mensagens recebidas."
                  : "Conecte-se e mande uma mensagem para começar a conversar!"}
              </p>
            </div>
          </div>
        ) : (
          <div className="space-y-1">
            <AnimatePresence mode="popLayout">
              {filteredConvs.map((c) => {
                const online = c.other?.show_activity !== false && isOnline(c.other?.last_seen_at);
                const hasUnread = c.unread > 0;

                return (
                  <motion.div
                    key={c.id}
                    layout
                    initial={{ opacity: 0, y: 6 }}
                    animate={{ opacity: 1, y: 0 }}
                    exit={{ opacity: 0, scale: 0.96 }}
                    className="relative group rounded-2xl overflow-hidden hover:bg-slate-900/60 transition-all border border-transparent hover:border-white/[0.06]"
                  >
                    <button
                      onClick={() => navigate(`/chat/${c.id}`)}
                      className="flex items-center gap-3.5 w-full p-3.5 text-left"
                    >
                      {/* Avatar with Online Status */}
                      <div className="relative shrink-0">
                        <Avatar url={c.other?.photo_url} name={c.other?.display_name || c.other?.username} size="md" />
                        {online && (
                          <span className="absolute bottom-0 right-0 w-3 h-3 bg-emerald-500 rounded-full ring-2 ring-slate-950 shadow-sm" />
                        )}
                      </div>

                      {/* Content Info */}
                      <div className="min-w-0 flex-1">
                        <div className="flex items-center justify-between gap-2 mb-0.5">
                          <span className="font-bold text-xs text-white truncate flex items-center gap-1.5">
                            <RGBName
                              name={c.other?.display_name || c.other?.username || "Conversa"}
                              profile_theme={c.other?.profile_theme}
                            />
                            {c.other?.is_verified && <VerifiedBadge size="xxs" />}
                          </span>
                          {c.last_message_at && (
                            <span
                              className={cn(
                                "text-[11px] shrink-0 font-medium",
                                hasUnread ? "text-sky-400 font-bold" : "text-slate-400"
                              )}
                            >
                              {formatDistanceToNow(new Date(c.last_message_at), { addSuffix: false, locale: ptBR })}
                            </span>
                          )}
                        </div>

                        <div className="flex items-center justify-between gap-3">
                          <p
                            className={cn(
                              "text-xs truncate flex-1 leading-relaxed",
                              hasUnread ? "font-semibold text-slate-100" : "text-slate-400"
                            )}
                          >
                            {preview(c)}
                          </p>

                          {hasUnread && (
                            <span className="px-2 py-0.5 rounded-full bg-sky-500 text-white font-bold text-[10px] shrink-0 shadow-sm shadow-sky-500/40">
                              {c.unread > 99 ? "99+" : c.unread}
                            </span>
                          )}
                        </div>
                      </div>
                    </button>

                    {/* Delete conversation action on hover */}
                    <button
                      onClick={(e) => {
                        e.stopPropagation();
                        hideConv(c.id);
                      }}
                      className="absolute right-3 top-1/2 -translate-y-1/2 opacity-0 group-hover:opacity-100 p-2 rounded-xl bg-rose-500/10 text-rose-400 hover:bg-rose-500/20 transition-all"
                      title="Excluir conversa"
                    >
                      <Trash2 className="w-4 h-4" />
                    </button>
                  </motion.div>
                );
              })}
            </AnimatePresence>
          </div>
        )}
      </div>
    </AppLayout>
  );
}