/**
 * Search input with autocomplete suggestions and recent searches.
 */

import { useState, useRef, useEffect, FormEvent, KeyboardEvent } from 'react';
import { useNavigate } from 'react-router-dom';
import {
  Search,
  Clock,
  Box,
  FileText,
  Wallet,
  X,
  ArrowRight,
  Trash2,
} from 'lucide-react';
import { useRecentSearches, type RecentSearch } from '../hooks/useRecentSearches';
import { cn, truncateHash } from '../lib/utils';

interface SearchAutocompleteProps {
  className?: string;
  placeholder?: string;
  onSearch?: (query: string) => void;
}

export default function SearchAutocomplete({
  className,
  placeholder = 'Search by address, tx hash, or block...',
  onSearch,
}: SearchAutocompleteProps) {
  const [query, setQuery] = useState('');
  const [isOpen, setIsOpen] = useState(false);
  const [selectedIndex, setSelectedIndex] = useState(-1);
  const inputRef = useRef<HTMLInputElement>(null);
  const dropdownRef = useRef<HTMLDivElement>(null);
  const navigate = useNavigate();
  const { searches, addSearch, removeSearch, clearSearches } = useRecentSearches();

  // Filter recent searches based on current query
  const filteredSearches = query.trim()
    ? searches.filter((s) =>
        s.query.toLowerCase().includes(query.toLowerCase())
      )
    : searches;

  // Generate suggestions based on query format
  const suggestions = generateSuggestions(query);

  // Combined items for keyboard navigation
  const allItems = [...suggestions, ...filteredSearches.slice(0, 5)];

  // Handle click outside to close dropdown
  useEffect(() => {
    function handleClickOutside(event: MouseEvent) {
      if (
        dropdownRef.current &&
        !dropdownRef.current.contains(event.target as Node) &&
        !inputRef.current?.contains(event.target as Node)
      ) {
        setIsOpen(false);
      }
    }

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

  // Reset selected index when query changes
  useEffect(() => {
    setSelectedIndex(-1);
  }, [query]);

  const handleSubmit = (e: FormEvent) => {
    e.preventDefault();
    if (query.trim()) {
      executeSearch(query.trim());
    }
  };

  const executeSearch = (searchQuery: string) => {
    addSearch(searchQuery);
    setQuery('');
    setIsOpen(false);

    if (onSearch) {
      onSearch(searchQuery);
    } else {
      navigate(`/search?q=${encodeURIComponent(searchQuery)}`);
    }
  };

  const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
    if (!isOpen) {
      if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
        setIsOpen(true);
        e.preventDefault();
      }
      return;
    }

    switch (e.key) {
      case 'ArrowDown':
        e.preventDefault();
        setSelectedIndex((prev) =>
          prev < allItems.length - 1 ? prev + 1 : prev
        );
        break;
      case 'ArrowUp':
        e.preventDefault();
        setSelectedIndex((prev) => (prev > 0 ? prev - 1 : -1));
        break;
      case 'Enter':
        e.preventDefault();
        if (selectedIndex >= 0 && selectedIndex < allItems.length) {
          const item = allItems[selectedIndex];
          const searchQuery = 'query' in item ? item.query : item.value;
          executeSearch(searchQuery);
        } else if (query.trim()) {
          executeSearch(query.trim());
        }
        break;
      case 'Escape':
        setIsOpen(false);
        setSelectedIndex(-1);
        break;
    }
  };

  const getTypeIcon = (type: RecentSearch['type'] | 'suggestion') => {
    switch (type) {
      case 'block':
        return <Box size={14} className="text-synor-400" />;
      case 'transaction':
        return <FileText size={14} className="text-amber-400" />;
      case 'address':
        return <Wallet size={14} className="text-green-400" />;
      default:
        return <Search size={14} className="text-gray-400" />;
    }
  };

  const showDropdown = isOpen && (filteredSearches.length > 0 || suggestions.length > 0 || query.trim());

  return (
    <div className={cn('relative', className)}>
      <form onSubmit={handleSubmit}>
        <div className="relative">
          <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-500" />
          <input
            ref={inputRef}
            type="text"
            value={query}
            onChange={(e) => setQuery(e.target.value)}
            onFocus={() => setIsOpen(true)}
            onKeyDown={handleKeyDown}
            placeholder={placeholder}
            className="w-full pl-10 pr-4 py-2 bg-gray-900 border border-gray-700 rounded-lg text-sm text-gray-100 placeholder-gray-500 focus:outline-none focus:border-synor-500 focus:ring-1 focus:ring-synor-500 transition-colors"
            autoComplete="off"
            spellCheck={false}
            role="combobox"
            aria-label="Search the blockchain"
            aria-expanded={!!showDropdown}
            aria-controls="search-listbox"
            aria-activedescendant={selectedIndex >= 0 ? `search-option-${selectedIndex}` : undefined}
            aria-autocomplete="list"
          />
          {query && (
            <button
              type="button"
              onClick={() => {
                setQuery('');
                inputRef.current?.focus();
              }}
              className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-500 hover:text-gray-300 transition-colors"
              aria-label="Clear search input"
            >
              <X size={14} />
            </button>
          )}
        </div>
      </form>

      {/* Dropdown */}
      {showDropdown && (
        <div
          ref={dropdownRef}
          id="search-listbox"
          role="listbox"
          aria-label="Search suggestions"
          className="absolute top-full left-0 right-0 mt-2 bg-gray-900 border border-gray-700 rounded-lg shadow-xl overflow-hidden z-50"
        >
          {/* Suggestions based on query format */}
          {suggestions.length > 0 && (
            <div className="border-b border-gray-800">
              <div className="px-3 py-2 text-xs text-gray-500 uppercase tracking-wider">
                Suggestions
              </div>
              {suggestions.map((suggestion, index) => (
                <button
                  key={suggestion.value}
                  id={`search-option-${index}`}
                  role="option"
                  aria-selected={selectedIndex === index}
                  onClick={() => executeSearch(suggestion.value)}
                  className={cn(
                    'w-full flex items-center gap-3 px-3 py-2 text-left transition-colors',
                    selectedIndex === index
                      ? 'bg-synor-500/20 text-white'
                      : 'hover:bg-gray-800 text-gray-300'
                  )}
                >
                  {getTypeIcon(suggestion.type)}
                  <span className="flex-1 font-mono text-sm truncate">
                    {truncateHash(suggestion.value, 12)}
                  </span>
                  <span className="text-xs text-gray-500 capitalize">
                    {suggestion.type}
                  </span>
                  <ArrowRight size={12} className="text-gray-600" />
                </button>
              ))}
            </div>
          )}

          {/* Recent searches */}
          {filteredSearches.length > 0 && (
            <div>
              <div className="px-3 py-2 flex items-center justify-between">
                <span className="text-xs text-gray-500 uppercase tracking-wider flex items-center gap-1">
                  <Clock size={12} />
                  Recent Searches
                </span>
                <button
                  onClick={(e) => {
                    e.stopPropagation();
                    clearSearches();
                  }}
                  className="text-xs text-gray-500 hover:text-red-400 transition-colors flex items-center gap-1"
                  aria-label="Clear all recent searches"
                >
                  <Trash2 size={10} />
                  Clear
                </button>
              </div>
              {filteredSearches.slice(0, 5).map((search, index) => {
                const itemIndex = suggestions.length + index;
                return (
                  <div
                    key={search.query}
                    id={`search-option-${itemIndex}`}
                    role="option"
                    aria-selected={selectedIndex === itemIndex}
                    className={cn(
                      'flex items-center gap-3 px-3 py-2 transition-colors group',
                      selectedIndex === itemIndex
                        ? 'bg-synor-500/20'
                        : 'hover:bg-gray-800'
                    )}
                  >
                    <button
                      onClick={() => executeSearch(search.query)}
                      className="flex-1 flex items-center gap-3 text-left"
                    >
                      {getTypeIcon(search.type)}
                      <span className="font-mono text-sm text-gray-300 truncate">
                        {search.query.length > 20
                          ? truncateHash(search.query, 10)
                          : search.query}
                      </span>
                      <span className="text-xs text-gray-500 capitalize">
                        {search.type}
                      </span>
                    </button>
                    <button
                      onClick={(e) => {
                        e.stopPropagation();
                        removeSearch(search.query);
                      }}
                      className="p-1 text-gray-600 hover:text-red-400 opacity-0 group-hover:opacity-100 transition-all"
                      aria-label={`Remove "${search.query}" from recent searches`}
                    >
                      <X size={12} />
                    </button>
                  </div>
                );
              })}
            </div>
          )}

          {/* No results hint */}
          {query.trim() && suggestions.length === 0 && filteredSearches.length === 0 && (
            <div className="px-3 py-4 text-center text-sm text-gray-500">
              Press <kbd className="px-1.5 py-0.5 bg-gray-800 rounded text-xs">Enter</kbd> to search for "{query}"
            </div>
          )}
        </div>
      )}
    </div>
  );
}

// Generate suggestions based on query format
interface Suggestion {
  value: string;
  type: 'block' | 'transaction' | 'address';
  label: string;
}

function generateSuggestions(query: string): Suggestion[] {
  const trimmed = query.trim();
  if (!trimmed) return [];

  const suggestions: Suggestion[] = [];

  // Address suggestion
  if (trimmed.startsWith('synor1')) {
    suggestions.push({
      value: trimmed,
      type: 'address',
      label: 'Look up address',
    });
  }

  // Hash-like query (could be block or tx)
  if (/^[0-9a-fA-F]{10,64}$/.test(trimmed)) {
    suggestions.push({
      value: trimmed,
      type: 'block',
      label: 'Search as block hash',
    });
    if (trimmed.length >= 32) {
      suggestions.push({
        value: trimmed,
        type: 'transaction',
        label: 'Search as transaction',
      });
    }
  }

  // Numeric query (block height)
  if (/^\d+$/.test(trimmed)) {
    suggestions.push({
      value: trimmed,
      type: 'block',
      label: `Go to block ${trimmed}`,
    });
  }

  return suggestions;
}
