import { useEffect, useRef, useState } from "react";
import { GitBranch, Plus, Search, X } from "lucide-react";
import { useChatConversations } from "../hooks/useChatConversations";
import { useChatPanel } from "../context/ChatPanelContext";
import { useMediaQuery } from "../hooks/useMediaQuery";
import { PullToRefresh } from "./PullToRefresh";
import { ChatConversationItem } from "./ChatConversationItem";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Skeleton } from "@/components/ui/skeleton";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import type { ChatConversationListItem } from "@paperclipai/shared";

interface ChatConversationListProps {
  companyId: string;
}

export function ChatConversationList({ companyId }: ChatConversationListProps) {
  const { activeConversationId, setActiveConversationId } = useChatPanel();

  const [searchTerm, setSearchTerm] = useState("");
  const [debouncedSearch, setDebouncedSearch] = useState("");
  const searchInputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    const timer = setTimeout(() => setDebouncedSearch(searchTerm), 300);
    return () => clearTimeout(timer);
  }, [searchTerm]);

  // Listen for focus-chat-search custom event (dispatched by Cmd+K in Layout)
  useEffect(() => {
    const handler = () => searchInputRef.current?.focus();
    window.addEventListener("nexus:focus-chat-search", handler);
    return () => window.removeEventListener("nexus:focus-chat-search", handler);
  }, []);

  const isMobile = !useMediaQuery("(min-width: 768px)");
  const { data, isLoading, hasNextPage, fetchNextPage, createMutation, updateMutation, deleteMutation, refetch } =
    useChatConversations(companyId, { search: debouncedSearch || undefined });

  const [deletingId, setDeletingId] = useState<string | null>(null);
  const sentinelRef = useRef<HTMLDivElement>(null);

  // Infinite scroll via IntersectionObserver
  useEffect(() => {
    const sentinel = sentinelRef.current;
    if (!sentinel) return;

    const observer = new IntersectionObserver(
      (entries) => {
        if (entries[0]?.isIntersecting && hasNextPage) {
          void fetchNextPage();
        }
      },
      { threshold: 0.1 },
    );

    observer.observe(sentinel);
    return () => observer.disconnect();
  }, [hasNextPage, fetchNextPage]);

  const allConversations: ChatConversationListItem[] =
    data?.pages.flatMap((p) => p.items) ?? [];

  // Separate pinned from unpinned
  const pinned = allConversations
    .filter((c) => c.pinnedAt)
    .sort((a, b) => (b.pinnedAt! > a.pinnedAt! ? 1 : -1));
  const unpinned = allConversations
    .filter((c) => !c.pinnedAt)
    .sort((a, b) => (b.updatedAt > a.updatedAt ? 1 : -1));

  const sorted = [...pinned, ...unpinned];

  const handleNewConversation = async () => {
    try {
      const newConvo = await createMutation.mutateAsync(undefined);
      setActiveConversationId(newConvo.id);
    } catch {
      // ignore -- error will surface via mutation state if needed
    }
  };

  const handleRename = (id: string, title: string) => {
    updateMutation.mutate({ id, title });
  };

  const handlePin = (id: string, pinned: boolean) => {
    updateMutation.mutate({ id, pinnedAt: pinned ? new Date().toISOString() : null });
  };

  const handleArchive = (id: string) => {
    updateMutation.mutate({ id, archivedAt: new Date().toISOString() });
  };

  const handleDeleteRequest = (id: string) => {
    setDeletingId(id);
  };

  const handleDeleteConfirm = () => {
    if (!deletingId) return;
    deleteMutation.mutate(deletingId, {
      onSuccess: () => {
        if (activeConversationId === deletingId) {
          setActiveConversationId(null);
        }
        setDeletingId(null);
      },
    });
  };

  return (
    <div className="flex flex-col h-full">
      {/* New conversation button */}
      <div className="p-2 border-b border-border">
        <Button
          variant="ghost"
          size="sm"
          className="w-full text-xs justify-start gap-1"
          onClick={handleNewConversation}
          disabled={createMutation.isPending}
        >
          <Plus className="h-3.5 w-3.5" />
          New conversation
        </Button>
      </div>

      {/* Search input */}
      <div className="px-2 pb-1 pt-1">
        <div className="relative">
          <Search className="absolute left-2 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground" />
          <Input
            ref={searchInputRef}
            value={searchTerm}
            onChange={(e) => setSearchTerm(e.target.value)}
            placeholder="Search conversations..."
            className="h-7 pl-7 pr-7 text-xs"
          />
          {searchTerm && (
            <button
              type="button"
              onClick={() => setSearchTerm("")}
              className="absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground"
            >
              <X className="h-3 w-3" />
            </button>
          )}
        </div>
      </div>

      <PullToRefresh onRefresh={() => { void refetch(); }} enabled={isMobile}>
        <ScrollArea className="flex-1">
          <div className="p-1 space-y-0.5">
            {isLoading ? (
              // Loading skeletons
              Array.from({ length: 5 }).map((_, i) => (
                <Skeleton key={i} className="h-10 w-full rounded" />
              ))
            ) : sorted.length === 0 ? (
              <div className="p-4 text-center">
                <p className="text-xs text-muted-foreground">No conversations yet</p>
                <p className="text-xs text-muted-foreground mt-1">
                  Start a conversation to get help from your agents.
                </p>
              </div>
            ) : (
              sorted.map((conversation) => (
                <div key={conversation.id} className="relative">
                  {conversation.parentConversationId && (
                    <GitBranch className="absolute left-1 top-1/2 -translate-y-1/2 h-3 w-3 text-muted-foreground pointer-events-none z-10" />
                  )}
                  <div className={conversation.parentConversationId ? "pl-4" : undefined}>
                    <ChatConversationItem
                      conversation={conversation}
                      isActive={activeConversationId === conversation.id}
                      onSelect={setActiveConversationId}
                      onRename={handleRename}
                      onPin={handlePin}
                      onArchive={handleArchive}
                      onDelete={handleDeleteRequest}
                    />
                  </div>
                </div>
              ))
            )}

            {/* Infinite scroll sentinel */}
            <div ref={sentinelRef} className="h-1" />
          </div>
        </ScrollArea>
      </PullToRefresh>

      {/* Delete confirmation dialog */}
      <Dialog open={!!deletingId} onOpenChange={(open) => !open && setDeletingId(null)}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Delete conversation?</DialogTitle>
            <DialogDescription>
              This conversation and all its messages will be permanently deleted.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button variant="outline" onClick={() => setDeletingId(null)}>
              Keep conversation
            </Button>
            <Button
              variant="destructive"
              onClick={handleDeleteConfirm}
              disabled={deleteMutation.isPending}
            >
              Delete
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}
