import React, { useEffect, useRef, useState } from 'react';
import { clsx } from 'clsx';
import { Check, ChevronsUpDown } from 'lucide-react';
import Input from './Input';
import Button from './Button';

export interface ComboboxOption {
  value: string;
  label: string;
  disabled?: boolean;
}

export interface ComboboxProps {
  options: ComboboxOption[];
  value?: string;
  onChange?: (value: string) => void;
  onSearch?: (searchTerm: string) => void;
  placeholder?: string;
  className?: string;
  disabled?: boolean;
  allowClear?: boolean;
  filterOptions?: (options: ComboboxOption[], searchTerm: string) => ComboboxOption[];
}

/**
 * Combobox/Autocomplete component
 */
export const Combobox = ({
  options,
  value,
  onChange,
  onSearch,
  placeholder = 'Select...',
  className,
  disabled,
  allowClear = false,
  filterOptions,
}: ComboboxProps) => {
  const [isOpen, setIsOpen] = useState(false);
  const [searchTerm, setSearchTerm] = useState('');
  const comboboxRef = useRef<HTMLDivElement>(null);
  const inputRef = useRef<HTMLInputElement>(null);

  const defaultFilter = (opts: ComboboxOption[], term: string) => {
    if (!term) return opts;
    const lowerTerm = term.toLowerCase();
    return opts.filter(
      (opt) =>
        opt.label.toLowerCase().includes(lowerTerm) || opt.value.toLowerCase().includes(lowerTerm)
    );
  };

  const filter = filterOptions || defaultFilter;
  const filteredOptions = filter(options, searchTerm);

  const selectedOption = options.find((opt) => opt.value === value);

  useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      if (comboboxRef.current && !comboboxRef.current.contains(event.target as Node)) {
        setIsOpen(false);
        setSearchTerm('');
      }
    };

    const handleEscape = (event: KeyboardEvent) => {
      if (event.key === 'Escape' && isOpen) {
        setIsOpen(false);
        setSearchTerm('');
      }
    };

    if (isOpen) {
      document.addEventListener('mousedown', handleClickOutside);
      document.addEventListener('keydown', handleEscape);
      inputRef.current?.focus();
    }

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

  const handleSelect = (optionValue: string) => {
    onChange?.(optionValue);
    setIsOpen(false);
    setSearchTerm('');
  };

  const handleSearchChange = (term: string) => {
    setSearchTerm(term);
    onSearch?.(term);
  };

  const handleClear = (e: React.MouseEvent) => {
    e.stopPropagation();
    onChange?.('');
    setSearchTerm('');
  };

  return (
    <div ref={comboboxRef} className={clsx('relative', className)}>
      <div className="relative">
        <Input
          ref={inputRef}
          type="text"
          value={isOpen ? searchTerm : selectedOption?.label || ''}
          onChange={(e) => {
            if (!isOpen) setIsOpen(true);
            handleSearchChange(e.target.value);
          }}
          onFocus={() => setIsOpen(true)}
          placeholder={placeholder}
          disabled={disabled}
          className="pr-20"
        />
        <div className="absolute right-2 top-1/2 -translate-y-1/2 flex items-center gap-1">
          {allowClear && value && (
            <Button
              type="button"
              variant="ghost"
              size="sm"
              onClick={handleClear}
              className="h-6 w-6 p-0"
              aria-label="Clear"
            >
              ×
            </Button>
          )}
          <ChevronsUpDown className="h-4 w-4 text-muted-foreground pointer-events-none" />
        </div>
      </div>

      {isOpen && (
        <div
          className={clsx(
            'absolute z-50 w-full mt-1',
            'bg-background border rounded-lg shadow-lg',
            'max-h-60 overflow-auto',
            'animate-in fade-in-0 zoom-in-95 duration-200'
          )}
        >
          {filteredOptions.length === 0 ? (
            <div className="p-4 text-sm text-muted-foreground text-center">No options found</div>
          ) : (
            <ul className="p-1" role="listbox">
              {filteredOptions.map((option) => (
                <li key={option.value}>
                  <button
                    type="button"
                    onClick={() => !option.disabled && handleSelect(option.value)}
                    disabled={option.disabled}
                    className={clsx(
                      'w-full flex items-center gap-2 px-3 py-2 text-sm text-left',
                      'rounded-md hover:bg-muted focus:bg-muted',
                      'focus:outline-none transition-colors',
                      {
                        'opacity-50 cursor-not-allowed': option.disabled,
                        'bg-primary/10': value === option.value,
                      }
                    )}
                    role="option"
                    aria-selected={value === option.value}
                  >
                    {value === option.value && (
                      <Check className="h-4 w-4 text-primary flex-shrink-0" />
                    )}
                    <span className={clsx({ 'font-medium': value === option.value })}>
                      {option.label}
                    </span>
                  </button>
                </li>
              ))}
            </ul>
          )}
        </div>
      )}
    </div>
  );
};
