import {
  Folder,
  FolderLock,
  LayoutGrid,
  Plus,
  Search,
  Terminal,
  TerminalSquare,
} from "lucide-react";
import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useI18n } from "../application/i18n/I18nProvider";
import { Host, TerminalSession, Workspace } from "../types";
import { KeyBinding } from "../domain/models";
import { useDiscoveredShells, getShellIconPath, isMonochromeShellIcon } from "../lib/useDiscoveredShells";

type QuickSwitcherItem = {
  type: "host" | "tab" | "workspace" | "action" | "shell";
  id: string;
  data?: Host | TerminalSession | Workspace;
};
import { DistroAvatar } from "./DistroAvatar";
import { Input } from "./ui/input";
import { ScrollArea } from "./ui/scroll-area";

// Compute once at module level
const IS_MAC = typeof navigator !== 'undefined' && /Mac|iPhone|iPad/.test(navigator.platform);

// Memoized host item component to prevent unnecessary re-renders
const HostItem = memo(({
  host,
  isSelected,
  onSelect,
  onMouseEnter,
}: {
  host: Host;
  isSelected: boolean;
  onSelect: (host: Host) => void;
  onMouseEnter: () => void;
}) => (
  <div
    className={`flex items-center justify-between px-4 py-2.5 cursor-pointer transition-colors ${isSelected ? "bg-primary/15" : "hover:bg-muted/50"
      }`}
    onClick={() => onSelect(host)}
    onMouseEnter={onMouseEnter}
  >
    <div className="flex items-center gap-3 min-w-0">
      <DistroAvatar
        host={host}
        fallback={host.label.slice(0, 2).toUpperCase()}
        size="sm"
      />
      <span className="text-sm font-medium truncate">{host.label}</span>
    </div>
    <div className="text-[11px] text-muted-foreground">
      {host.group ? `Personal / ${host.group}` : "Personal"}
    </div>
  </div>
));
HostItem.displayName = "HostItem";

interface QuickSwitcherProps {
  isOpen: boolean;
  query: string;
  results: Host[];
  sessions: TerminalSession[];
  workspaces: Workspace[];
  onQueryChange: (value: string) => void;
  onSelect: (host: Host) => void;
  onSelectTab: (tabId: string) => void;
  onClose: () => void;
  onCreateLocalTerminal?: (shell?: { command: string; args?: string[]; name?: string; icon?: string }) => void;
  onCreateWorkspace?: () => void;
  keyBindings?: KeyBinding[];
  showSftpTab: boolean;
}

