import { useState, useEffect, useRef, useCallback, useMemo } from 'react';
import { useDebounce } from '@/hooks/useDebounce';
import { useLocalStorage } from '@/hooks/useLocalStorage';
import { cn } from '@/lib/utils';
import {
  Search as SearchIcon,
  X,
  Clock,
  Music,
  User,
  List,
} from 'lucide-react';
import { Button } from '@/components/ui/button';
import { logger } from '@/utils/logger';

export interface SearchResult {
  id: string;
  type: 'track' | 'user' | 'playlist';
  title: string;
  subtitle?: string;
  image?: string;
}

export interface SearchProps {
  onSearch: (query: string) => void;
  onResultSelect?: (result: SearchResult) => void;
  placeholder?: string;
  showSuggestions?: boolean;
  showHistory?: boolean;
  maxHistoryItems?: number;
  fetchSuggestions?: (
    query: string,
  ) => Promise<SearchResult[]> | SearchResult[];
  className?: string;
  debounceDelay?: number;
}

const HISTORY_KEY = 'veza_search_history';
const MAX_HISTORY_ITEMS = 10;

/**
 * Composant Search avec autocomplete, suggestions, et historique.
 */
export function Search({
  onSearch,
  onResultSelect,
  placeholder = 'Rechercher...',
  showSuggestions = true,
  showHistory = true,
  maxHistoryItems = MAX_HISTORY_ITEMS,
  fetchSuggestions,
  className,
  debounceDelay = 300,
}: SearchProps) {
  const [query, setQuery] = useState('');
  const [suggestions, setSuggestions] = useState<SearchResult[]>([]);
  const [isLoading, setIsLoading] = useState(false);
  const [showDropdown, setShowDropdown] = useState(false);
  const [activeIndex, setActiveIndex] = useState(-1);
  const [history, setHistory, removeHistory] = useLocalStorage<string[]>(
    HISTORY_KEY,
    [],
  );
  const searchRef = useRef<HTMLDivElement>(null);
  const inputRef = useRef<HTMLInputElement>(null);

  // Debounce de la query pour la recherche
  const debouncedQuery = useDebounce(query, debounceDelay);

  // Fetch suggestions lorsque la query change
  useEffect(() => {
    if (!debouncedQuery.trim() || !fetchSuggestions || !showSuggestions) {
      setSuggestions([]);
      setIsLoading(false);
      return;
    }

    setIsLoading(true);
    const loadSuggestions = async () => {
      try {
        const results = await Promise.resolve(fetchSuggestions(debouncedQuery));
        setSuggestions(results);
      } catch (error) {
        logger.error('Error fetching suggestions', {
          error: error instanceof Error ? error.message : String(error),
          stack: error instanceof Error ? error.stack : undefined,
          query: debouncedQuery,
        });
        setSuggestions([]);
      } finally {
        setIsLoading(false);
      }
    };

    loadSuggestions();
  }, [debouncedQuery, fetchSuggestions, showSuggestions]);

  // Appeler onSearch quand la query débounced change
  useEffect(() => {
    if (debouncedQuery.trim()) {
      onSearch(debouncedQuery);
    }
  }, [debouncedQuery, onSearch]);

  // Gérer le clic en dehors pour fermer le dropdown
  useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      if (
        searchRef.current &&
        !searchRef.current.contains(event.target as Node)
      ) {
        setShowDropdown(false);
        setActiveIndex(-1);
      }
    };

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

  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const value = e.target.value;
    setQuery(value);
    setShowDropdown(true);
    setActiveIndex(-1);
  };

  const handleInputFocus = () => {
    if (query.trim() || (showHistory && history.length > 0)) {
      setShowDropdown(true);
    }
  };

  const handleInputKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    const items = [
      ...(showHistory && query.trim() === '' ? history.slice(0, 5) : []),
      ...suggestions,
    ];

    switch (e.key) {
      case 'ArrowDown':
        e.preventDefault();
        setActiveIndex((prev) => (prev < items.length - 1 ? prev + 1 : prev));
        break;
      case 'ArrowUp':
        e.preventDefault();
        setActiveIndex((prev) => (prev > 0 ? prev - 1 : -1));
        break;
      case 'Enter':
        e.preventDefault();
        if (activeIndex >= 0 && activeIndex < items.length) {
          if (
            activeIndex <
            (showHistory && query.trim() === '' ? history.length : 0)
          ) {
            // C'est un item de l'historique
            const historyItem = history[activeIndex];
            setQuery(historyItem);
            handleSearch(historyItem);
          } else {
            // C'est une suggestion
            const suggestionIndex =
              activeIndex -
              (showHistory && query.trim() === ''
                ? Math.min(history.length, 5)
                : 0);
            const result = suggestions[suggestionIndex];
            handleResultSelect(result);
          }
        } else if (query.trim()) {
          handleSearch(query);
        }
        break;
      case 'Escape':
        setShowDropdown(false);
        setActiveIndex(-1);
        inputRef.current?.blur();
        break;
    }
  };

  const handleSearch = useCallback(
    (searchQuery: string) => {
      if (searchQuery.trim()) {
        // Ajouter à l'historique
        if (showHistory) {
          setHistory((prev) => {
            const filtered = prev.filter((item) => item !== searchQuery);
            const updated = [searchQuery, ...filtered].slice(
              0,
              maxHistoryItems,
            );
            return updated;
          });
        }
        setShowDropdown(false);
        onSearch(searchQuery);
      }
    },
    [onSearch, showHistory, setHistory, maxHistoryItems],
  );

  const handleResultSelect = useCallback(
    (result: SearchResult) => {
      setQuery(result.title);
      setShowDropdown(false);
      setActiveIndex(-1);
      onResultSelect?.(result);
    },
    [onResultSelect],
  );

  const handleHistoryItemClick = (item: string) => {
    setQuery(item);
    handleSearch(item);
  };

  const handleClearHistory = () => {
    removeHistory();
  };

  const handleClear = () => {
    setQuery('');
    setSuggestions([]);
    setShowDropdown(false);
    inputRef.current?.focus();
  };

  const getResultIcon = (type: SearchResult['type']) => {
    switch (type) {
      case 'track':
        return <Music className="h-4 w-4" />;
      case 'user':
        return <User className="h-4 w-4" />;
      case 'playlist':
        return <List className="h-4 w-4" />;
    }
  };

  const displayItems = useMemo(() => {
    const items: Array<{
      type: 'history' | 'suggestion';
      data: string | SearchResult;
    }> = [];

    if (showHistory && query.trim() === '' && history.length > 0) {
      items.push(
        ...history
          .slice(0, 5)
          .map((item) => ({ type: 'history' as const, data: item })),
      );
    }

    if (showSuggestions && suggestions.length > 0) {
      items.push(
        ...suggestions.map((result) => ({
          type: 'suggestion' as const,
          data: result,
        })),
      );
    }

    return items;
  }, [showHistory, showSuggestions, query, history, suggestions]);

  const shouldShowDropdown =
    showDropdown &&
    (displayItems.length > 0 || isLoading) &&
    (showSuggestions || (showHistory && query.trim() === ''));

  return (
    <div ref={searchRef} className={cn('relative w-full', className)}>
      <div className="relative">
        <SearchIcon className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
        <input
          ref={inputRef}
          type="text"
          value={query}
          onChange={handleInputChange}
          onFocus={handleInputFocus}
          onKeyDown={handleInputKeyDown}
          placeholder={placeholder}
          className={cn(
            'w-full rounded-md border border-input bg-background px-9 py-2 text-sm',
            'placeholder:text-muted-foreground',
            'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
            'disabled:cursor-not-allowed disabled:opacity-50',
          )}
        />
        {query && (
          <button
            type="button"
            onClick={handleClear}
            className="absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground"
            aria-label="Clear search"
          >
            <X className="h-4 w-4" />
          </button>
        )}
      </div>

      {shouldShowDropdown && (
        <div className="absolute z-50 mt-2 w-full rounded-md border bg-popover shadow-lg">
          {isLoading && (
            <div className="p-4 text-center text-sm text-muted-foreground">
              Recherche en cours...
            </div>
          )}

          {!isLoading && displayItems.length === 0 && query.trim() && (
            <div className="p-4 text-center text-sm text-muted-foreground">
              Aucun résultat trouvé
            </div>
          )}

          {!isLoading && displayItems.length > 0 && (
            <div className="max-h-96 overflow-y-auto">
              {showHistory && query.trim() === '' && history.length > 0 && (
                <div className="border-b p-2">
                  <div className="flex items-center justify-between px-2 py-1">
                    <span className="text-xs font-medium text-muted-foreground">
                      RÉCENTS
                    </span>
                    <Button
                      variant="ghost"
                      size="sm"
                      onClick={handleClearHistory}
                      className="h-6 text-xs"
                    >
                      Effacer
                    </Button>
                  </div>
                  {history.slice(0, 5).map((item, index) => (
                    <button
                      key={index}
                      type="button"
                      onClick={() => handleHistoryItemClick(item)}
                      className={cn(
                        'w-full px-3 py-2 text-left text-sm hover:bg-accent',
                        'flex items-center gap-2',
                        activeIndex === index && 'bg-accent',
                      )}
                    >
                      <Clock className="h-4 w-4 text-muted-foreground" />
                      <span className="flex-1">{item}</span>
                    </button>
                  ))}
                </div>
              )}

              {showSuggestions && suggestions.length > 0 && (
                <div className="p-2">
                  {query.trim() && (
                    <div className="px-2 py-1 text-xs font-medium text-muted-foreground">
                      SUGGESTIONS
                    </div>
                  )}
                  {suggestions.map((result, index) => {
                    const itemIndex =
                      (showHistory && query.trim() === ''
                        ? Math.min(history.length, 5)
                        : 0) + index;
                    return (
                      <button
                        key={result.id}
                        type="button"
                        onClick={() => handleResultSelect(result)}
                        className={cn(
                          'w-full px-3 py-2 text-left text-sm hover:bg-accent',
                          'flex items-center gap-3',
                          activeIndex === itemIndex && 'bg-accent',
                        )}
                      >
                        <div className="flex h-8 w-8 items-center justify-center rounded bg-muted">
                          {getResultIcon(result.type)}
                        </div>
                        <div className="flex-1">
                          <div className="font-medium">{result.title}</div>
                          {result.subtitle && (
                            <div className="text-xs text-muted-foreground">
                              {result.subtitle}
                            </div>
                          )}
                        </div>
                      </button>
                    );
                  })}
                </div>
              )}
            </div>
          )}
        </div>
      )}
    </div>
  );
}
