import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet";
import { Button } from "@/components/ui/button";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Menu, LayoutDashboard, Plus, MoreVertical, User, Search, Brain, Trash2, Pencil, Pin, Archive, Database, CheckSquare, Square, ListChecks, RotateCcw, Wand2, Folder, Globe, Bot, Loader2, CheckCircle2, XCircle, ChevronRight } from "lucide-react";
import { useState, useRef, useEffect } from "react";
import { Link, useNavigate, useLocation } from "react-router-dom";
import { useTranslation } from "react-i18next";
import { useAuthStore } from "@/store/authStore";
import { useProjectStore } from "@/store/projectStore";
import { useDashboardStore } from "@/store/dashboardStore";
import { api } from "@/lib/api";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Switch } from "@/components/ui/switch";

interface SessionInfo {
  key: string;
  created_at: string;
  updated_at: string;
  alias?: string | null;
  pinned?: boolean;
  archived?: boolean;
  metadata?: {
    title?: string;
  };
}

function SectionHeader({
  title,
  count,
  isSelectionMode,
  setIsSelectionMode,
  selectedKeys,
  setSelectedKeys,
  items,
  onBatchDelete
}: {
  title: string;
  count: number;
  isSelectionMode: boolean;
  setIsSelectionMode: (val: boolean) => void;
  selectedKeys: string[];
  setSelectedKeys: (val: string[] | ((prev: string[]) => string[])) => void;
  items: SessionInfo[];
  onBatchDelete: (keys: string[]) => void;
}) {
  const { t } = useTranslation();

  const handleSelectAll = (e: React.MouseEvent) => {
    e.stopPropagation();
    if (selectedKeys.length === items.length && items.length > 0) {
      setSelectedKeys([]);
    } else {
      setSelectedKeys(items.map(item => item.key));
    }
  };

  const handleInvertSelection = (e: React.MouseEvent) => {
    e.stopPropagation();
    const allKeys = items.map(item => item.key);
    setSelectedKeys(allKeys.filter(key => !selectedKeys.includes(key)));
  };

  const handleBatchDelete = (e: React.MouseEvent) => {
    e.stopPropagation();
    if (selectedKeys.length === 0) return;
    onBatchDelete(selectedKeys);
    setSelectedKeys([]);
    setIsSelectionMode(false);
  };

  useEffect(() => {
    if (!isSelectionMode) {
      setSelectedKeys([]);
    }
  }, [isSelectionMode, setSelectedKeys]);

  return (
    <div className="px-3 pt-4 pb-1">
      <div className="flex items-center justify-between px-1 group">
        <div className="text-[14px] font-semibold text-muted-foreground flex items-center gap-1">
          {title}
          <span>({count})</span>
        </div>
        <div className="flex items-center gap-1">
          {isSelectionMode ? (
            <>
              <button
                onClick={handleSelectAll}
                title={t('selectAllOrCancel')}
                className="p-1 hover:bg-muted/80 rounded text-muted-foreground transition-colors"
              >
                <ListChecks className="h-3.5 w-3.5" />
              </button>
              <button
                onClick={handleInvertSelection}
                title={t('invertSelection')}
                className="p-1 hover:bg-muted/80 rounded text-muted-foreground transition-colors"
              >
                <RotateCcw className="h-3.5 w-3.5" />
              </button>
              <button
                onClick={handleBatchDelete}
                disabled={selectedKeys.length === 0}
                title={t('batchDelete')}
                className={`p-1 rounded transition-colors ${
                  selectedKeys.length > 0 
                    ? "hover:bg-red-100 text-red-500" 
                    : "text-muted-foreground/50 cursor-not-allowed"
                }`}
              >
                <Trash2 className="h-3.5 w-3.5" />
              </button>
              <button
                onClick={() => setIsSelectionMode(false)}
                className="text-[10px] font-medium px-1.5 py-0.5 hover:bg-muted/80 rounded text-muted-foreground transition-colors ml-1"
              >
                {t('cancel')}
              </button>
            </>
          ) : (
            <button
              onClick={() => setIsSelectionMode(true)}
              className="p-1 hover:bg-muted/80 rounded text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity"
              style={{ opacity: count > 0 ? undefined : 0 }}
            >
              <CheckSquare className="h-3.5 w-3.5" />
            </button>
          )}
        </div>
      </div>
    </div>
  );
}