const QuickSwitcherInner: React.FC<QuickSwitcherProps> = ({
  isOpen,
  query,
  results,
  sessions,
  workspaces,
  onQueryChange,
  onSelect,
  onSelectTab,
  onClose,
  onCreateLocalTerminal,
  onCreateWorkspace,
  keyBindings,
  showSftpTab,
}) => {
  const { t } = useI18n();
  const discoveredShells = useDiscoveredShells();

  const filteredShells = useMemo(() => {
    const list = !query.trim()
      ? discoveredShells
      : discoveredShells.filter(
          (s) => s.name.toLowerCase().includes(query.toLowerCase()) || s.id.toLowerCase().includes(query.toLowerCase())
        );
    // Default shell first
    return [...list].sort((a, b) => (a.isDefault === b.isDefault ? 0 : a.isDefault ? -1 : 1));
  }, [discoveredShells, query]);

  // Get hotkey display strings
  const getHotkeyLabel = useCallback((actionId: string) => {
    const binding = keyBindings?.find(k => k.id === actionId);
    if (!binding) return '';
    return IS_MAC ? binding.mac : binding.pc;
  }, [keyBindings]);
  const quickSwitchKey = getHotkeyLabel('quick-switch');
  const [selectedIndex, setSelectedIndex] = useState(0);
  const inputRef = useRef<HTMLInputElement>(null);
  const containerRef = useRef<HTMLDivElement>(null);

  // Reset state when opening
  useEffect(() => {
    if (!isOpen) return;

    const focusTimer = window.setTimeout(() => {
      inputRef.current?.focus();
    }, 50);

    setSelectedIndex(0);

    return () => {
      window.clearTimeout(focusTimer);
    };
  }, [isOpen]);

  // Handle clicks outside the container
  useEffect(() => {
    if (!isOpen) return;

    const handleClickOutside = (e: MouseEvent) => {
      if (
        containerRef.current &&
        !containerRef.current.contains(e.target as Node)
      ) {
        onClose();
      }
    };

    document.addEventListener("mousedown", handleClickOutside);
    return () => document.removeEventListener("mousedown", handleClickOutside);
  }, [isOpen, onClose]);

  // Memoize orphan sessions
  const orphanSessions = useMemo(
    () => sessions.filter((s) => !s.workspaceId),
    [sessions]
  );

  // Always show categorized view (Hosts/Tabs/Quick connect)
  const showCategorized = true;

  // Memoize flat items list and index map
  const { flatItems, itemIndexMap } = useMemo(() => {
    const items: QuickSwitcherItem[] = [];

    if (showCategorized) {
      // Hosts
      results.forEach((host) =>
        items.push({ type: "host", id: host.id, data: host }),
      );
      // Tabs (built-in + sessions + workspaces)
      items.push({ type: "tab", id: "vault" });
      if (showSftpTab) items.push({ type: "tab", id: "sftp" });
      orphanSessions.forEach((s) =>
        items.push({ type: "tab", id: s.id, data: s }),
      );
      workspaces.forEach((w) =>
        items.push({ type: "workspace", id: w.id, data: w }),
      );
      // Local shells (or fallback action if discovery not ready)
      if (filteredShells.length > 0) {
        filteredShells.forEach((shell) =>
          items.push({ type: "shell", id: shell.id }),
        );
      } else {
        items.push({ type: "action", id: "local-terminal" });
      }
    } else {
      // Recent connections only
      results.forEach((host) =>
        items.push({ type: "host", id: host.id, data: host }),
      );
      // Also include matching shells in search results
      filteredShells.forEach((shell) =>
        items.push({ type: "shell", id: shell.id }),
      );
    }

    // Build index map for O(1) lookup
    const indexMap = new Map<string, number>();
    items.forEach((item, idx) => {
      indexMap.set(`${item.type}:${item.id}`, idx);
    });

    return { flatItems: items, itemIndexMap: indexMap };
  }, [showCategorized, results, orphanSessions, workspaces, filteredShells, showSftpTab]);

  // O(1) index lookup
  const getItemIndex = useCallback((type: string, id: string) => {
    return itemIndexMap.get(`${type}:${id}`) ?? -1;
  }, [itemIndexMap]);

  if (!isOpen) return null;

  const handleKeyDown = (e: React.KeyboardEvent) => {
    if (e.key === "ArrowDown") {
      e.preventDefault();
      setSelectedIndex((prev) => Math.min(prev + 1, flatItems.length - 1));
    } else if (e.key === "ArrowUp") {
      e.preventDefault();
      setSelectedIndex((prev) => Math.max(prev - 1, 0));
    } else if (e.key === "Enter" && flatItems.length > 0) {
      e.preventDefault();
      const item = flatItems[selectedIndex];
      handleItemSelect(item);
    }
  };

  const handleItemSelect = (item: QuickSwitcherItem) => {
    switch (item.type) {
      case "host":
        onSelect(item.data as Host);
        break;
      case "tab":
      case "workspace":
        onSelectTab(item.id);
        onClose();
        break;
      case "action":
        if (item.id === "local-terminal" && onCreateLocalTerminal) {
          onCreateLocalTerminal();
          onClose();
        }
        break;
      case "shell": {
        const shell = discoveredShells.find(s => s.id === item.id);
        if (shell && onCreateLocalTerminal) {
          onCreateLocalTerminal({ command: shell.command, args: shell.args, name: shell.name, icon: shell.icon });
          onClose();
        }
        break;
      }
    }
  };

  return (
    <div
      className="fixed inset-x-0 top-12 z-50 flex justify-center pt-2"
      style={{ pointerEvents: "none" }}
    >
      <div
        ref={containerRef}
        className="w-full max-w-2xl mx-4 bg-background border border-border rounded-xl shadow-2xl overflow-hidden max-h-[520px] flex flex-col"
        style={{ pointerEvents: "auto" }}
      >
        {/* Search Header */}
        <div className="flex items-center gap-3 px-4 py-3 border-b border-border">
          <Search size={16} className="text-muted-foreground" />
          <Input
            ref={inputRef}
            value={query}
            onChange={(e) => {
              onQueryChange(e.target.value);
              setSelectedIndex(0);
            }}
            onKeyDown={handleKeyDown}
            placeholder={t("qs.search.placeholder")}
            className="flex-1 h-8 border-0 bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0 px-0 text-sm"
          />
          {quickSwitchKey && (
            <kbd className="text-[11px] text-muted-foreground bg-muted px-1.5 py-0.5 rounded">
              {quickSwitchKey.replace(/ \+ /g, '+')}
            </kbd>
          )}
        </div>

        <ScrollArea className="flex-1 h-full">
          {/* Categorized view: Hosts/Tabs/Quick connect */}
          <div>
            {/* Jump To hint + New Workspace action */}
            <div className="px-4 py-2 flex items-center gap-2">
              <span className="text-xs text-muted-foreground">{t("qs.jumpTo")}</span>
              {quickSwitchKey && (
                <kbd className="text-[10px] text-muted-foreground bg-muted px-1 py-0.5 rounded">
                  {quickSwitchKey.replace(/ \+ /g, '+')}
                </kbd>
              )}
              {onCreateWorkspace && (
                <button
                  type="button"
                  onClick={() => {
                    onCreateWorkspace();
                    onClose();
                  }}
                  className="ml-auto inline-flex items-center gap-1 text-[11px] text-muted-foreground hover:text-foreground border border-border rounded px-1.5 py-0.5 transition-colors hover:bg-muted/50"
                >
                  <Plus size={11} />
                  <span>New Workspace</span>
                </button>
              )}
            </div>

            {/* Hosts section */}
            {results.length > 0 && (
              <div>
                <div className="px-4 py-1.5">
                  <span className="text-xs font-medium text-muted-foreground">
                    Hosts
                  </span>
                </div>
                {results.map((host) => (
                  <HostItem
                    key={host.id}
                    host={host}
                    isSelected={getItemIndex("host", host.id) === selectedIndex}
                    onSelect={onSelect}
                    onMouseEnter={() => setSelectedIndex(getItemIndex("host", host.id))}
                  />
                ))}
              </div>
            )}

            {/* Tabs section */}
            <div>
              <div className="px-4 py-1.5">
                <span className="text-xs font-medium text-muted-foreground">
                  Tabs
                </span>
              </div>

              {/* Built-in tabs */}
              {(showSftpTab ? ["vault", "sftp"] : ["vault"]).map((tabId) => {
                const idx = getItemIndex("tab", tabId);
                const isSelected = idx === selectedIndex;
                const icon =
                  tabId === "vault" ? (
                    <FolderLock size={16} />
                  ) : (
                    <Folder size={16} />
                  );
                const label = tabId === "vault" ? "Vaults" : "SFTP";

                return (
                  <div
                    key={tabId}
                    className={`flex items-center gap-3 px-4 py-2.5 cursor-pointer transition-colors ${isSelected ? "bg-primary/15" : "hover:bg-muted/50"
                      }`}
                    onClick={() => {
                      onSelectTab(tabId);
                      onClose();
                    }}
                    onMouseEnter={() => setSelectedIndex(idx)}
                  >
                    <div className="h-6 w-6 rounded flex items-center justify-center text-muted-foreground">
                      {icon}
                    </div>
                    <span className="text-sm font-medium">{label}</span>
                  </div>
                );
              })}

              {/* Workspaces */}
              {workspaces.map((workspace) => {
                const idx = getItemIndex("workspace", workspace.id);
                const isSelected = idx === selectedIndex;

                return (
                  <div
                    key={workspace.id}
                    className={`flex items-center gap-3 px-4 py-2.5 cursor-pointer transition-colors ${isSelected ? "bg-primary/15" : "hover:bg-muted/50"
                      }`}
                    onClick={() => {
                      onSelectTab(workspace.id);
                      onClose();
                    }}
                    onMouseEnter={() => setSelectedIndex(idx)}
                  >
                    <div className="h-6 w-6 rounded flex items-center justify-center text-muted-foreground">
                      <LayoutGrid size={16} />
                    </div>
                    <span className="text-sm font-medium">
                      {workspace.title}
                    </span>
                  </div>
                );
              })}

              {/* Orphan sessions */}
              {orphanSessions.map((session) => {
                const idx = getItemIndex("tab", session.id);
                const isSelected = idx === selectedIndex;

                return (
                  <div
                    key={session.id}
                    className={`flex items-center gap-3 px-4 py-2.5 cursor-pointer transition-colors ${isSelected ? "bg-primary/15" : "hover:bg-muted/50"
                      }`}
                    onClick={() => {
                      onSelectTab(session.id);
                      onClose();
                    }}
                    onMouseEnter={() => setSelectedIndex(idx)}
                  >
                    <div className="h-6 w-6 rounded flex items-center justify-center text-muted-foreground">
                      <TerminalSquare size={16} />
                    </div>
                    <span className="text-sm font-medium">
                      {session.hostLabel}
                    </span>
                  </div>
                );
              })}
            </div>

            {/* Local Shells section */}
            {/* Local Shells or fallback Local Terminal */}
            {filteredShells.length > 0 ? (
              <div>
                <div className="px-4 py-1.5">
                  <span className="text-xs font-medium text-muted-foreground">
                    {t("qs.localShells")}
                  </span>
                </div>
                {filteredShells.map((shell) => {
                  const idx = getItemIndex("shell", shell.id);
                  const isSelected = idx === selectedIndex;
                  return (
                    <div
                      key={shell.id}
                      className={`flex items-center gap-3 px-4 py-2.5 cursor-pointer transition-colors ${
                        isSelected ? "bg-primary/15" : "hover:bg-muted/50"
                      }`}
                      onClick={() => {
                        if (onCreateLocalTerminal) {
                          onCreateLocalTerminal({ command: shell.command, args: shell.args, name: shell.name, icon: shell.icon });
                          onClose();
                        }
                      }}
                      onMouseEnter={() => setSelectedIndex(idx)}
                    >
                      <img
                        src={getShellIconPath(shell.icon)}
                        alt={shell.name}
                        className={`h-6 w-6 shrink-0${isMonochromeShellIcon(shell.icon) ? " dark:invert" : ""}`}
                      />
                      <span className="text-sm font-medium">{shell.name}</span>
                      {shell.isDefault && (
                        <span className="text-[10px] text-muted-foreground bg-muted px-1.5 py-0.5 rounded">
                          {t("qs.default")}
                        </span>
                      )}
                    </div>
                  );
                })}
              </div>
            ) : onCreateLocalTerminal && (
              <div>
                <div className="px-4 py-1.5">
                  <span className="text-xs font-medium text-muted-foreground">
                    {t("qs.localShells")}
                  </span>
                </div>
                <div
                  className={`flex items-center gap-3 px-4 py-2.5 cursor-pointer transition-colors ${
                    getItemIndex("action", "local-terminal") === selectedIndex
                      ? "bg-primary/15"
                      : "hover:bg-muted/50"
                  }`}
                  onClick={() => {
                    onCreateLocalTerminal();
                    onClose();
                  }}
                  onMouseEnter={() =>
                    setSelectedIndex(getItemIndex("action", "local-terminal"))
                  }
                >
                  <div className="h-6 w-6 rounded flex items-center justify-center text-muted-foreground">
                    <Terminal size={16} />
                  </div>
                  <span className="text-sm font-medium">{t("qs.localTerminal")}</span>
                </div>
              </div>
            )}
          </div>
        </ScrollArea>
      </div>
    </div>
  );
};

export const QuickSwitcher = memo(QuickSwitcherInner);
QuickSwitcher.displayName = "QuickSwitcher";
