"use client";

import { useState, useMemo, useCallback, useRef, useEffect, Fragment } from "react";
import { useQuery, keepPreviousData } from "@tanstack/react-query";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Input } from "@/components/ui/input";
import {
  ChevronLeft,
  ChevronRight,
  ChevronDown,
  Search,
  MessageSquare,
  X,
  User,
  Bot,
  Loader2,
} from "lucide-react";
import { formatDate } from "@/lib/utils";
import {
  LibreChatConversation,
  LibreChatUser,
  LibreChatMessage,
} from "@/lib/types";

// Hook debounce personnalisé
function useDebounce<T>(value: T, delay: number): T {
  const [debouncedValue, setDebouncedValue] = useState<T>(value);

  useEffect(() => {
    const timer = setTimeout(() => setDebouncedValue(value), delay);
    return () => clearTimeout(timer);
  }, [value, delay]);

  return debouncedValue;
}

// Types pour les messages étendus
interface ExtendedMessage extends LibreChatMessage {
  content?: Array<{ type: string; text: string }> | string;
  parts?: Array<string | { text: string }>;
  [key: string]: unknown;
}

// Type pour les groupes d'utilisateurs
interface UserGroup {
  userId: string;
  conversations: LibreChatConversation[];
  totalMessages: number;
}

// Fetcher générique
async function fetchCollection<T>(
  collection: string,
  params: Record<string, string | number>
): Promise<{ data: T[]; total: number; totalPages: number }> {
  const searchParams = new URLSearchParams();
  Object.entries(params).forEach(([key, value]) => {
    if (value !== undefined && value !== "") {
      searchParams.set(key, String(value));
    }
  });

  const url = `/api/collections/${collection}?${searchParams}`;
  console.log("[fetchCollection]", collection, "URL:", url);

  const response = await fetch(url);
  if (!response.ok) throw new Error(`Erreur lors du chargement de ${collection}`);
  const data = await response.json();
  console.log("[fetchCollection]", collection, "Results:", data.data?.length, "items");
  return data;
}

