import { useState, useEffect, useRef, useCallback, useMemo } from 'react';
import { Search, Loader2, Network, HardDrive, Box, Database, ArrowLeftRight, ArrowUpDown, Router, Wifi, Monitor, Container, FolderTree, Folder, X } from 'lucide-react';
import { useTopologyStore } from '../store/topologyStore';
import { NodeType } from '../types';

interface Command {
  id: string;
  label: string;
  description?: string;
  icon: React.ReactNode;
  category: 'action' | 'filter' | 'view' | 'orientation';
  action: () => void;
}

  const nodeTypeLabels: Record<NodeType, string> = {
    gateway: 'Gateway',
    vlan: 'VLAN',
    wifi: 'WiFi',
    host_physical: 'Physical Host',
    host_vm: 'VM Host',
    host_container: 'Container Host',
    vm_lxc: 'LXC Container',
    vm_qemu: 'QEMU VM',
    systemd_service: 'Systemd Service',
    service: 'Service',
    volume: 'Volume',
    mount: 'Mount',
    path: 'Path',
  };

const nodeTypeIcons: Record<NodeType, React.ReactNode> = {
  gateway: <Router className="w-4 h-4" />,
  vlan: <Network className="w-4 h-4" />,
  wifi: <Wifi className="w-4 h-4" />,
  host_physical: <HardDrive className="w-4 h-4" />,
  host_vm: <Monitor className="w-4 h-4" />,
  host_container: <Container className="w-4 h-4" />,
  vm_lxc: <Container className="w-4 h-4" />,
  vm_qemu: <Monitor className="w-4 h-4" />,
  systemd_service: <Box className="w-4 h-4" />,
  service: <Box className="w-4 h-4" />,
  volume: <Database className="w-4 h-4" />,
  mount: <FolderTree className="w-4 h-4" />,
  path: <Folder className="w-4 h-4" />
};

function fuzzyMatch(pattern: string, text: string): boolean {
  const patternLower = pattern.toLowerCase();
  const textLower = text.toLowerCase();
  
  let patternIdx = 0;
  for (let i = 0; i < textLower.length && patternIdx < patternLower.length; i++) {
    if (textLower[i] === patternLower[patternIdx]) {
      patternIdx++;
    }
  }
  
  return patternIdx === patternLower.length;
}

interface CommandPaletteProps {
  onRefresh?: () => Promise<void>;
}

