import React, { useState } from "react";
import {
  ChevronUp,
  User2,
  HardDrive,
  Menu,
  ChevronRight,
  RotateCcw,
} from "lucide-react";
import { useTranslation } from "react-i18next";
import { isElectron, logoutUser } from "@/ui/main-axios.ts";

import {
  Sidebar,
  SidebarContent,
  SidebarFooter,
  SidebarGroup,
  SidebarGroupLabel,
  SidebarMenu,
  SidebarMenuButton,
  SidebarMenuItem,
  SidebarProvider,
  SidebarInset,
  SidebarHeader,
} from "@/components/ui/sidebar.tsx";

import { Separator } from "@/components/ui/separator.tsx";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@radix-ui/react-dropdown-menu";
import { Input } from "@/components/ui/input.tsx";
import { Button } from "@/components/ui/button.tsx";
import { FolderCard } from "@/ui/desktop/navigation/hosts/FolderCard.tsx";
import { getSSHHosts, getSSHFolders } from "@/ui/main-axios.ts";
import { useTabs } from "@/ui/desktop/navigation/tabs/TabContext.tsx";
import type { SSHFolder } from "@/types/index.ts";

interface SSHHost {
  id: number;
  name: string;
  ip: string;
  port: number;
  username: string;
  folder: string;
  tags: string[];
  pin: boolean;
  authType: string;
  password?: string;
  key?: string;
  keyPassword?: string;
  keyType?: string;
  enableTerminal: boolean;
  enableTunnel: boolean;
  enableFileManager: boolean;
  defaultPath: string;
  tunnelConnections: unknown[];
  createdAt: string;
  updatedAt: string;
}

interface SidebarProps {
  disabled?: boolean;
  isAdmin?: boolean;
  username?: string | null;
  children?: React.ReactNode;
  onLogout?: () => void;
}

async function handleLogout() {
  try {
    await logoutUser();

    if (isElectron()) {
      localStorage.removeItem("jwt");
    }

    window.location.reload();
  } catch (error) {
    console.error("Logout failed:", error);
    window.location.reload();
  }
}

