"use client";

import { useState, useEffect, useCallback, useRef, KeyboardEvent } from "react";
import { Search, X } from "lucide-react";
import { cn } from "@/lib/utils";
import { Input } from "@/components/ui/input";

interface SearchInputProps {
  value: string;
  onChange: (value: string) => void;
  onSubmit?: (value: string) => void;
  placeholder?: string;
  debounceMs?: number;
  className?: string;
  showClearButton?: boolean;
  autoFocus?: boolean;
}

export function SearchInput({
  value,
  onChange,
  onSubmit,
  placeholder = "Search...",
  debounceMs = 300,
  className = "",
  showClearButton = true,
  autoFocus = false,
}: SearchInputProps) {
  const [isFocused, setIsFocused] = useState(false);
  const timeoutRef = useRef<NodeJS.Timeout>();
  const inputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    if (autoFocus && inputRef.current) {
      inputRef.current.focus();
    }
  }, [autoFocus]);

  // Debounce callback for API calls (not used for local filtering)
  useEffect(() => {
    timeoutRef.current = setTimeout(() => {
      // Debounced value available for API calls if needed
    }, debounceMs);

    return () => {
      if (timeoutRef.current) clearTimeout(timeoutRef.current);
    };
  }, [value, debounceMs]);

  const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
    onChange(e.target.value);
  }, [onChange]);

  const handleKeyDown = useCallback((e: KeyboardEvent<HTMLInputElement>) => {
    if (e.key === "Enter" && onSubmit) {
      e.preventDefault();
      onSubmit(value);
    }
    if (e.key === "Escape") {
      e.currentTarget.blur();
    }
  }, [onSubmit, value]);

  const clear = useCallback(() => {
    onChange("");
    inputRef.current?.focus();
  }, [onChange]);

  return (
    <div className={cn("relative", className)}>
      <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" aria-hidden="true" />
      <Input
        ref={inputRef}
        type="text"
        value={value}
        onChange={handleChange}
        onKeyDown={handleKeyDown}
        onFocus={() => setIsFocused(true)}
        onBlur={() => setIsFocused(false)}
        placeholder={placeholder}
        className={cn("pl-9 pr-10", isFocused && "ring-2 ring-indigo-500/20")}
        aria-label={placeholder}
      />
      {showClearButton && value && (
        <button
          onClick={clear}
          className="absolute right-2.5 top-1/2 h-5 w-5 -translate-y-1/2 rounded-md text-muted-foreground hover:text-foreground hover:bg-muted transition-colors"
          aria-label="Clear search"
        >
          <X className="h-4 w-4" />
        </button>
      )}
    </div>
  );
}

interface SelectableSearchProps<T> extends SearchInputProps {
  items: T[];
  getItemLabel: (item: T) => string;
  getItemValue: (item: T) => string;
  onSelect: (item: T) => void;
  renderItem?: (item: T, highlighted: boolean) => React.ReactNode;
  maxResults?: number;
}

export function SelectableSearch<T>({
  items,
  getItemLabel,
  getItemValue,
  onSelect,
  renderItem,
  maxResults = 10,
  value,
  onChange,
  placeholder = "Search...",
  debounceMs = 300,
  className = "",
  autoFocus = false,
}: SelectableSearchProps<T>) {
  const [isOpen, setIsOpen] = useState(false);
  const [highlightedIndex, setHighlightedIndex] = useState(-1);
  const dropdownRef = useRef<HTMLDivElement>(null);
  const inputRef = useRef<HTMLInputElement>(null);

  const filteredItems = useMemo(
    () => items
      .filter((item) =>
        getItemLabel(item).toLowerCase().includes(value.toLowerCase()) ||
        getItemValue(item).toLowerCase().includes(value.toLowerCase())
      )
      .slice(0, maxResults),
    [items, value, getItemLabel, getItemValue, maxResults]
  );

  useEffect(() => {
    if (autoFocus && inputRef.current) {
      inputRef.current.focus();
    }
  }, [autoFocus]);

  useEffect(() => {
    if (isOpen && highlightedIndex >= 0) {
      const element = dropdownRef.current?.querySelector(`[data-index="${highlightedIndex}"]`);
      element?.scrollIntoView({ block: "nearest" });
    }
  }, [highlightedIndex, isOpen]);

  const handleKeyDown = useCallback((e: KeyboardEvent<HTMLInputElement>) => {
    if (!isOpen) {
      if (e.key === "ArrowDown" || e.key === "Enter") {
        e.preventDefault();
        setIsOpen(true);
        setHighlightedIndex(0);
      }
      return;
    }

    switch (e.key) {
      case "ArrowDown":
        e.preventDefault();
        setHighlightedIndex((prev) => Math.min(prev + 1, filteredItems.length - 1));
        break;
      case "ArrowUp":
        e.preventDefault();
        setHighlightedIndex((prev) => Math.max(prev - 1, 0));
        break;
      case "Enter":
        e.preventDefault();
        if (highlightedIndex >= 0 && filteredItems[highlightedIndex]) {
          onSelect(filteredItems[highlightedIndex]);
          setIsOpen(false);
          setHighlightedIndex(-1);
        }
        break;
      case "Escape":
        setIsOpen(false);
        setHighlightedIndex(-1);
        inputRef.current?.blur();
        break;
    }
  }, [isOpen, filteredItems, highlightedIndex, onSelect]);

  const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
    onChange(e.target.value);
    if (e.target.value) {
      setIsOpen(true);
      setHighlightedIndex(0);
    } else {
      setIsOpen(false);
      setHighlightedIndex(-1);
    }
  }, [onChange]);

  const handleBlur = useCallback(() => {
    setTimeout(() => {
      setIsOpen(false);
      setHighlightedIndex(-1);
    }, 200);
  }, []);

  return (
    <div className={cn("relative", className)}>
      <SearchInput
        ref={inputRef}
        value={value}
        onChange={handleChange}
        onKeyDown={handleKeyDown}
        onBlur={handleBlur}
        placeholder={placeholder}
        debounceMs={debounceMs}
        showClearButton={true}
        autoFocus={autoFocus}
      />

      {isOpen && filteredItems.length > 0 && (
        <div
          ref={dropdownRef}
          className="absolute z-50 mt-1 w-full max-h-60 overflow-y-auto rounded-md border border-border bg-card shadow-lg"
          role="listbox"
        >
          {filteredItems.map((item, index) => {
            const highlighted = index === highlightedIndex;
            return (
              <div
                key={getItemValue(item)}
                data-index={index}
                role="option"
                aria-selected={highlighted}
                className={cn(
                  "px-3 py-2 cursor-pointer select-none transition-colors",
                  highlighted ? "bg-indigo-50 text-indigo-900" : "hover:bg-muted"
                )}
                onMouseEnter={() => setHighlightedIndex(index)}
                onClick={() => {
                  onSelect(item);
                  setIsOpen(false);
                  setHighlightedIndex(-1);
                  inputRef.current?.focus();
                }}
              >
                {renderItem
                  ? renderItem(item, highlighted)
                  : (
                      <div className="flex items-center gap-2">
                        <span className="font-medium">{getItemLabel(item)}</span>
                        <span className="text-xs text-muted-foreground">{getItemValue(item)}</span>
                      </div>
                    )}
              </div>
            );
          })}
        </div>
      )}

      {isOpen && filteredItems.length === 0 && value && (
        <div className="absolute z-50 mt-1 w-full rounded-md border border-border bg-card p-3 text-sm text-muted-foreground text-center shadow-lg">
          No results found
        </div>
      )}
    </div>
  );
}