/**
 * Searchable Select Component
 * Combo box with search/filter functionality for large option lists
 */
import React, { useState, useRef, useEffect } from 'react';
import { createPortal } from 'react-dom';
import { ChevronDown, Search, X } from 'lucide-react';

interface SearchableSelectProps {
  value: string;
  onChange: (value: string) => void;
  options: string[];
  placeholder?: string;
  required?: boolean;
  className?: string;
  zIndex?: number; // Custom z-index for the dropdown
}

export const SearchableSelect: React.FC<SearchableSelectProps> = ({
  value,
  onChange,
  options,
  placeholder = 'Select...',
  required = false,
  className = '',
  zIndex = 110, // Default z-index for dropdown
}) => {
  const [isOpen, setIsOpen] = useState(false);
  const [searchTerm, setSearchTerm] = useState('');
  const [highlightedIndex, setHighlightedIndex] = useState(0);
  const [dropdownPosition, setDropdownPosition] = useState({ top: 0, left: 0, width: 0 });
  const containerRef = useRef<HTMLDivElement>(null);
  const inputRef = useRef<HTMLInputElement>(null);
  const listRef = useRef<HTMLUListElement>(null);
  const dropdownRef = useRef<HTMLDivElement>(null);

  // Filter options based on search term
  const filteredOptions = options.filter((option) =>
    option.toLowerCase().includes(searchTerm.toLowerCase())
  );

  // Close dropdown on scroll (prevents it from covering modal header)
  useEffect(() => {
    if (isOpen && containerRef.current) {
      const updatePosition = () => {
        const rect = containerRef.current!.getBoundingClientRect();
        
        // Always position below the trigger
        setDropdownPosition({
          top: rect.bottom + 4,
          left: rect.left,
          width: rect.width,
        });
      };
      
      updatePosition();
      
      // Close dropdown on scroll (prevents it from covering modal header)
      const handleScroll = (e: Event) => {
        // Only close if scroll is not from the dropdown itself
        if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) {
          setIsOpen(false);
        }
      };
      
      // Update position on resize, close on scroll
      window.addEventListener('scroll', handleScroll, true);
      window.addEventListener('resize', updatePosition);
      
      return () => {
        window.removeEventListener('scroll', handleScroll, true);
        window.removeEventListener('resize', updatePosition);
      };
    }
  }, [isOpen]);

  // Close dropdown when clicking outside
  useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      if (
        containerRef.current && 
        !containerRef.current.contains(event.target as Node) &&
        dropdownRef.current &&
        !dropdownRef.current.contains(event.target as Node)
      ) {
        setIsOpen(false);
        setSearchTerm('');
      }
    };

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

  // Handle keyboard navigation
  const handleKeyDown = (e: React.KeyboardEvent) => {
    if (!isOpen) {
      if (e.key === 'Enter' || e.key === 'ArrowDown' || e.key === 'ArrowUp') {
        setIsOpen(true);
        e.preventDefault();
      }
      return;
    }

    switch (e.key) {
      case 'ArrowDown':
        e.preventDefault();
        setHighlightedIndex((prev) => 
          prev < filteredOptions.length - 1 ? prev + 1 : prev
        );
        break;
      case 'ArrowUp':
        e.preventDefault();
        setHighlightedIndex((prev) => (prev > 0 ? prev - 1 : 0));
        break;
      case 'Enter':
        e.preventDefault();
        if (filteredOptions[highlightedIndex]) {
          handleSelect(filteredOptions[highlightedIndex]);
        }
        break;
      case 'Escape':
        setIsOpen(false);
        setSearchTerm('');
        break;
    }
  };

  // Scroll highlighted item into view
  useEffect(() => {
    if (isOpen && listRef.current) {
      const highlightedElement = listRef.current.children[highlightedIndex] as HTMLElement;
      if (highlightedElement) {
        highlightedElement.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
      }
    }
  }, [highlightedIndex, isOpen]);

  // Reset highlighted index when filtered options change
  useEffect(() => {
    setHighlightedIndex(0);
  }, [searchTerm]);

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

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

  const handleToggle = () => {
    setIsOpen(!isOpen);
    if (!isOpen) {
      // Focus input when opening
      setTimeout(() => inputRef.current?.focus(), 0);
    }
  };

  // Get display text
  const displayText = value || '';

  // Render dropdown in portal (to avoid being clipped by Modal overflow)
  const renderDropdown = () => {
    if (!isOpen) return null;

    return createPortal(
      <div 
        ref={dropdownRef}
        className="fixed bg-white border border-slate-200 rounded-md shadow-2xl flex flex-col"
        style={{
          top: `${dropdownPosition.top}px`,
          left: `${dropdownPosition.left}px`,
          width: `${dropdownPosition.width}px`,
          maxHeight: 'min(32rem, 80vh)',
          zIndex: zIndex,
        }}
        role="dialog"
      >
        {/* Search Input */}
        <div className="p-2 border-b border-slate-200 bg-white flex-shrink-0">
          <div className="relative">
            <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-slate-400" />
            <input
              ref={inputRef}
              type="text"
              value={searchTerm}
              onChange={(e) => setSearchTerm(e.target.value)}
              onKeyDown={handleKeyDown}
              placeholder="Type to search..."
              className="w-full pl-9 pr-3 py-2 bg-slate-50 border border-slate-300 text-slate-900 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
              autoFocus
            />
          </div>
        </div>

        {/* Options List */}
        <ul
          ref={listRef}
          className="overflow-y-auto overflow-x-hidden overscroll-contain scroll-smooth flex-1"
          style={{ 
            maxHeight: '400px',
            minHeight: '280px', // Display at least 5-6 options
            WebkitOverflowScrolling: 'touch', // Enable momentum scrolling on iOS
          }}
          role="listbox"
        >
          {filteredOptions.length === 0 ? (
            <li className="px-3 py-2 text-slate-500 text-sm text-center">
              No results found
            </li>
          ) : (
            filteredOptions.map((option, index) => (
              <li
                key={option}
                onClick={() => handleSelect(option)}
                className={`px-4 py-3 text-sm cursor-pointer transition border-b border-slate-100 last:border-0 ${
                  index === highlightedIndex
                    ? 'bg-blue-600 text-white'
                    : value === option
                    ? 'bg-blue-50 text-blue-700'
                    : 'text-slate-700 hover:bg-slate-50'
                }`}
                role="option"
                aria-selected={value === option}
              >
                <div className="truncate" title={option}>
                  {option}
                </div>
              </li>
            ))
          )}
        </ul>

        {/* Result Count - Always show for large lists */}
        {(searchTerm || options.length > 20) && (
          <div className="px-3 py-2 bg-slate-50 border-t border-slate-200 text-xs text-slate-500 flex items-center justify-between flex-shrink-0">
            <span>
              {searchTerm 
                ? `${filteredOptions.length} of ${options.length} options`
                : `${options.length} total options`
              }
            </span>
            {!searchTerm && options.length > 20 && (
              <span className="text-blue-600">Type to search</span>
            )}
          </div>
        )}
      </div>,
      document.body
    );
  };

  return (
    <div ref={containerRef} className={`relative ${className}`}>
      {/* Trigger Button/Input */}
      <div
        onClick={handleToggle}
        className="w-full px-3 py-2 bg-white border border-slate-300 text-slate-900 rounded-md cursor-pointer hover:border-slate-400 transition flex items-center justify-between"
      >
        <span className={value ? 'text-slate-900' : 'text-slate-400'}>
          {displayText || placeholder}
        </span>
        <div className="flex items-center gap-1">
          {value && (
            <button
              onClick={handleClear}
              className="p-0.5 hover:bg-slate-100 rounded transition"
              type="button"
            >
              <X className="w-4 h-4 text-slate-400" />
            </button>
          )}
          <ChevronDown
            className={`w-4 h-4 text-slate-400 transition-transform ${
              isOpen ? 'transform rotate-180' : ''
            }`}
          />
        </div>
      </div>

      {/* Required indicator (hidden input for form validation) */}
      {required && (
        <input
          type="text"
          value={value}
          onChange={() => {}}
          required
          className="absolute opacity-0 pointer-events-none"
          tabIndex={-1}
        />
      )}

      {/* Dropdown (rendered via portal to avoid Modal overflow clipping) */}
      {renderDropdown()}
    </div>
  );
};
