import { useEffect, useRef, useState, useCallback } from 'react';
import { Search, Play, Zap } from 'lucide-react';
import { Input } from '../ui/input';
import { Badge } from '../ui/badge';
import { ScrollArea } from '../ui/scroll-area';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../ui/tooltip';
import {
  AvailableContext,
  ContextVariable,
  ContextVariableType,
} from '../../types/workflow-context';

interface SuggestionDropdownProps {
  /** Available context from preceding nodes */
  availableContext: AvailableContext;
  /** Callback when a variable is selected */
  onSelect: (variable: ContextVariable) => void;
  /** Callback when dropdown should close */
  onClose: () => void;
  /** Position of the dropdown */
  position: { top: number; left: number } | null;
  /** Initial search query (text typed after @) */
  initialQuery?: string;
  /** Optional type filter - only show variables of these types */
  allowedTypes?: ContextVariableType[];
}

/**
 * Floating dropdown for variable suggestions.
 * Appears at cursor position when user types @.
 */
export function SuggestionDropdown({
  availableContext,
  onSelect,
  onClose,
  position,
  initialQuery = '',
  allowedTypes,
}: SuggestionDropdownProps) {
  const [searchQuery, setSearchQuery] = useState(initialQuery);
  const [selectedIndex, setSelectedIndex] = useState(0);
  const dropdownRef = useRef<HTMLDivElement>(null);
  const inputRef = useRef<HTMLInputElement>(null);

  // Update search when initialQuery changes (user typing after @)
  useEffect(() => {
    setSearchQuery(initialQuery);
  }, [initialQuery]);

  // Filter groups and variables based on search query AND allowed types
  const filteredGroups = availableContext.groups
    .map((group) => ({
      ...group,
      variables: group.variables.filter((v) => {
        // First check type filter
        if (allowedTypes && allowedTypes.length > 0 && !allowedTypes.includes(v.type)) {
          return false;
        }
        // Then check search query
        return (
          v.label.toLowerCase().includes(searchQuery.toLowerCase()) ||
          v.path.toLowerCase().includes(searchQuery.toLowerCase()) ||
          v.description.toLowerCase().includes(searchQuery.toLowerCase())
        );
      }),
    }))
    .filter((group) => group.variables.length > 0);

  // Calculate warning state for type filtering
  const totalAvailableVariables = availableContext.groups.reduce(
    (sum, g) => sum + g.variables.length,
    0,
  );
  const hasTypeFilter = allowedTypes && allowedTypes.length > 0;
  const noMatchingTypes =
    hasTypeFilter && totalAvailableVariables > 0 && filteredGroups.length === 0 && !searchQuery;

  // Flatten variables for keyboard navigation
  const flatVariables = filteredGroups.flatMap((g) => g.variables);

  // Reset selection when filter changes
  useEffect(() => {
    setSelectedIndex(0);
  }, [searchQuery]);

  // Handle keyboard navigation
  const handleKeyDown = useCallback(
    (e: KeyboardEvent) => {
      if (!position) return;

      switch (e.key) {
        case 'ArrowDown':
          e.preventDefault();
          setSelectedIndex((prev) => (prev < flatVariables.length - 1 ? prev + 1 : 0));
          break;
        case 'ArrowUp':
          e.preventDefault();
          setSelectedIndex((prev) => (prev > 0 ? prev - 1 : flatVariables.length - 1));
          break;
        case 'Enter':
        case 'Tab':
          e.preventDefault();
          if (flatVariables[selectedIndex]) {
            onSelect(flatVariables[selectedIndex]);
          }
          break;
        case 'Escape':
          e.preventDefault();
          onClose();
          break;
      }
    },
    [flatVariables, selectedIndex, onSelect, onClose, position],
  );

  // Attach keyboard listener
  useEffect(() => {
    document.addEventListener('keydown', handleKeyDown);
    return () => document.removeEventListener('keydown', handleKeyDown);
  }, [handleKeyDown]);

  // Close on outside click
  useEffect(() => {
    const handleClickOutside = (e: MouseEvent) => {
      if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) {
        onClose();
      }
    };
    document.addEventListener('mousedown', handleClickOutside);
    return () => document.removeEventListener('mousedown', handleClickOutside);
  }, [onClose]);

  const getTypeColor = (type: string): string => {
    switch (type) {
      case 'string':
        return 'bg-blue-100 text-blue-800 border-blue-200';
      case 'integer':
        return 'bg-green-100 text-green-800 border-green-200';
      case 'boolean':
        return 'bg-purple-100 text-purple-800 border-purple-200';
      case 'datetime':
        return 'bg-orange-100 text-orange-800 border-orange-200';
      case 'array':
        return 'bg-gray-100 text-gray-800 border-gray-200';
      default:
        return 'bg-gray-100 text-gray-800 border-gray-200';
    }
  };

  if (!position) return null;

  const isEmpty = availableContext.groups.length === 0;

  // Calculate position with viewport bounds checking
  const viewportHeight = typeof window !== 'undefined' ? window.innerHeight : 800;
  const maxDropdownHeight = Math.min(400, viewportHeight - position.top - 20);
  // Reserve space for search (~48px) and footer (~40px)
  const scrollAreaMaxHeight = maxDropdownHeight - 88;

  const dropdownStyle: React.CSSProperties = {
    position: 'fixed',
    top: position.top,
    left: Math.max(10, position.left), // Ensure at least 10px from left edge
    zIndex: 9999,
  };

  return (
    <div
      ref={dropdownRef}
      style={dropdownStyle}
      className="w-80 bg-white border border-slate-200 rounded-md shadow-lg flex flex-col"
    >
      {/* Search input */}
      <div className="p-2 border-b border-slate-200">
        <div className="relative">
          <Search className="absolute left-2 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-400" />
          <Input
            ref={inputRef}
            placeholder="Search variables..."
            value={searchQuery}
            onChange={(e) => setSearchQuery(e.target.value)}
            className="pl-8 h-8 text-sm"
            autoFocus
          />
        </div>
      </div>

      {/* Variable groups */}
      <ScrollArea style={{ maxHeight: scrollAreaMaxHeight }}>
        {isEmpty ? (
          <div className="p-4 text-center text-sm text-slate-500">
            No variables available (add preceding nodes)
          </div>
        ) : noMatchingTypes ? (
          <div className="p-4 text-center text-sm text-amber-600">
            <span className="block font-medium mb-1">No compatible variables</span>
            <span className="text-xs">
              This field requires {allowedTypes?.join(' or ')} type variables
            </span>
          </div>
        ) : filteredGroups.length === 0 ? (
          <div className="p-4 text-center text-sm text-slate-500">No matching variables found</div>
        ) : (
          <div className="py-1">
            {filteredGroups.map((group, groupIndex) => {
              // Calculate the starting index for this group
              const startIndex = filteredGroups
                .slice(0, groupIndex)
                .reduce((acc, g) => acc + g.variables.length, 0);

              return (
                <div key={group.namespace}>
                  {groupIndex > 0 && <div className="h-px bg-slate-200 my-1" />}
                  <div className="px-3 py-1.5 text-xs font-semibold text-slate-500 flex items-center gap-2">
                    {group.sourceType === 'trigger' ? (
                      <Play className="w-3 h-3 text-success" />
                    ) : (
                      <Zap className="w-3 h-3 text-cyan-600" />
                    )}
                    <span className="truncate">{group.sourceName}</span>
                  </div>
                  {group.variables.map((variable, varIndex) => {
                    const absoluteIndex = startIndex + varIndex;
                    const isSelected = absoluteIndex === selectedIndex;

                    return (
                      <TooltipProvider key={variable.path}>
                        <Tooltip delayDuration={300}>
                          <TooltipTrigger asChild>
                            <button
                              onClick={() => onSelect(variable)}
                              className={`w-full flex items-center justify-between cursor-pointer py-2 px-3 text-left
                                ${isSelected ? 'bg-slate-100' : 'hover:bg-slate-50'}`}
                            >
                              <div className="flex flex-col gap-0.5 min-w-0">
                                <span className="text-sm font-medium truncate">
                                  {variable.label}
                                </span>
                                <code className="text-xs text-slate-500 font-mono truncate">
                                  {`{{${variable.path}}}`}
                                </code>
                              </div>
                              <Badge
                                variant="outline"
                                className={`text-xs ml-2 shrink-0 ${getTypeColor(variable.type)}`}
                              >
                                {variable.type}
                              </Badge>
                            </button>
                          </TooltipTrigger>
                          <TooltipContent side="left" className="max-w-xs">
                            <p className="text-sm">{variable.description}</p>
                            <p className="text-xs text-slate-500 mt-1">
                              Example: <code>{variable.example}</code>
                            </p>
                          </TooltipContent>
                        </Tooltip>
                      </TooltipProvider>
                    );
                  })}
                </div>
              );
            })}
          </div>
        )}
      </ScrollArea>

      {/* Hint footer */}
      <div className="px-3 py-2 border-t border-slate-200 text-xs text-slate-500">
        <kbd className="px-1.5 py-0.5 bg-slate-100 rounded text-[10px]">↑↓</kbd> navigate{' '}
        <kbd className="px-1.5 py-0.5 bg-slate-100 rounded text-[10px] ml-2">Enter</kbd> select{' '}
        <kbd className="px-1.5 py-0.5 bg-slate-100 rounded text-[10px] ml-2">Esc</kbd> close
      </div>
    </div>
  );
}
