import { useState, useEffect, useCallback, useMemo } from "react";
import { useParams, useNavigate } from "react-router";
import { Plus, MessageSquare, Bot } from "lucide-react";
import { motion, AnimatePresence } from "motion/react";
import { client } from "@/client";
import type { ConversationWithSessionResponse } from "@/client/models/conversationWithSessionResponse";
import { Shimmer } from "@/components/ai-elements/shimmer";
import { ChatItem } from "./chat/chat-item";
import { useWorkspaceSessions } from "./chat/use-sessions";
import { ensureWorkspaceSession } from "./chat/use-session";


const SKELETON_COUNT = 3;

interface GroupedConversations {
  today: ConversationWithSessionResponse[];
  yesterday: ConversationWithSessionResponse[];
  recent: ConversationWithSessionResponse[];
  older: ConversationWithSessionResponse[];
}

function groupConversations(
  convs: ConversationWithSessionResponse[],
): GroupedConversations {
  const now = new Date();
  const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
  const yesterday = new Date(today);
  yesterday.setDate(yesterday.getDate() - 1);
  const sevenDaysAgo = new Date(today);
  sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);

  const groups: GroupedConversations = {
    today: [],
    yesterday: [],
    recent: [],
    older: [],
  };

  for (const conv of convs) {
    const date = new Date(conv.last_message_at || conv.created_at);
    const d = new Date(date.getFullYear(), date.getMonth(), date.getDate());

    if (d.getTime() === today.getTime()) {
      groups.today.push(conv);
    } else if (d.getTime() === yesterday.getTime()) {
      groups.yesterday.push(conv);
    } else if (d.getTime() >= sevenDaysAgo.getTime()) {
      groups.recent.push(conv);
    } else {
      groups.older.push(conv);
    }
  }

  return groups;
}

export function WorkplanChatSidebar() {
  const { projectName = "", conversationId } = useParams();
  const navigate = useNavigate();
  const [conversations, setConversations] = useState<
    ConversationWithSessionResponse[]
  >([]);
  const [loadingConvs, setLoadingConvs] = useState(true);
  const { sessionsRef } = useWorkspaceSessions(projectName);

  const loadConversations = useCallback(async () => {
    try {
      setLoadingConvs(true);
      const convsRes = await client
        .agentListAllConversations({ wk: projectName })
        .catch(() => ({
          data: [] as ConversationWithSessionResponse[],
        }));

      const sorted = [...convsRes.data].sort((a, b) => {
        const da = a.last_message_at
          ? new Date(a.last_message_at).getTime()
          : new Date(a.created_at).getTime();
        const db = b.last_message_at
          ? new Date(b.last_message_at).getTime()
          : new Date(b.created_at).getTime();
        return db - da;
      });
      setConversations(sorted);
    } finally {
      setLoadingConvs(false);
    }
  }, [projectName]);

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

  const handleNewChat = useCallback(async () => {
    const sessionId = await ensureWorkspaceSession(
      projectName,
      sessionsRef.current,
    );
    if (!sessionId) return;

    try {
      const res = await client.agentCreateConversation(sessionId, {
        title: "New Chat",
      });
      const conv =
        res.data as unknown as ConversationWithSessionResponse;
      setConversations((prev) => [conv, ...prev]);
      navigate(`/${projectName}/workplan/chat/${conv.id}`);
    } catch {
      // User may retry via UI.
    }
  }, [projectName, sessionsRef, navigate]);

  const handleDelete = useCallback(
    async (id: string) => {
      try {
        await client.agentDeleteConversation(id);
        if (conversationId === id) {
          navigate(`/${projectName}/workplan/chat`);
        }
        setConversations((prev) => prev.filter((c) => c.id !== id));
      } catch {
        // Deletion failed; item remains in list.
      }
    },
    [conversationId, navigate, projectName],
  );

  const grouped = useMemo(
    () => groupConversations(conversations),
    [conversations],
  );

  const isLoading = loadingConvs;

  const groupOrder: Array<{
    key: keyof GroupedConversations;
    label: string;
  }> = [
    { key: "today", label: "Today" },
    { key: "yesterday", label: "Yesterday" },
    { key: "recent", label: "Previous 7 Days" },
    { key: "older", label: "Older" },
  ];

  return (
    <div className="flex flex-col h-full" role="navigation" aria-label="AI Chats">
      {/* Header */}
      <div className="mb-2 flex items-center justify-between px-3 py-2">
        <div className="flex items-center gap-2">
          <div className="grid size-6 place-items-center rounded-md bg-primary/10">
            <MessageSquare className="size-3.5 text-primary/70" />
          </div>
          <span className="text-xs font-semibold uppercase tracking-[0.06em] text-muted-foreground">
            Chats
          </span>
        </div>
        <motion.button
          type="button"
          whileHover={{ scale: 1.05 }}
          whileTap={{ scale: 0.92 }}
          className="inline-flex size-6 cursor-pointer items-center justify-center rounded-md bg-muted/60 text-muted-foreground/60 transition-colors hover:bg-primary/10 hover:text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
          onClick={handleNewChat}
          aria-label="New chat"
        >
          <Plus className="size-3" aria-hidden="true" />
        </motion.button>
      </div>

      {/* Conversation list */}
      <div className="flex-1 overflow-y-auto overscroll-contain px-1.5">
        {isLoading && (
          <div className="space-y-1 px-1">
            {Array.from({ length: SKELETON_COUNT }).map((_, i) => (
              <div className="h-9 rounded-lg px-2.5 py-2" key={i}>
                <Shimmer duration={1.8} spread={1.5}>
                  {"\u00A0".repeat(24 + i * 6)}
                </Shimmer>
              </div>
            ))}
          </div>
        )}

        <AnimatePresence>
          {!isLoading && conversations.length === 0 && (
            <motion.div
              initial={{ opacity: 0, y: 8 }}
              animate={{ opacity: 1, y: 0 }}
              className="flex flex-col items-center justify-center gap-3 py-10 px-4 text-center"
            >
              <div className="grid size-12 place-items-center rounded-2xl bg-muted/30">
                <Bot className="size-5 text-muted-foreground/25" />
              </div>
              <div>
                <p className="text-xs font-medium text-muted-foreground/70">
                  No chats yet
                </p>
                <p className="mt-0.5 text-[11px] text-muted-foreground/40">
                  Click + to start a conversation
                </p>
              </div>
            </motion.div>
          )}
        </AnimatePresence>

        {!isLoading &&
          groupOrder.map(
            ({ key, label }) =>
              grouped[key].length > 0 && (
                <div key={key} className="mb-2">
                  <div className="mb-1 flex items-center gap-2 px-2.5 py-1">
                    <span className="h-px flex-1 bg-border/30" />
                    <span className="text-[10px] font-medium uppercase tracking-wider text-muted-foreground/40">
                      {label}
                    </span>
                    <span className="h-px flex-1 bg-border/30" />
                  </div>
                  <div className="space-y-0.5">
                    {grouped[key].map((conv) => (
                      <ChatItem
                        key={conv.id}
                        conv={conv}
                        active={conversationId === conv.id}
                        onSelect={() =>
                          navigate(`/${projectName}/workplan/chat/${conv.id}`)
                        }
                        onDelete={handleDelete}
                      />
                    ))}
                  </div>
                </div>
              ),
          )}
      </div>
    </div>
  );
}