export function ConversationsTable() {
  const [page, setPage] = useState(1);
  const [searchInput, setSearchInput] = useState("");
  const [expandedUsers, setExpandedUsers] = useState<Set<string>>(new Set());
  const [expandedConversation, setExpandedConversation] = useState<string | null>(null);
  const searchInputRef = useRef<HTMLInputElement>(null);

  const usersPerPage = 10; // Nombre de groupes d'utilisateurs par page
  const debouncedSearch = useDebounce(searchInput, 250);

  // Reset page et expanded states quand la recherche change
  useEffect(() => {
    setPage(1);
    setExpandedUsers(new Set());
    setExpandedConversation(null);
  }, [debouncedSearch]);

  // Query conversations avec TanStack Query - limite élevée pour groupement client
  const {
    data: conversationsData,
    isLoading: conversationsLoading,
    isFetching: conversationsFetching,
  } = useQuery({
    queryKey: ["conversations", debouncedSearch],
    queryFn: () =>
      fetchCollection<LibreChatConversation>("conversations", {
        page: 1,
        limit: 1000, // Charger beaucoup pour grouper côté client
        search: debouncedSearch,
      }),
    placeholderData: keepPreviousData,
    staleTime: 30000, // 30 secondes
  });

  // Query users (cache long car ça change rarement)
  const { data: usersData } = useQuery({
    queryKey: ["users", "all"],
    queryFn: () => fetchCollection<LibreChatUser>("users", { limit: 1000 }),
    staleTime: 1000 * 60 * 5, // 5 minutes
  });

  // Query messages de la conversation sélectionnée
  const { data: messagesData, isLoading: messagesLoading } = useQuery({
    queryKey: ["messages", expandedConversation],
    queryFn: () =>
      fetchCollection<LibreChatMessage>("messages", {
        limit: 500,
        filter: JSON.stringify({ conversationId: expandedConversation }),
      }),
    enabled: !!expandedConversation,
    staleTime: 30000,
  });

  const conversations = conversationsData?.data ?? [];
  const total = conversationsData?.total ?? 0;
  const users = usersData?.data ?? [];
  const messages = messagesData?.data ?? [];

  // Map des users pour lookup rapide
  const userMap = useMemo(() => new Map(users.map((u) => [u._id, u])), [users]);

  // Grouper les conversations par utilisateur
  const groupedByUser = useMemo((): UserGroup[] => {
    const groups: Record<string, LibreChatConversation[]> = {};
    conversations.forEach((conv) => {
      const uId = String(conv.user);
      if (!groups[uId]) groups[uId] = [];
      groups[uId].push(conv);
    });
    return Object.entries(groups)
      .map(([userId, convs]) => ({
        userId,
        conversations: convs.sort(
          (a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()
        ),
        totalMessages: convs.reduce((sum, c) => sum + (c.messages?.length || 0), 0),
      }))
      .sort((a, b) => {
        // Trier par date de dernière conversation
        const aDate = new Date(a.conversations[0]?.updatedAt || 0).getTime();
        const bDate = new Date(b.conversations[0]?.updatedAt || 0).getTime();
        return bDate - aDate;
      });
  }, [conversations]);

  // Pagination sur les groupes d'utilisateurs
  const totalUserGroups = groupedByUser.length;
  const totalPages = Math.ceil(totalUserGroups / usersPerPage);
  const paginatedGroups = groupedByUser.slice(
    (page - 1) * usersPerPage,
    page * usersPerPage
  );

  // Toggle user group expansion
  const toggleUserExpanded = useCallback((userId: string) => {
    setExpandedUsers((prev) => {
      const next = new Set(prev);
      if (next.has(userId)) {
        next.delete(userId);
        // Fermer aussi la conversation si elle appartient à cet utilisateur
        setExpandedConversation(null);
      } else {
        next.add(userId);
      }
      return next;
    });
  }, []);

  // Toggle conversation expansion
  const toggleConversationExpanded = useCallback((conversationId: string) => {
    console.log("[Conversations] Toggle conversation:", conversationId);
    setExpandedConversation((prev) =>
      prev === conversationId ? null : conversationId
    );
  }, []);

  const getUserInfo = useCallback(
    (userId: string) => {
      const user = userMap.get(userId);
      return {
        name: user?.name || user?.username || `User ${userId.slice(-6)}`,
        email: user?.email || null,
      };
    },
    [userMap]
  );

  // Extraction du contenu des messages
  const getMessageContent = useCallback((message: LibreChatMessage): string => {
    const msg = message as ExtendedMessage;

    if (msg.content && Array.isArray(msg.content)) {
      for (const item of msg.content) {
        if (item?.text) return item.text.trim();
      }
    }
    if (message.text?.trim()) return message.text.trim();
    if (typeof msg.content === "string" && msg.content.trim()) return msg.content.trim();
    if (msg.parts?.[0]) {
      const part = msg.parts[0];
      if (typeof part === "string") return part.trim();
      if (part?.text) return part.text.trim();
    }
    return "Contenu non disponible";
  }, []);

  const clearSearch = () => {
    setSearchInput("");
    searchInputRef.current?.focus();
  };

  const isSearching = searchInput !== debouncedSearch || conversationsFetching;

  return (
    <div className="space-y-4">
      <Card>
        <CardHeader className="pb-4">
          <div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
            <CardTitle className="flex items-center gap-2">
              <MessageSquare className="h-5 w-5" />
              Conversations
              <Badge variant="secondary" className="ml-2">
                {total}
              </Badge>
              {conversationsFetching && !conversationsLoading && (
                <Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
              )}
            </CardTitle>

            {/* Barre de recherche */}
            <div className="relative w-full sm:w-96">
              <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
              <Input
                ref={searchInputRef}
                placeholder="Rechercher par nom ou email..."
                value={searchInput}
                onChange={(e) => setSearchInput(e.target.value)}
                className="pl-10 pr-10"
              />
              <div className="absolute right-3 top-1/2 -translate-y-1/2">
                {isSearching ? (
                  <Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
                ) : searchInput ? (
                  <button
                    onClick={clearSearch}
                    className="text-muted-foreground hover:text-foreground transition-colors"
                    type="button"
                  >
                    <X className="h-4 w-4" />
                  </button>
                ) : null}
              </div>
            </div>
          </div>

          {debouncedSearch && (
            <p className="text-sm text-muted-foreground mt-2">
              {total} résultat{total > 1 ? "s" : ""} pour &quot;{debouncedSearch}&quot;
            </p>
          )}
        </CardHeader>

        <CardContent>
          {conversationsLoading ? (
            <div className="space-y-3">
              {Array.from({ length: 5 }).map((_, i) => (
                <div key={i} className="h-14 bg-muted animate-pulse rounded-lg" />
              ))}
            </div>
          ) : conversations.length === 0 ? (
            <div className="text-center py-12 text-muted-foreground">
              {debouncedSearch ? (
                <>
                  <Search className="h-12 w-12 mx-auto mb-4 opacity-20" />
                  <p>Aucun résultat pour &quot;{debouncedSearch}&quot;</p>
                  <Button variant="link" onClick={clearSearch} className="mt-2">
                    Effacer la recherche
                  </Button>
                </>
              ) : (
                <p>Aucune conversation</p>
              )}
            </div>
          ) : (
            <>
              {/* Liste des groupes d'utilisateurs */}
              <div className="space-y-2">
                {paginatedGroups.map((group) => {
                  const userInfo = getUserInfo(group.userId);
                  const isUserExpanded = expandedUsers.has(group.userId);

                  return (
                    <div key={group.userId} className="border rounded-lg overflow-hidden">
                      {/* Header du groupe utilisateur */}
                      <button
                        onClick={() => toggleUserExpanded(group.userId)}
                        className="w-full flex items-center gap-3 p-4 bg-muted/30 hover:bg-muted/50 transition-colors text-left"
                      >
                        <ChevronDown
                          className={`h-5 w-5 text-muted-foreground transition-transform flex-shrink-0 ${
                            isUserExpanded ? "rotate-0" : "-rotate-90"
                          }`}
                        />
                        <div className="flex-1 min-w-0">
                          <div className="flex items-center gap-2 flex-wrap">
                            <span className="font-semibold">{userInfo.name}</span>
                            {userInfo.email && (
                              <span className="text-sm text-muted-foreground">
                                ({userInfo.email})
                              </span>
                            )}
                          </div>
                        </div>
                        <div className="flex items-center gap-2 flex-shrink-0">
                          <Badge variant="secondary">
                            {group.conversations.length} conversation{group.conversations.length > 1 ? "s" : ""}
                          </Badge>
                          <Badge variant="outline" className="text-xs">
                            {group.totalMessages} msg{group.totalMessages > 1 ? "s" : ""}
                          </Badge>
                        </div>
                      </button>

                      {/* Liste des conversations de l'utilisateur */}
                      {isUserExpanded && (
                        <div className="border-t">
                          {group.conversations.map((conv) => {
                            const msgCount = conv.messages?.length || 0;
                            const isConvExpanded = expandedConversation === conv.conversationId;

                            return (
                              <Fragment key={conv._id}>
                                <button
                                  onClick={() => toggleConversationExpanded(conv.conversationId)}
                                  className={`w-full flex items-center gap-3 p-3 pl-10 hover:bg-muted/30 transition-colors text-left border-b last:border-b-0 ${
                                    isConvExpanded ? "bg-muted/20" : ""
                                  }`}
                                >
                                  <ChevronDown
                                    className={`h-4 w-4 text-muted-foreground transition-transform flex-shrink-0 ${
                                      isConvExpanded ? "rotate-0" : "-rotate-90"
                                    }`}
                                  />
                                  <div className="flex-1 min-w-0">
                                    <span className="truncate block text-sm font-medium">
                                      {String(conv.title) || "Sans titre"}
                                    </span>
                                  </div>
                                  <div className="flex items-center gap-2 flex-shrink-0">
                                    <Badge variant="outline" className="text-xs font-mono">
                                      {String(conv.endpoint).slice(0, 8)}
                                    </Badge>
                                    <Badge variant="secondary" className="text-xs">
                                      {msgCount} msg{msgCount > 1 ? "s" : ""}
                                    </Badge>
                                    <Badge
                                      variant={conv.isArchived ? "outline" : "default"}
                                      className="text-xs"
                                    >
                                      {conv.isArchived ? "Archivée" : "Active"}
                                    </Badge>
                                    <span className="text-xs text-muted-foreground">
                                      {formatDate(conv.updatedAt)}
                                    </span>
                                  </div>
                                </button>

                                {/* Messages de la conversation */}
                                {isConvExpanded && (
                                  <div className="bg-slate-50 p-4 pl-14 border-b">
                                    {messagesLoading ? (
                                      <div className="flex items-center justify-center py-8 gap-2 text-muted-foreground">
                                        <Loader2 className="h-5 w-5 animate-spin" />
                                        <span>Chargement des messages...</span>
                                      </div>
                                    ) : messages.length === 0 ? (
                                      <p className="text-center py-8 text-muted-foreground">
                                        Aucun message dans cette conversation
                                      </p>
                                    ) : (
                                      <div className="space-y-3 max-h-[400px] overflow-y-auto">
                                        {messages
                                          .sort(
                                            (a, b) =>
                                              new Date(a.createdAt).getTime() -
                                              new Date(b.createdAt).getTime()
                                          )
                                          .map((msg) => {
                                            const content = getMessageContent(msg);
                                            const isUser = msg.isCreatedByUser;

                                            return (
                                              <div
                                                key={msg._id}
                                                className={`flex gap-3 p-3 rounded-lg border-l-4 ${
                                                  isUser
                                                    ? "bg-blue-50 border-l-blue-500"
                                                    : "bg-white border-l-gray-300"
                                                }`}
                                              >
                                                <div className="flex-shrink-0 mt-0.5">
                                                  {isUser ? (
                                                    <User className="h-4 w-4 text-blue-600" />
                                                  ) : (
                                                    <Bot className="h-4 w-4 text-gray-500" />
                                                  )}
                                                </div>
                                                <div className="flex-1 min-w-0">
                                                  <div className="flex items-center gap-2 mb-1 flex-wrap">
                                                    <span className="text-xs font-medium">
                                                      {isUser ? "Utilisateur" : "Assistant"}
                                                    </span>
                                                    <span className="text-xs text-muted-foreground">
                                                      {formatDate(msg.createdAt)}
                                                    </span>
                                                    {msg.tokenCount > 0 && (
                                                      <span className="text-xs text-muted-foreground">
                                                        ({msg.tokenCount} tokens)
                                                      </span>
                                                    )}
                                                  </div>
                                                  <div className="text-sm whitespace-pre-wrap break-words">
                                                    {content}
                                                  </div>
                                                </div>
                                              </div>
                                            );
                                          })}
                                      </div>
                                    )}
                                  </div>
                                )}
                              </Fragment>
                            );
                          })}
                        </div>
                      )}
                    </div>
                  );
                })}
              </div>

              {/* Pagination */}
              {totalPages > 1 && (
                <div className="flex items-center justify-between mt-4">
                  <p className="text-sm text-muted-foreground">
                    Page {page} / {totalPages} ({totalUserGroups} utilisateurs)
                  </p>
                  <div className="flex gap-2">
                    <Button
                      variant="outline"
                      size="sm"
                      onClick={() => setPage((p) => Math.max(1, p - 1))}
                      disabled={page === 1}
                    >
                      <ChevronLeft className="h-4 w-4" />
                      Préc.
                    </Button>
                    <Button
                      variant="outline"
                      size="sm"
                      onClick={() => setPage((p) => Math.min(totalPages, p + 1))}
                      disabled={page === totalPages}
                    >
                      Suiv.
                      <ChevronRight className="h-4 w-4" />
                    </Button>
                  </div>
                </div>
              )}
            </>
          )}
        </CardContent>
      </Card>
    </div>
  );
}