export default function CommandPalette({ onRefresh }: CommandPaletteProps) {
  const { 
    commandPaletteOpen, 
    toggleCommandPalette,
    typeFilters,
    toggleTypeFilter,
    setViewMode,
    setOrientation
  } = useTopologyStore();

  const [search, setSearch] = useState('');
  const [selectedIndex, setSelectedIndex] = useState(0);
  const inputRef = useRef<HTMLInputElement>(null);
  const listRef = useRef<HTMLDivElement>(null);

  const commands = useMemo<Command[]>(() => {
    const cmds: Command[] = [
      {
        id: 'refresh',
        label: 'Refresh Discovery',
        description: 'Reload topology data from hosts',
        icon: <Loader2 className="w-4 h-4" />,
        category: 'action',
        action: async () => {
          if (onRefresh) {
            await onRefresh();
          }
          toggleCommandPalette();
        }
      },
      {
        id: 'view-full',
        label: 'Set View: Full',
        description: 'Show complete topology',
        icon: <Network className="w-4 h-4" />,
        category: 'view',
        action: () => {
          setViewMode('full');
          toggleCommandPalette();
        }
      },
      {
        id: 'view-network',
        label: 'Set View: Network',
        description: 'Show network infrastructure',
        icon: <Network className="w-4 h-4" />,
        category: 'view',
        action: () => {
          setViewMode('network');
          toggleCommandPalette();
        }
      },
      {
        id: 'view-host',
        label: 'Set View: Hosts',
        description: 'Show hosts and containers',
        icon: <HardDrive className="w-4 h-4" />,
        category: 'view',
        action: () => {
          setViewMode('host');
          toggleCommandPalette();
        }
      },
      {
        id: 'view-service',
        label: 'Set View: Services',
        description: 'Show services and volumes',
        icon: <Box className="w-4 h-4" />,
        category: 'view',
        action: () => {
          setViewMode('service');
          toggleCommandPalette();
        }
      },
      {
        id: 'view-filesystem',
        label: 'Set View: Files',
        description: 'Show filesystem hierarchy',
        icon: <Database className="w-4 h-4" />,
        category: 'view',
        action: () => {
          setViewMode('filesystem');
          toggleCommandPalette();
        }
      },
      {
        id: 'orientation-lr',
        label: 'Set Orientation: Left to Right',
        icon: <ArrowLeftRight className="w-4 h-4" />,
        category: 'orientation',
        action: () => {
          setOrientation('LR');
          toggleCommandPalette();
        }
      },
      {
        id: 'orientation-tb',
        label: 'Set Orientation: Top to Bottom',
        icon: <ArrowUpDown className="w-4 h-4" />,
        category: 'orientation',
        action: () => {
          setOrientation('TB');
          toggleCommandPalette();
        }
      }
    ];

    const nodeTypes: NodeType[] = [
      'gateway', 'vlan', 'wifi', 'host_physical', 'host_vm', 
      'host_container', 'service', 'volume', 'mount', 'path'
    ];

    nodeTypes.forEach((type) => {
      const isActive = typeFilters.includes(type);
      cmds.push({
        id: `filter-${type}`,
        label: `${isActive ? 'Disable' : 'Enable'} Filter: ${nodeTypeLabels[type]}`,
        description: `${isActive ? 'Hide' : 'Show'} ${nodeTypeLabels[type]} nodes`,
        icon: nodeTypeIcons[type],
        category: 'filter',
        action: () => {
          toggleTypeFilter(type);
          toggleCommandPalette();
        }
      });
    });

    return cmds;
  }, [typeFilters, onRefresh, setViewMode, setOrientation, toggleTypeFilter, toggleCommandPalette]);

  const filteredCommands = useMemo(() => {
    if (!search.trim()) return commands;
    return commands.filter(cmd => fuzzyMatch(search, cmd.label));
  }, [commands, search]);

  useEffect(() => {
    setSelectedIndex(0);
  }, [filteredCommands.length]);

  useEffect(() => {
    if (commandPaletteOpen) {
      setSearch('');
      setSelectedIndex(0);
      setTimeout(() => inputRef.current?.focus(), 50);
    }
  }, [commandPaletteOpen]);

  useEffect(() => {
    if (listRef.current) {
      const selectedEl = listRef.current.children[selectedIndex] as HTMLElement;
      if (selectedEl) {
        selectedEl.scrollIntoView({ block: 'nearest' });
      }
    }
  }, [selectedIndex]);

  const handleKeyDown = useCallback((e: React.KeyboardEvent) => {
    switch (e.key) {
      case 'ArrowDown':
        e.preventDefault();
        setSelectedIndex(prev => Math.min(prev + 1, filteredCommands.length - 1));
        break;
      case 'ArrowUp':
        e.preventDefault();
        setSelectedIndex(prev => Math.max(prev - 1, 0));
        break;
      case 'Enter':
        e.preventDefault();
        if (filteredCommands[selectedIndex]) {
          filteredCommands[selectedIndex].action();
        }
        break;
      case 'Escape':
        e.preventDefault();
        toggleCommandPalette();
        break;
    }
  }, [filteredCommands, selectedIndex, toggleCommandPalette]);

  const handleBackdropClick = useCallback((e: React.MouseEvent) => {
    if (e.target === e.currentTarget) {
      toggleCommandPalette();
    }
  }, [toggleCommandPalette]);

  if (!commandPaletteOpen) return null;

  const categoryLabels: Record<Command['category'], string> = {
    action: 'Actions',
    filter: 'Filters',
    view: 'View Mode',
    orientation: 'Orientation'
  };

  const groupedCommands = filteredCommands.reduce((acc, cmd) => {
    if (!acc[cmd.category]) {
      acc[cmd.category] = [];
    }
    acc[cmd.category].push(cmd);
    return acc;
  }, {} as Record<Command['category'], Command[]>);

  let globalIndex = 0;

  return (
    <div 
      className="fixed inset-0 z-50 flex items-start justify-center pt-[15vh] bg-black/60 backdrop-blur-sm"
      onClick={handleBackdropClick}
    >
      <div className="w-full max-w-xl bg-slate-800 rounded-xl shadow-2xl border border-slate-700 overflow-hidden animate-in fade-in zoom-in-95 duration-150">
        <div className="flex items-center gap-3 px-4 py-3 border-b border-slate-700">
          <Search className="w-5 h-5 text-slate-400 flex-shrink-0" />
          <input
            ref={inputRef}
            type="text"
            placeholder="Type a command..."
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            onKeyDown={handleKeyDown}
            className="flex-1 bg-transparent text-white placeholder-slate-400 outline-none text-base"
          />
          <button
            onClick={toggleCommandPalette}
            className="p-1 text-slate-400 hover:text-white hover:bg-slate-700 rounded"
          >
            <X className="w-4 h-4" />
          </button>
        </div>

        <div ref={listRef} className="max-h-[50vh] overflow-y-auto py-2">
          {filteredCommands.length === 0 ? (
            <div className="px-4 py-8 text-center text-slate-400">
              No commands found
            </div>
          ) : (
            Object.entries(groupedCommands).map(([category, cmds]) => (
              <div key={category}>
                <div className="px-4 py-2 text-xs font-medium text-slate-500 uppercase tracking-wider">
                  {categoryLabels[category as Command['category']]}
                </div>
                {cmds.map((cmd) => {
                  const currentIndex = globalIndex++;
                  const isSelected = currentIndex === selectedIndex;
                  
                  return (
                    <button
                      key={cmd.id}
                      onClick={cmd.action}
                      onMouseEnter={() => setSelectedIndex(currentIndex)}
                      className={`w-full flex items-center gap-3 px-4 py-2.5 text-left transition-colors ${
                        isSelected 
                          ? 'bg-indigo-500/20 text-white' 
                          : 'text-slate-300 hover:bg-slate-700/50'
                      }`}
                    >
                      <span className={`flex-shrink-0 ${isSelected ? 'text-indigo-400' : 'text-slate-400'}`}>
                        {cmd.icon}
                      </span>
                      <div className="flex-1 min-w-0">
                        <div className="font-medium truncate">{cmd.label}</div>
                        {cmd.description && (
                          <div className="text-xs text-slate-500 truncate">{cmd.description}</div>
                        )}
                      </div>
                      {isSelected && (
                        <span className="text-xs text-slate-500 flex-shrink-0">
                          Enter
                        </span>
                      )}
                    </button>
                  );
                })}
              </div>
            ))
          )}
        </div>

        <div className="px-4 py-2 border-t border-slate-700 flex items-center gap-4 text-xs text-slate-500">
          <span className="flex items-center gap-1">
            <kbd className="px-1.5 py-0.5 bg-slate-700 rounded text-slate-400">↑↓</kbd>
            Navigate
          </span>
          <span className="flex items-center gap-1">
            <kbd className="px-1.5 py-0.5 bg-slate-700 rounded text-slate-400">Enter</kbd>
            Select
          </span>
          <span className="flex items-center gap-1">
            <kbd className="px-1.5 py-0.5 bg-slate-700 rounded text-slate-400">Esc</kbd>
            Close
          </span>
        </div>
      </div>
    </div>
  );
}