export function LeftSidebar({
  disabled,
  isAdmin,
  username,
  children,
  onLogout,
}: SidebarProps): React.ReactElement {
  const { t } = useTranslation();

  const [isSidebarOpen, setIsSidebarOpen] = useState<boolean>(() => {
    const saved = localStorage.getItem("leftSidebarOpen");
    return saved !== null ? JSON.parse(saved) : true;
  });

  const {
    tabs: tabList,
    addTab,
    setCurrentTab,
    allSplitScreenTab,
    updateHostConfig,
  } = useTabs() as {
    tabs: Array<{ id: number; type: string; [key: string]: unknown }>;
    addTab: (tab: { type: string; [key: string]: unknown }) => number;
    setCurrentTab: (id: number) => void;
    allSplitScreenTab: number[];
    updateHostConfig: (id: number, config: unknown) => void;
  };
  const isSplitScreenActive =
    Array.isArray(allSplitScreenTab) && allSplitScreenTab.length > 0;
  const sshManagerTab = tabList.find((t) => t.type === "ssh_manager");
  const openSshManagerTab = () => {
    if (isSplitScreenActive) return;
    if (sshManagerTab) {
      setCurrentTab(sshManagerTab.id);
      return;
    }
    const id = addTab({ type: "ssh_manager", title: "Host Manager" });
    setCurrentTab(id);
  };
  const adminTab = tabList.find((t) => t.type === "admin");
  const openAdminTab = () => {
    if (isSplitScreenActive) return;
    if (adminTab) {
      setCurrentTab(adminTab.id);
      return;
    }
    const id = addTab({ type: "admin" });
    setCurrentTab(id);
  };
  const userProfileTab = tabList.find((t) => t.type === "user_profile");
  const openUserProfileTab = () => {
    if (isSplitScreenActive) return;
    if (userProfileTab) {
      setCurrentTab(userProfileTab.id);
      return;
    }
    const id = addTab({ type: "user_profile" });
    setCurrentTab(id);
  };

  const [hosts, setHosts] = useState<SSHHost[]>([]);
  const [hostsLoading] = useState(false);
  const [hostsError, setHostsError] = useState<string | null>(null);
  const prevHostsRef = React.useRef<SSHHost[]>([]);
  const [search, setSearch] = useState("");
  const [debouncedSearch, setDebouncedSearch] = useState("");
  const [folderMetadata, setFolderMetadata] = useState<Map<string, SSHFolder>>(
    new Map(),
  );

  const fetchFolderMetadata = React.useCallback(async () => {
    try {
      const folders = await getSSHFolders();
      const metadataMap = new Map<string, SSHFolder>();
      folders.forEach((folder) => {
        metadataMap.set(folder.name, folder);
      });
      setFolderMetadata(metadataMap);
    } catch (error) {
      console.error("Failed to fetch folder metadata:", error);
    }
  }, []);

  const fetchHosts = React.useCallback(async () => {
    try {
      const newHosts = await getSSHHosts();
      const prevHosts = prevHostsRef.current;

      const existingHostsMap = new Map(prevHosts.map((h) => [h.id, h]));
      const newHostsMap = new Map(newHosts.map((h) => [h.id, h]));

      let hasChanges = false;

      if (newHosts.length !== prevHosts.length) {
        hasChanges = true;
      } else {
        for (const [id, newHost] of newHostsMap) {
          const existingHost = existingHostsMap.get(id);
          if (!existingHost) {
            hasChanges = true;
            break;
          }

          if (
            newHost.name !== existingHost.name ||
            newHost.folder !== existingHost.folder ||
            newHost.ip !== existingHost.ip ||
            newHost.port !== existingHost.port ||
            newHost.username !== existingHost.username ||
            newHost.pin !== existingHost.pin ||
            newHost.enableTerminal !== existingHost.enableTerminal ||
            newHost.enableTunnel !== existingHost.enableTunnel ||
            newHost.enableFileManager !== existingHost.enableFileManager ||
            newHost.authType !== existingHost.authType ||
            newHost.password !== existingHost.password ||
            newHost.key !== existingHost.key ||
            newHost.keyPassword !== existingHost.keyPassword ||
            newHost.keyType !== existingHost.keyType ||
            newHost.defaultPath !== existingHost.defaultPath ||
            JSON.stringify(newHost.tags) !==
              JSON.stringify(existingHost.tags) ||
            JSON.stringify(newHost.tunnelConnections) !==
              JSON.stringify(existingHost.tunnelConnections)
          ) {
            hasChanges = true;
            break;
          }
        }
      }

      if (hasChanges) {
        setTimeout(() => {
          setHosts(newHosts);
          prevHostsRef.current = newHosts;

          newHosts.forEach((newHost) => {
            updateHostConfig(newHost.id, newHost);
          });
        }, 50);
      }
    } catch {
      setHostsError(t("leftSidebar.failedToLoadHosts"));
    }
  }, [updateHostConfig]);

  React.useEffect(() => {
    fetchHosts();
    fetchFolderMetadata();
    const interval = setInterval(() => {
      fetchHosts();
      fetchFolderMetadata();
    }, 300000);
    return () => clearInterval(interval);
  }, [fetchHosts, fetchFolderMetadata]);

  React.useEffect(() => {
    const handleHostsChanged = () => {
      fetchHosts();
      fetchFolderMetadata();
    };
    const handleCredentialsChanged = () => {
      fetchHosts();
    };
    const handleFoldersChanged = () => {
      fetchFolderMetadata();
    };
    window.addEventListener(
      "ssh-hosts:changed",
      handleHostsChanged as EventListener,
    );
    window.addEventListener(
      "credentials:changed",
      handleCredentialsChanged as EventListener,
    );
    window.addEventListener(
      "folders:changed",
      handleFoldersChanged as EventListener,
    );
    return () => {
      window.removeEventListener(
        "ssh-hosts:changed",
        handleHostsChanged as EventListener,
      );
      window.removeEventListener(
        "credentials:changed",
        handleCredentialsChanged as EventListener,
      );
      window.removeEventListener(
        "folders:changed",
        handleFoldersChanged as EventListener,
      );
    };
  }, [fetchHosts, fetchFolderMetadata]);

  React.useEffect(() => {
    const handler = setTimeout(() => setDebouncedSearch(search), 200);
    return () => clearTimeout(handler);
  }, [search]);

  React.useEffect(() => {
    localStorage.setItem("leftSidebarOpen", JSON.stringify(isSidebarOpen));
  }, [isSidebarOpen]);

  const [sidebarWidth, setSidebarWidth] = useState<number>(() => {
    const saved = localStorage.getItem("leftSidebarWidth");
    const defaultWidth = 250;
    const savedWidth = saved !== null ? parseInt(saved, 10) : defaultWidth;
    const minWidth = Math.min(200, Math.floor(window.innerWidth * 0.15));
    const maxWidth = Math.floor(window.innerWidth * 0.3);
    return Math.min(savedWidth, Math.max(minWidth, maxWidth));
  });

  const [isResizing, setIsResizing] = useState(false);
  const startXRef = React.useRef<number | null>(null);
  const startWidthRef = React.useRef<number>(sidebarWidth);

  React.useEffect(() => {
    localStorage.setItem("leftSidebarWidth", String(sidebarWidth));
  }, [sidebarWidth]);

  React.useEffect(() => {
    const handleResize = () => {
      const minWidth = Math.min(200, Math.floor(window.innerWidth * 0.15));
      const maxWidth = Math.floor(window.innerWidth * 0.3);
      if (sidebarWidth > maxWidth) {
        setSidebarWidth(Math.max(minWidth, maxWidth));
      } else if (sidebarWidth < minWidth) {
        setSidebarWidth(minWidth);
      }
    };
    window.addEventListener("resize", handleResize);
    return () => window.removeEventListener("resize", handleResize);
  }, [sidebarWidth]);

  const handleMouseDown = (e: React.MouseEvent) => {
    e.preventDefault();
    setIsResizing(true);
    startXRef.current = e.clientX;
    startWidthRef.current = sidebarWidth;
  };

  React.useEffect(() => {
    if (!isResizing) return;

    const handleMouseMove = (e: MouseEvent) => {
      if (startXRef.current == null) return;
      const dx = e.clientX - startXRef.current;
      const newWidth = Math.round(startWidthRef.current + dx);
      const minWidth = Math.min(200, Math.floor(window.innerWidth * 0.15));
      const maxWidth = Math.round(window.innerWidth * 0.3);
      if (newWidth >= minWidth && newWidth <= maxWidth) {
        setSidebarWidth(newWidth);
      } else if (newWidth < minWidth) {
        setSidebarWidth(minWidth);
      } else if (newWidth > maxWidth) {
        setSidebarWidth(maxWidth);
      }
    };

    const handleMouseUp = () => {
      setIsResizing(false);
      startXRef.current = null;
    };

    document.addEventListener("mousemove", handleMouseMove);
    document.addEventListener("mouseup", handleMouseUp);
    document.body.style.cursor = "col-resize";
    document.body.style.userSelect = "none";

    return () => {
      document.removeEventListener("mousemove", handleMouseMove);
      document.removeEventListener("mouseup", handleMouseUp);
      document.body.style.cursor = "";
      document.body.style.userSelect = "";
    };
  }, [isResizing]);

  const filteredHosts = React.useMemo(() => {
    if (!debouncedSearch.trim()) return hosts;
    const q = debouncedSearch.trim().toLowerCase();
    return hosts.filter((h) => {
      const searchableText = [
        h.name || "",
        h.username,
        h.ip,
        h.folder || "",
        ...(h.tags || []),
        h.authType,
        h.defaultPath || "",
      ]
        .join(" ")
        .toLowerCase();
      return searchableText.includes(q);
    });
  }, [hosts, debouncedSearch]);

  const hostsByFolder = React.useMemo(() => {
    const map: Record<string, SSHHost[]> = {};
    filteredHosts.forEach((h) => {
      const folder =
        h.folder && h.folder.trim() ? h.folder : t("leftSidebar.noFolder");
      if (!map[folder]) map[folder] = [];
      map[folder].push(h);
    });
    return map;
  }, [filteredHosts]);

  const sortedFolders = React.useMemo(() => {
    const folders = Object.keys(hostsByFolder);
    folders.sort((a, b) => {
      if (a === t("leftSidebar.noFolder")) return -1;
      if (b === t("leftSidebar.noFolder")) return 1;
      return a.localeCompare(b);
    });
    return folders;
  }, [hostsByFolder]);

  const getSortedHosts = React.useCallback((arr: SSHHost[]) => {
    const pinned = arr
      .filter((h) => h.pin)
      .sort((a, b) => (a.name || "").localeCompare(b.name || ""));
    const rest = arr
      .filter((h) => !h.pin)
      .sort((a, b) => (a.name || "").localeCompare(b.name || ""));
    return [...pinned, ...rest];
  }, []);

  return (
    <div className="h-screen w-screen overflow-hidden">
      <SidebarProvider
        open={isSidebarOpen}
        style={
          { "--sidebar-width": `${sidebarWidth}px` } as React.CSSProperties
        }
      >
        <div className="flex h-screen w-screen overflow-hidden">
          <Sidebar variant="floating">
            <SidebarHeader>
              <SidebarGroupLabel className="text-lg font-bold text-white">
                Termix
                <div className="absolute right-5 flex gap-1">
                  <Button
                    variant="outline"
                    onClick={() => setSidebarWidth(250)}
                    className="w-[28px] h-[28px]"
                    title="Reset sidebar width"
                  >
                    <RotateCcw className="h-4 w-4" />
                  </Button>
                  <Button
                    variant="outline"
                    onClick={() => setIsSidebarOpen(!isSidebarOpen)}
                    className="w-[28px] h-[28px]"
                    title={t("common.toggleSidebar")}
                  >
                    <Menu className="h-4 w-4" />
                  </Button>
                </div>
              </SidebarGroupLabel>
            </SidebarHeader>
            <Separator className="p-0.25" />
            <SidebarContent>
              <SidebarGroup className="!m-0 !p-0 !-mb-2">
                <Button
                  className="m-2 flex flex-row font-semibold border-2 !border-dark-border"
                  variant="outline"
                  onClick={openSshManagerTab}
                  disabled={isSplitScreenActive}
                  title={
                    isSplitScreenActive
                      ? t("interface.disabledDuringSplitScreen")
                      : undefined
                  }
                >
                  <HardDrive strokeWidth="2.5" />
                  {t("nav.hostManager")}
                </Button>
              </SidebarGroup>
              <Separator className="p-0.25" />
              <SidebarGroup className="flex flex-col gap-y-2 !-mt-2">
                <div className="!bg-dark-bg-input rounded-lg">
                  <Input
                    value={search}
                    onChange={(e) => setSearch(e.target.value)}
                    placeholder={t("placeholders.searchHostsAny")}
                    className="w-full h-8 text-sm border-2 !bg-dark-bg-input border-dark-border rounded-md"
                    autoComplete="off"
                  />
                </div>

                {hostsError && (
                  <div className="!bg-dark-bg-input rounded-lg">
                    <div className="w-full h-8 text-sm border-2 !bg-dark-bg-input border-dark-border rounded-md px-3 py-1.5 flex items-center text-red-500">
                      {t("leftSidebar.failedToLoadHosts")}
                    </div>
                  </div>
                )}

                {hostsLoading && (
                  <div className="px-4 pb-2">
                    <div className="text-xs text-muted-foreground text-center">
                      {t("hosts.loadingHosts")}
                    </div>
                  </div>
                )}

                {sortedFolders.map((folder, idx) => {
                  const metadata = folderMetadata.get(folder);
                  return (
                    <FolderCard
                      key={`folder-${folder}-${hostsByFolder[folder]?.length || 0}`}
                      folderName={folder}
                      hosts={getSortedHosts(hostsByFolder[folder])}
                      isFirst={idx === 0}
                      isLast={idx === sortedFolders.length - 1}
                      folderColor={metadata?.color}
                      folderIcon={metadata?.icon}
                    />
                  );
                })}
              </SidebarGroup>
            </SidebarContent>
            <Separator className="p-0.25 mt-1 mb-1" />
            <SidebarFooter>
              <SidebarMenu>
                <SidebarMenuItem>
                  <DropdownMenu>
                    <DropdownMenuTrigger asChild>
                      <SidebarMenuButton
                        className="data-[state=open]:opacity-90 w-full"
                        disabled={disabled}
                      >
                        <User2 /> {username ? username : t("common.logout")}
                        <ChevronUp className="ml-auto" />
                      </SidebarMenuButton>
                    </DropdownMenuTrigger>
                    <DropdownMenuContent
                      side="top"
                      align="start"
                      sideOffset={6}
                      className="min-w-[var(--radix-popper-anchor-width)] bg-sidebar-accent text-sidebar-accent-foreground border border-border rounded-md shadow-2xl p-1"
                    >
                      <DropdownMenuItem
                        className="rounded px-2 py-1.5 hover:bg-white/15 hover:text-accent-foreground focus:bg-white/20 focus:text-accent-foreground cursor-pointer focus:outline-none"
                        onClick={() => {
                          openUserProfileTab();
                        }}
                      >
                        <span>{t("profile.title")}</span>
                      </DropdownMenuItem>
                      {isAdmin && (
                        <DropdownMenuItem
                          className="rounded px-2 py-1.5 hover:bg-white/15 hover:text-accent-foreground focus:bg-white/20 focus:text-accent-foreground cursor-pointer focus:outline-none"
                          onClick={() => {
                            if (isAdmin) openAdminTab();
                          }}
                        >
                          <span>{t("admin.title")}</span>
                        </DropdownMenuItem>
                      )}
                      <DropdownMenuItem
                        className="rounded px-2 py-1.5 hover:bg-white/15 hover:text-accent-foreground focus:bg-white/20 focus:text-accent-foreground cursor-pointer focus:outline-none"
                        onClick={onLogout || handleLogout}
                      >
                        <span>{t("common.logout")}</span>
                      </DropdownMenuItem>
                    </DropdownMenuContent>
                  </DropdownMenu>
                </SidebarMenuItem>
              </SidebarMenu>
            </SidebarFooter>
            {isSidebarOpen && (
              <div
                className="absolute top-0 h-full cursor-col-resize z-[60]"
                onMouseDown={handleMouseDown}
                style={{
                  right: "-8px",
                  width: "18px",
                  backgroundColor: isResizing
                    ? "var(--dark-active)"
                    : "transparent",
                }}
                onMouseEnter={(e) => {
                  if (!isResizing) {
                    e.currentTarget.style.backgroundColor =
                      "var(--dark-border-hover)";
                  }
                }}
                onMouseLeave={(e) => {
                  if (!isResizing) {
                    e.currentTarget.style.backgroundColor = "transparent";
                  }
                }}
                title="Drag to resize sidebar"
              />
            )}
          </Sidebar>

          <SidebarInset>{children}</SidebarInset>
        </div>
      </SidebarProvider>

      {!isSidebarOpen && (
        <div
          onClick={() => setIsSidebarOpen(true)}
          className="fixed top-0 left-0 w-[10px] h-full cursor-pointer flex items-center justify-center rounded-tr-md rounded-br-md"
          style={{
            zIndex: 9999,
            backgroundColor: "#18181b",
            border: "2px solid #27272a",
            borderLeft: "none",
          }}
        >
          <ChevronRight size={10} />
        </div>
      )}
    </div>
  );
}