function Section({
  items,
  onSelect,
  onDelete,
  onRename,
  onTogglePinned,
  onToggleArchived,
  activeKey,
  isSelectionMode,
  selectedKeys,
  setSelectedKeys
}: {
  items: SessionInfo[];
  onSelect: (key: string) => void;
  onDelete: (key: string) => void;
  onRename: (key: string, currentTitle: string) => void;
  onTogglePinned: (key: string, pinned: boolean) => void;
  onToggleArchived: (key: string, archived: boolean) => void;
  activeKey: string | null;
  isSelectionMode: boolean;
  selectedKeys: string[];
  setSelectedKeys: (val: string[] | ((prev: string[]) => string[])) => void;
}) {
  const { t } = useTranslation();

  const toggleSelect = (key: string, e: React.MouseEvent) => {
    e.stopPropagation();
    setSelectedKeys(prev => 
      prev.includes(key) ? prev.filter(k => k !== key) : [...prev, key]
    );
  };

  return (
    <div className="px-3 pb-2">
      <div className="space-y-0 mt-1">
        {items.map((item) => {
          const displayTitle = item.metadata?.title || item.key.replace("api:", "");
          const isActive = activeKey === item.key;
          const isSelected = selectedKeys.includes(item.key);
          
          return (
            <div
              key={item.key}
              className={`w-full h-8 px-2 text-left rounded-md text-[14px] flex items-center justify-between group transition-colors cursor-pointer ${
                isActive && !isSelectionMode ? 'bg-muted text-foreground font-medium' : 'text-muted-foreground hover:bg-muted/50 hover:text-foreground'
              } ${isSelected ? 'bg-indigo-50/50 text-indigo-700' : ''}`}
                onClick={(e) => isSelectionMode ? toggleSelect(item.key, e) : onSelect(item.key)}
              >
              <div className="truncate pr-2 flex-1 flex items-center gap-1.5 min-w-0">
                {isSelectionMode ? (
                  <span 
                    className="w-4 shrink-0 flex items-center justify-center"
                    onClick={(e) => toggleSelect(item.key, e)}
                  >
                    {isSelected ? (
                      <CheckSquare className="h-3.5 w-3.5 text-indigo-600" />
                    ) : (
                      <Square className="h-3.5 w-3.5 text-muted-foreground/50" />
                    )}
                  </span>
                ) : (
                  <span className="w-4 shrink-0 flex items-center justify-center">
                    {item.pinned && <Pin className="h-3.5 w-3.5 text-muted-foreground" />}
                  </span>
                )}
                <span className="truncate">{displayTitle}</span>
              </div>
              
              {!isSelectionMode && (
                <DropdownMenu>
                <DropdownMenuTrigger onClick={(e) => e.stopPropagation()} className="h-6 w-6 flex items-center justify-center rounded hover:bg-muted/80 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity outline-none">
                  <MoreVertical className="h-4 w-4" />
                </DropdownMenuTrigger>
                <DropdownMenuContent align="end" className="w-32">
                  <DropdownMenuItem
                    onClick={(e) => {
                      e.preventDefault();
                      e.stopPropagation();
                      onRename(item.key, displayTitle);
                    }}
                    onSelect={(e) => {
                      e.preventDefault();
                      e.stopPropagation();
                      onRename(item.key, displayTitle);
                    }}
                  >
                    <Pencil className="mr-2 h-4 w-4" />
                    <span>{t('rename')}</span>
                  </DropdownMenuItem>
                  <DropdownMenuItem
                    onClick={(e) => {
                      e.preventDefault();
                      e.stopPropagation();
                      onTogglePinned(item.key, !!item.pinned);
                    }}
                    onSelect={(e) => {
                      e.preventDefault();
                      e.stopPropagation();
                      onTogglePinned(item.key, !!item.pinned);
                    }}
                  >
                    <Pin className="mr-2 h-4 w-4" />
                    <span>{item.pinned ? t('unpin') : t('pin')}</span>
                  </DropdownMenuItem>
                  <DropdownMenuItem
                    onClick={(e) => {
                      e.preventDefault();
                      e.stopPropagation();
                      onToggleArchived(item.key, !!item.archived);
                    }}
                    onSelect={(e) => {
                      e.preventDefault();
                      e.stopPropagation();
                      onToggleArchived(item.key, !!item.archived);
                    }}
                  >
                    <Archive className="mr-2 h-4 w-4" />
                    <span>{item.archived ? t('unarchive') : t('archive')}</span>
                  </DropdownMenuItem>
                  <DropdownMenuItem
                    onClick={(e) => {
                      e.preventDefault();
                      e.stopPropagation();
                      onDelete(item.key);
                    }}
                    onSelect={(e) => {
                      e.preventDefault();
                      e.stopPropagation();
                      onDelete(item.key);
                    }}
                    className="text-red-600 focus:text-red-600 focus:bg-red-50"
                  >
                    <Trash2 className="mr-2 h-4 w-4" />
                    <span>{t('deleteSession')}</span>
                  </DropdownMenuItem>
                </DropdownMenuContent>
                </DropdownMenu>
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
}

function DashboardSection({
  title,
  count,
  items,
  onSelect,
  onDelete,
  onRename,
  onCreate,
  activeId
}: {
  title: string;
  count: number;
  items: {id: string, name: string}[];
  onSelect: (id: string) => void;
  onDelete: (id: string) => void;
  onRename: (id: string, currentName: string) => void;
  onCreate: () => void;
  activeId: string | null;
}) {
  const { t } = useTranslation();
  return (
    <div className="px-3 pt-4">
      <div className="flex items-center justify-between mb-1.5 px-1 group">
        <div className="text-[14px] font-semibold text-muted-foreground flex items-center gap-1">
          {title}
          <span>({count})</span>
        </div>
        <button
          onClick={onCreate}
          className="text-[10px] font-medium px-1.5 py-0.5 hover:bg-muted/80 rounded text-muted-foreground transition-colors opacity-0 group-hover:opacity-100 flex items-center gap-0.5"
        >
          <Plus className="h-3.5 w-3.5" />
          {t('new')}
        </button>
      </div>
      <div className="space-y-0 mt-1">
        {items.map((item) => {
          const isActive = activeId === item.id;
          return (
            <div
              key={item.id}
              className={`w-full h-8 px-2 text-left rounded-md text-[14px] flex items-center justify-between group transition-colors cursor-pointer ${
                isActive ? 'bg-muted text-foreground font-medium' : 'text-muted-foreground hover:bg-muted/50 hover:text-foreground'
              }`}
                onClick={() => onSelect(item.id)}
              >
              <div className="truncate pr-2 flex-1 flex items-center gap-1.5 min-w-0">
                <span className="w-4 shrink-0 flex items-center justify-center">
                  <LayoutDashboard className="h-3.5 w-3.5 text-muted-foreground" />
                </span>
                <span className="truncate">{item.name}</span>
              </div>
              <DropdownMenu>
                <DropdownMenuTrigger onClick={(e) => e.stopPropagation()} className="h-6 w-6 flex items-center justify-center rounded hover:bg-muted/80 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity outline-none">
                  <MoreVertical className="h-4 w-4" />
                </DropdownMenuTrigger>
                <DropdownMenuContent align="end" className="w-32">
                  <DropdownMenuItem
                    onClick={(e) => {
                      e.preventDefault();
                      e.stopPropagation();
                      onRename(item.id, item.name);
                    }}
                  >
                    <Pencil className="mr-2 h-4 w-4" />
                    <span>{t('rename')}</span>
                  </DropdownMenuItem>
                  <DropdownMenuItem
                    onClick={(e) => {
                      e.preventDefault();
                      e.stopPropagation();
                      onDelete(item.id);
                    }}
                    className="text-red-600 focus:text-red-600 focus:bg-red-50"
                  >
                    <Trash2 className="mr-2 h-4 w-4" />
                    <span>{t('delete')}</span>
                  </DropdownMenuItem>
                </DropdownMenuContent>
                </DropdownMenu>
              </div>
            );
          })}
        </div>
    </div>
  );
}

function SidebarBody() {
  const navigate = useNavigate();
  const location = useLocation();
  const { user, logout } = useAuthStore();
  const { currentProject } = useProjectStore();
  const { dashboards, activeDashboardId, loadDashboards, createDashboard, deleteDashboard, renameDashboard, setActiveDashboard } = useDashboardStore();
  const { t, i18n } = useTranslation();
  const [showUserMenu, setShowUserMenu] = useState(false);
  const menuRef = useRef<HTMLDivElement>(null);
  const [voiceSettingsOpen, setVoiceSettingsOpen] = useState(false);
  const [voiceEnabledDraft, setVoiceEnabledDraft] = useState(false);
  const [showKnowledgeSubmenu, setShowKnowledgeSubmenu] = useState(false);
  const [showMoreSubmenu, setShowMoreSubmenu] = useState(false);
  const [whisperUrlDraft, setWhisperUrlDraft] = useState("");
  const [isTestingVoice, setIsTestingVoice] = useState(false);
  const [voiceTestStatus, setVoiceTestStatus] = useState<"success" | "error" | null>(null);
  const [voiceTestMessage, setVoiceTestMessage] = useState("");
  
  // Session management state
  const [sessions, setSessions] = useState<SessionInfo[]>([]);
  const [sessionFilter, setSessionFilter] = useState("");
  const [renameDialogOpen, setRenameDialogOpen] = useState(false);
  const [sessionToRename, setSessionToRename] = useState<{key: string, title: string} | null>(null);
  const [newTitle, setNewTitle] = useState("");

  const [activeSelectionMode, setActiveSelectionMode] = useState(false);
  const [activeSelectedKeys, setActiveSelectedKeys] = useState<string[]>([]);
  const [archivedSelectionMode, setArchivedSelectionMode] = useState(false);
  const [archivedSelectedKeys, setArchivedSelectedKeys] = useState<string[]>([]);

  const [dashboardRenameDialogOpen, setDashboardRenameDialogOpen] = useState(false);
  const [dashboardToRename, setDashboardToRename] = useState<{id: string, name: string} | null>(null);
  const [newDashboardName, setNewDashboardName] = useState("");

  // Try to parse active session from URL query
  const queryParams = new URLSearchParams(location.search);
  const activeSessionKey = queryParams.get("session") || "api:default";

  useEffect(() => {
    if (currentProject) {
      loadDashboards(currentProject.id);
    }
  }, [currentProject, loadDashboards]);

  const fetchSessions = async () => {
    try {
      const url = currentProject 
        ? `/nanobot/sessions?project_id=${currentProject.id}`
        : "/nanobot/sessions";
      const data = await api.get<SessionInfo[]>(url);
      setSessions(data);
    } catch (e) {
      console.error("Failed to fetch sessions", e);
    }
  };

  useEffect(() => {
    fetchSessions();
  }, [location.pathname, location.search, currentProject?.id]);

  useEffect(() => {
    const onFocus = () => fetchSessions();
    const onSessionsChanged = () => fetchSessions();
    window.addEventListener("focus", onFocus);
    window.addEventListener("nanobot:sessions-changed", onSessionsChanged);
    return () => {
      window.removeEventListener("focus", onFocus);
      window.removeEventListener("nanobot:sessions-changed", onSessionsChanged);
    };
  }, []);

  useEffect(() => {
    function handleClickOutside(event: MouseEvent) {
      if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
        setShowUserMenu(false);
      }
    }
    document.addEventListener("mousedown", handleClickOutside);
    return () => document.removeEventListener("mousedown", handleClickOutside);
  }, []);

  const handleLogout = () => {
    logout();
    navigate("/login");
  };

  const openVoiceSettings = () => {
    const enabled = localStorage.getItem("whisper_enabled") === "true";
    const saved = (localStorage.getItem("whisper_url") || "").trim();
    setVoiceEnabledDraft(enabled);
    setWhisperUrlDraft(saved);
    setVoiceTestStatus(null);
    setVoiceTestMessage("");
    setVoiceSettingsOpen(true);
  };

  const handleSaveVoiceSettings = () => {
    localStorage.setItem("whisper_enabled", String(voiceEnabledDraft));
    if (!voiceEnabledDraft) {
      setVoiceSettingsOpen(false);
      return;
    }
    const normalized = whisperUrlDraft.trim();
    if (!normalized) {
      alert(t('voiceServerRequired', '请填写语音识别服务地址'));
      return;
    }
    localStorage.setItem("whisper_url", normalized);
    setVoiceSettingsOpen(false);
  };

  const handleTestVoiceConnection = async () => {
    if (!voiceEnabledDraft) {
      alert(t('voiceInputDisabledHint', '请先开启语音输入'));
      return;
    }
    const normalized = whisperUrlDraft.trim();
    if (!normalized) {
      alert(t('voiceServerRequired', '请填写语音识别服务地址'));
      return;
    }
    setIsTestingVoice(true);
    setVoiceTestStatus(null);
    setVoiceTestMessage("");
    try {
      const response = await fetch(`${normalized.replace(/\/$/, "")}/health`, {
        method: "GET",
      });
      if (!response.ok) {
        throw new Error(`HTTP ${response.status}`);
      }
      setVoiceTestStatus("success");
      setVoiceTestMessage(t('voiceConnectionSuccess', '连接成功'));
    } catch (error: any) {
      setVoiceTestStatus("error");
      setVoiceTestMessage(`${t('voiceConnectionFailed', '连接失败')}: ${error?.message || t('unknownError', '未知错误')}`);
    } finally {
      setIsTestingVoice(false);
    }
  };

  const handleSelectSession = (key: string) => {
    navigate(`/?session=${encodeURIComponent(key)}`);
  };

  const handleNewThread = async () => {
    const newSessionId = `api:${Date.now()}`;
    try {
      const payload = currentProject ? { project_id: currentProject.id } : {};
      await api.post(`/nanobot/sessions/${encodeURIComponent(newSessionId)}/ensure`, payload);
      await fetchSessions();
      window.dispatchEvent(new Event("nanobot:sessions-changed"));
    } catch (e) {
      console.error("Failed to create session", e);
    }
    navigate(`/?session=${encodeURIComponent(newSessionId)}`);
  };

  const handleDeleteSession = async (key: string) => {
    if (!window.confirm(t('confirmDeleteSession'))) return;
    try {
      await api.delete(`/nanobot/sessions/${encodeURIComponent(key)}`);
      if (activeSessionKey === key) {
        navigate("/");
      }
      fetchSessions();
      window.dispatchEvent(new Event("nanobot:sessions-changed"));
    } catch (e) {
      console.error("Failed to delete session", e);
    }
  };

  const handleBatchDelete = async (keys: string[]) => {
    if (!window.confirm(t('confirmBatchDeleteSessions', { count: keys.length }))) return;
    try {
      await api.post("/nanobot/sessions/batch-delete", { session_ids: keys });
      if (keys.includes(activeSessionKey)) {
        navigate("/");
      }
      fetchSessions();
      window.dispatchEvent(new Event("nanobot:sessions-changed"));
    } catch (e) {
      console.error("Failed to batch delete sessions", e);
    }
  };

  const openRenameDialog = (key: string, currentTitle: string) => {
    setSessionToRename({ key, title: currentTitle });
    setNewTitle(currentTitle);
    setRenameDialogOpen(true);
  };

  const handleRename = async () => {
    if (!sessionToRename || !newTitle.trim()) return;
    try {
      const nextTitle = newTitle.trim();
      await api.put(`/nanobot/sessions/${encodeURIComponent(sessionToRename.key)}`, { title: nextTitle });
      setSessions((prev) =>
        prev.map((item) =>
          item.key === sessionToRename.key
            ? { ...item, alias: nextTitle, metadata: { ...(item.metadata || {}), title: nextTitle } }
            : item
        )
      );
      setRenameDialogOpen(false);
      fetchSessions();
      window.dispatchEvent(new Event("nanobot:sessions-changed"));
    } catch (e) {
      console.error("Failed to rename session", e);
    }
  };

  const handleTogglePinned = async (key: string, pinned: boolean) => {
    const nextPinned = !pinned;
    try {
      await api.put(`/nanobot/sessions/${encodeURIComponent(key)}`, { pinned: nextPinned });
      setSessions((prev) =>
        prev
          .map((item) => (item.key === key ? { ...item, pinned: nextPinned } : item))
          .sort((a, b) => {
            const ap = a.pinned ? 1 : 0;
            const bp = b.pinned ? 1 : 0;
            if (bp !== ap) return bp - ap;
            const aa = a.archived ? 1 : 0;
            const ba = b.archived ? 1 : 0;
            if (aa !== ba) return aa - ba;
            return (b.updated_at || "").localeCompare(a.updated_at || "");
          })
      );
      window.dispatchEvent(new Event("nanobot:sessions-changed"));
    } catch (e) {
      console.error("Failed to toggle pinned", e);
    }
  };

  const handleToggleArchived = async (key: string, archived: boolean) => {
    const nextArchived = !archived;
    try {
      await api.put(`/nanobot/sessions/${encodeURIComponent(key)}`, { archived: nextArchived });
      setSessions((prev) =>
        prev
          .map((item) => (item.key === key ? { ...item, archived: nextArchived } : item))
          .sort((a, b) => {
            const ap = a.pinned ? 1 : 0;
            const bp = b.pinned ? 1 : 0;
            if (bp !== ap) return bp - ap;
            const aa = a.archived ? 1 : 0;
            const ba = b.archived ? 1 : 0;
            if (aa !== ba) return aa - ba;
            return (b.updated_at || "").localeCompare(a.updated_at || "");
          })
      );
      window.dispatchEvent(new Event("nanobot:sessions-changed"));
    } catch (e) {
      console.error("Failed to toggle archived", e);
    }
  };

  const normalizedFilter = sessionFilter.trim().toLowerCase();
  const activeSessions = sessions.filter((item) => {
    if (item.archived) return false;
    if (!normalizedFilter) return true;
    const title = (item.metadata?.title || item.key.replace("api:", "")).toLowerCase();
    return title.includes(normalizedFilter);
  });
  const archivedSessions = sessions.filter((item) => {
    if (!item.archived) return false;
    if (!normalizedFilter) return true;
    const title = (item.metadata?.title || item.key.replace("api:", "")).toLowerCase();
    return title.includes(normalizedFilter);
  });

  const handleCreateDashboard = () => {
    if (!currentProject) return;
    if (dashboards.length >= 3) {
      alert(t('dashboardLimitReached') || "You can only create up to 3 dashboards.");
      return;
    }
    createDashboard(t('newDashboardNameDefault'), currentProject.id);
    navigate(`/dashboard`);
  };

  const handleSelectDashboard = (id: string) => {
    setActiveDashboard(id);
    navigate(`/dashboard`);
  };

  const openDashboardRenameDialog = (id: string, name: string) => {
    setDashboardToRename({ id, name });
    setNewDashboardName(name);
    setDashboardRenameDialogOpen(true);
  };

  const handleDashboardRename = () => {
    if (!currentProject || !dashboardToRename || !newDashboardName.trim()) return;
    renameDashboard(dashboardToRename.id, newDashboardName.trim(), currentProject.id);
    setDashboardRenameDialogOpen(false);
  };

  const handleDashboardDelete = (id: string) => {
    if (!currentProject) return;
    if (!window.confirm(t('confirmDeleteDashboard'))) return;
    deleteDashboard(id, currentProject.id);
  };

  const filteredDashboards = dashboards.filter((d) => {
    if (!normalizedFilter) return true;
    return d.name.toLowerCase().includes(normalizedFilter);
  });

  return (
    <div className="h-full min-h-0 flex flex-col bg-muted/50/30 border-r border-border relative">
      {/* Header */}
      <div className="h-14 px-4 flex items-center justify-between border-b border-border">
        <Link to="/" className="flex items-center gap-1.5 text-foreground/80 font-bold text-lg hover:opacity-80 transition-opacity">
          <span className="text-xl leading-none mr-0.5">🦞</span>
          <span className="bg-clip-text text-transparent bg-gradient-to-r from-foreground to-muted-foreground">
            {t('lobsterDataQA')}
          </span>
        </Link>
        <div className="w-8" />
      </div>

      <div className="flex-none">
        <DashboardSection
          title={t('dashboards') || 'Dashboards'}
          count={filteredDashboards.length}
          items={filteredDashboards.map(d => ({ id: d.id, name: d.name }))}
          onSelect={handleSelectDashboard}
          onDelete={handleDashboardDelete}
          onRename={openDashboardRenameDialog}
          onCreate={handleCreateDashboard}
          activeId={location.pathname === "/dashboard" ? activeDashboardId : null}
        />
        
        <div className="px-3 pt-4 mb-2">
          <Button 
            variant="outline" 
            className="w-full justify-start h-10 px-3 rounded-lg border-border bg-background hover:bg-muted/50 text-muted-foreground font-medium text-[14px]"
            onClick={handleNewThread}
          >
            <Plus className="h-4 w-4 mr-2" />
            {t('newThread')}
          </Button>
        </div>

        <div className="px-3 pt-2">
          <div className="relative">
            <Search className="h-4 w-4 text-muted-foreground absolute left-3 top-1/2 -translate-y-1/2" />
            <Input
              value={sessionFilter}
              onChange={(e) => setSessionFilter(e.target.value)}
              placeholder={t('filterSessionName')}
              className="pl-9 h-9 border-border bg-background text-[14px]"
            />
          </div>
        </div>
      </div>

      <div className="flex-1 min-h-0 flex flex-col mt-2">
        <div className="flex-1 min-h-0 flex flex-col">
          <SectionHeader
            title={t('threads')}
            count={activeSessions.length}
            isSelectionMode={activeSelectionMode}
            setIsSelectionMode={setActiveSelectionMode}
            selectedKeys={activeSelectedKeys}
            setSelectedKeys={setActiveSelectedKeys}
            items={activeSessions}
            onBatchDelete={handleBatchDelete}
          />
          <ScrollArea className="flex-1 min-h-0">
            <Section 
              items={activeSessions} 
              onSelect={handleSelectSession}
              onDelete={handleDeleteSession}
              onRename={openRenameDialog}
              onTogglePinned={handleTogglePinned}
              onToggleArchived={handleToggleArchived}
              activeKey={activeSessionKey}
              isSelectionMode={activeSelectionMode}
              selectedKeys={activeSelectedKeys}
              setSelectedKeys={setActiveSelectedKeys}
            />
          </ScrollArea>
        </div>
        
        {archivedSessions.length > 0 && (
          <div className="h-[35%] min-h-[150px] shrink-0 border-t border-border bg-muted/50/50 flex flex-col">
            <SectionHeader
              title={t('archivedThreads')}
              count={archivedSessions.length}
              isSelectionMode={archivedSelectionMode}
              setIsSelectionMode={setArchivedSelectionMode}
              selectedKeys={archivedSelectedKeys}
              setSelectedKeys={setArchivedSelectedKeys}
              items={archivedSessions}
              onBatchDelete={handleBatchDelete}
            />
            <ScrollArea className="flex-1 min-h-0">
              <Section 
                items={archivedSessions} 
                onSelect={handleSelectSession}
                onDelete={handleDeleteSession}
                onRename={openRenameDialog}
                onTogglePinned={handleTogglePinned}
                onToggleArchived={handleToggleArchived}
                activeKey={activeSessionKey}
                isSelectionMode={archivedSelectionMode}
                selectedKeys={archivedSelectedKeys}
                setSelectedKeys={setArchivedSelectedKeys}
              />
            </ScrollArea>
          </div>
        )}
      </div>

      <Dialog open={renameDialogOpen} onOpenChange={setRenameDialogOpen}>
        <DialogContent className="sm:max-w-md">
          <DialogHeader>
            <DialogTitle>{t('renameSession')}</DialogTitle>
          </DialogHeader>
          <div className="py-4">
            <Input 
              value={newTitle} 
              onChange={(e) => setNewTitle(e.target.value)} 
              placeholder={t('enterNewSessionTitle')} 
              autoFocus
              onKeyDown={(e) => {
                if (e.key === 'Enter') {
                  handleRename();
                }
              }}
            />
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setRenameDialogOpen(false)}>{t('cancel')}</Button>
            <Button className="bg-indigo-600 hover:bg-indigo-700 text-primary-foreground" onClick={handleRename}>{t('save')}</Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={dashboardRenameDialogOpen} onOpenChange={setDashboardRenameDialogOpen}>
        <DialogContent className="sm:max-w-md">
          <DialogHeader>
            <DialogTitle>{t('renameDashboard')}</DialogTitle>
          </DialogHeader>
          <div className="py-4">
            <Input 
              value={newDashboardName} 
              onChange={(e) => setNewDashboardName(e.target.value)} 
              placeholder={t('enterNewDashboardName')} 
              autoFocus
              onKeyDown={(e) => {
                if (e.key === 'Enter') {
                  handleDashboardRename();
                }
              }}
            />
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setDashboardRenameDialogOpen(false)}>{t('cancel')}</Button>
            <Button className="bg-indigo-600 hover:bg-indigo-700 text-primary-foreground" onClick={handleDashboardRename}>{t('save')}</Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={voiceSettingsOpen} onOpenChange={setVoiceSettingsOpen}>
        <DialogContent className="sm:max-w-md">
          <DialogHeader>
            <DialogTitle>{t('voiceSettings', '语音输入配置')}</DialogTitle>
          </DialogHeader>
          <div className="py-4 space-y-3">
            <div className="flex items-center justify-between rounded-md border border-border p-3">
              <span className="text-sm text-foreground">{t('enableVoiceInput', '启用语音输入')}</span>
              <Switch checked={voiceEnabledDraft} onCheckedChange={setVoiceEnabledDraft} />
            </div>
            <Input
              value={whisperUrlDraft}
              onChange={(e) => setWhisperUrlDraft(e.target.value)}
              placeholder="http://localhost:8001"
              disabled={!voiceEnabledDraft}
            />
            <p className="text-xs text-muted-foreground">
              {voiceEnabledDraft
                ? t('voiceSettingsHint', '请输入语音识别服务地址，例如：http://localhost:8001')
                : t('voiceSettingsDisabledHint', '请先开启语音输入，再配置服务地址')}
            </p>
            {voiceTestStatus && (
              <div className={`flex items-center gap-2 text-xs ${voiceTestStatus === "success" ? "text-emerald-600" : "text-red-600"}`}>
                {voiceTestStatus === "success" ? <CheckCircle2 className="h-3.5 w-3.5" /> : <XCircle className="h-3.5 w-3.5" />}
                <span>{voiceTestMessage}</span>
              </div>
            )}
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setVoiceSettingsOpen(false)}>{t('cancel')}</Button>
            <Button variant="outline" onClick={handleTestVoiceConnection} disabled={isTestingVoice}>
              {isTestingVoice ? <Loader2 className="h-4 w-4 animate-spin" /> : t('testConnection', '测试连接')}
            </Button>
            <Button className="bg-indigo-600 hover:bg-indigo-700 text-primary-foreground" onClick={handleSaveVoiceSettings}>{t('save')}</Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <div className="p-4 border-t border-border mt-auto relative" ref={menuRef}>
        <div className="flex items-center justify-between text-muted-foreground">
          <button 
            className="flex items-center gap-2 hover:text-foreground transition-colors p-1 rounded-full hover:bg-muted"
            onClick={() => {
              setShowUserMenu(!showUserMenu);
              if (showUserMenu) {
                setShowKnowledgeSubmenu(false);
                setShowMoreSubmenu(false);
              }
            }}
          >
            <div className="w-8 h-8 rounded-full bg-indigo-100 flex items-center justify-center text-indigo-600 border border-indigo-200 shadow-sm overflow-hidden">
              {user?.avatar ? (
                <img src={user.avatar} alt="avatar" className="w-full h-full object-cover" />
              ) : (
                <User className="h-4.5 w-4.5" />
              )}
            </div>
            <div className="text-sm font-medium truncate max-w-[100px] text-left">
              {user?.username || t('defaultUser')}
            </div>
          </button>
          
          <button 
            className="flex items-center gap-1.5 text-sm hover:text-foreground transition-colors px-2 py-1.5 rounded-md hover:bg-muted"
            onClick={() => navigate("/skills")}
          >
            <Wand2 className="h-4 w-4" />
            {t('skillCenter')}
          </button>
        </div>

        {/* User Settings Popover Menu */}
        {showUserMenu && (
          <div className="absolute bottom-[72px] left-4 w-56 bg-background rounded-xl shadow-xl border border-border py-1.5 z-50 overflow-visible animate-in fade-in zoom-in duration-200">
            <div className="px-3 py-2 border-b border-border mb-1">
              <p className="text-sm font-medium text-foreground truncate">{user?.username}</p>
              <p className="text-xs text-muted-foreground truncate">{user?.email}</p>
            </div>
            
            <button 
              className="w-full flex items-center gap-2 px-3 py-2 text-sm text-foreground/80 hover:bg-muted transition-colors"
              onClick={() => {
                navigate("/projects");
                setShowUserMenu(false);
              }}
            >
              <Folder className="h-4 w-4 text-muted-foreground" />
              {t('projectManagement')}
            </button>
            {user?.is_admin && (
              <button
                className="w-full flex items-center gap-2 px-3 py-2 text-sm text-foreground/80 hover:bg-muted transition-colors"
                onClick={() => {
                  navigate("/model-configs");
                  setShowUserMenu(false);
                }}
              >
                <Brain className="h-4 w-4 text-muted-foreground" />
                {t('modelConfig')}
              </button>
            )}

            <button 
              className="w-full flex items-center gap-2 px-3 py-2 text-sm text-foreground/80 hover:bg-muted transition-colors"
              onClick={() => {
                if (currentProject?.id) {
                  navigate(`/projects/${currentProject.id}/subagents`);
                } else {
                  navigate("/projects");
                }
                setShowUserMenu(false);
              }}
            >
              <Bot className="h-4 w-4 text-muted-foreground" />
              {t('subagents', 'Subagents')}
            </button>

            <button 
              className="w-full flex items-center gap-2 px-3 py-2 text-sm text-foreground/80 hover:bg-muted transition-colors"
              onClick={() => {
                navigate("/datasources");
                setShowUserMenu(false);
              }}
            >
              <Database className="h-4 w-4 text-muted-foreground" />
              {t('dataSourceManagement')}
            </button>

            <div 
              className="relative group/kb"
              onMouseEnter={() => setShowKnowledgeSubmenu(true)}
              onMouseLeave={() => setShowKnowledgeSubmenu(false)}
            >
              <button 
                className="w-full flex items-center justify-between px-3 py-2 text-sm text-foreground/80 hover:bg-muted transition-colors"
                onClick={(e) => {
                  e.preventDefault();
                  setShowKnowledgeSubmenu(!showKnowledgeSubmenu);
                }}
              >
                <div className="flex items-center gap-2">
                  <Database className="h-4 w-4 text-muted-foreground" />
                  {t('knowledgeBaseGroup', 'Knowledge Base')}
                </div>
                <ChevronRight className={`h-4 w-4 text-muted-foreground transition-transform ${showKnowledgeSubmenu ? 'translate-x-0.5' : ''}`} />
              </button>

              {showKnowledgeSubmenu && (
                <div 
                  className="absolute left-[calc(100%-8px)] top-0 w-48 bg-background border border-border rounded-md shadow-lg py-1 z-[60] animate-in fade-in zoom-in-95 duration-200"
                  style={{ minWidth: 'max-content' }}
                >
                  <div className="absolute -left-3 top-0 bottom-0 w-4" />
                  
                  <button 
                    className="w-full flex items-center gap-2 px-3 py-2 text-sm text-foreground/80 hover:bg-muted transition-colors relative z-10"
                    onClick={() => {
                      navigate("/knowledge-bases");
                      setShowUserMenu(false);
                      setShowKnowledgeSubmenu(false);
                    }}
                  >
                    {t('knowledgeBases')}
                  </button>
                  
                  {user?.is_admin && (
                    <button
                      className="w-full flex items-center gap-2 px-3 py-2 text-sm text-foreground/80 hover:bg-muted transition-colors relative z-10"
                      onClick={() => {
                        navigate("/embedding-models");
                        setShowUserMenu(false);
                        setShowKnowledgeSubmenu(false);
                      }}
                    >
                      {t('embeddingModels')}
                    </button>
                  )}
                </div>
              )}
            </div>

            <div 
              className="relative"
              onMouseEnter={() => setShowMoreSubmenu(true)}
              onMouseLeave={() => setShowMoreSubmenu(false)}
            >
              <button 
                className="w-full flex items-center justify-between px-3 py-2 text-sm text-foreground/80 hover:bg-muted transition-colors"
                onClick={(e) => {
                  e.preventDefault();
                  setShowMoreSubmenu(!showMoreSubmenu);
                }}
              >
                <div className="flex items-center gap-2">
                  <MoreVertical className="h-4 w-4 text-muted-foreground" />
                  {t('moreGroup')}
                </div>
                <ChevronRight className={`h-4 w-4 text-muted-foreground transition-transform ${showMoreSubmenu ? 'translate-x-0.5' : ''}`} />
              </button>

              {showMoreSubmenu && (
                <div 
                  className="absolute left-[calc(100%-8px)] top-0 w-48 bg-background border border-border rounded-md shadow-lg py-1 z-[60] animate-in fade-in zoom-in-95 duration-200"
                  style={{ minWidth: 'max-content' }}
                >
                  <div className="absolute -left-3 top-0 bottom-0 w-4" />
                  <button 
                    className="w-full flex items-center gap-2 px-3 py-2 text-sm text-foreground/80 hover:bg-muted transition-colors relative z-10"
                    onClick={() => {
                      navigate("/settings");
                      setShowUserMenu(false);
                      setShowMoreSubmenu(false);
                    }}
                  >
                    {t('personalSettings')}
                  </button>
                  {user?.is_admin && (
                    <button 
                      className="w-full flex items-center gap-2 px-3 py-2 text-sm text-foreground/80 hover:bg-muted transition-colors relative z-10"
                      onClick={() => {
                        navigate("/users");
                        setShowUserMenu(false);
                        setShowMoreSubmenu(false);
                      }}
                    >
                      {t('userManagement')}
                    </button>
                  )}
                  <button 
                    className="w-full flex items-center gap-2 px-3 py-2 text-sm text-foreground/80 hover:bg-muted transition-colors relative z-10"
                    onClick={() => {
                      openVoiceSettings();
                      setShowUserMenu(false);
                      setShowMoreSubmenu(false);
                    }}
                  >
                    {t('voiceSettings')}
                  </button>
                  {user?.is_admin && (
                    <button 
                      className="w-full flex items-center gap-2 px-3 py-2 text-sm text-foreground/80 hover:bg-muted transition-colors relative z-10"
                      onClick={() => {
                        navigate("/web-search-config");
                        setShowUserMenu(false);
                        setShowMoreSubmenu(false);
                      }}
                    >
                      {t('webSearchConfig', 'Web Search Config')}
                    </button>
                  )}
                </div>
              )}
            </div>
            
            <div className="h-px bg-muted my-1 mx-2" />
            
            <button 
              className="w-full flex items-center gap-2 px-3 py-2 text-sm text-foreground/80 hover:bg-muted transition-colors"
              onClick={() => {
                i18n.changeLanguage(i18n.language === 'zh' ? 'en' : 'zh');
                setShowUserMenu(false);
              }}
            >
              <Globe className="h-4 w-4 text-muted-foreground" />
              {i18n.language === 'zh' ? 'English' : '中文'}
            </button>
            
            <button 
              className="w-full flex items-center gap-2 px-3 py-2 text-sm text-red-600 hover:bg-red-50 transition-colors"
              onClick={handleLogout}
            >
              {t('logout')}
            </button>
          </div>
        )}
      </div>
    </div>
  );
}

export function Sidebar() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <>
      <Sheet open={isOpen} onOpenChange={setIsOpen}>
        <SheetTrigger render={
          <Button variant="ghost" size="icon" className="md:hidden fixed top-3 left-3 z-50 border border-border bg-background">
            <Menu className="h-5 w-5" />
          </Button>
        } />
        <SheetContent side="left" className="w-[280px] p-0">
          <SidebarBody />
        </SheetContent>
      </Sheet>

      <div className="hidden md:flex w-[280px] h-screen shrink-0">
        <SidebarBody />
      </div>
    </>
  );
}
