import { useVirtualizer } from '@tanstack/react-virtual';
import { useRef, useState, useMemo, useCallback } from 'react';

/**
 * Option shape for checkbox list items
 */
export interface CheckboxOption {
  label: string;
  value: string;
}

/**
 * Props for VirtualizedCheckboxList component
 */
export interface VirtualizedCheckboxListProps {
  /** Array of checkbox options to render */
  options: CheckboxOption[];
  /** Currently selected values */
  selectedValues: string[];
  /** Callback when selection changes */
  onSelectionChange: (selectedValues: string[]) => void;
  /** Height of each item in pixels (default: 40) */
  itemHeight?: number;
  /** Total height of the scrollable container in pixels (default: 400) */
  containerHeight?: number;
  /** Placeholder text for search input (default: "Search...") */
  searchPlaceholder?: string;
  /** Label for "Select All" button (default: "Select All") */
  selectAllLabel?: string;
  /** Label for "Clear All" button (default: "Clear All") */
  clearAllLabel?: string;
  /** Class name for the container element */
  className?: string;
  /** Whether to show the selected count (default: true) */
  showSelectedCount?: boolean;
}

/**
 * VirtualizedCheckboxList - Windowed checkbox list for large datasets (200+ items)
 *
 * Features:
 * - Virtualized rendering using @tanstack/react-virtual for optimal performance
 * - Built-in search/filter functionality
 * - Select All / Clear All actions
 * - Selected count display
 * - Accessible keyboard navigation
 * - Tailwind CSS styling support
 *
 * @example
 * ```tsx
 * const [selectedValues, setSelectedValues] = useState<string[]>([]);
 *
 * <VirtualizedCheckboxList
 *   options={enumOptions}
 *   selectedValues={selectedValues}
 *   onSelectionChange={setSelectedValues}
 *   containerHeight={500}
 * />
 * ```
 */
export function VirtualizedCheckboxList({
  options,
  selectedValues,
  onSelectionChange,
  itemHeight = 40,
  containerHeight = 400,
  searchPlaceholder = 'Search...',
  selectAllLabel = 'Select All',
  clearAllLabel = 'Clear All',
  className = '',
  showSelectedCount = true,
}: VirtualizedCheckboxListProps) {
  const [searchTerm, setSearchTerm] = useState('');
  const parentRef = useRef<HTMLDivElement>(null);

  // Filter options based on search term
  const filteredOptions = useMemo(() => {
    if (!searchTerm.trim()) {
      return options;
    }

    const lowerSearch = searchTerm.toLowerCase();
    return options.filter((option) =>
      option.label.toLowerCase().includes(lowerSearch)
    );
  }, [options, searchTerm]);

  // Set up virtualizer for windowed rendering
  const virtualizer = useVirtualizer({
    count: filteredOptions.length,
    getScrollElement: () => parentRef.current,
    estimateSize: () => itemHeight,
    overscan: 5, // Render 5 extra items above/below viewport
  });

  // Toggle individual checkbox
  const handleToggle = useCallback(
    (value: string) => {
      const isSelected = selectedValues.includes(value);
      if (isSelected) {
        onSelectionChange(selectedValues.filter((v) => v !== value));
      } else {
        onSelectionChange([...selectedValues, value]);
      }
    },
    [selectedValues, onSelectionChange]
  );

  // Select all filtered options
  const handleSelectAll = useCallback(() => {
    const allFilteredValues = filteredOptions.map((opt) => opt.value);
    const uniqueValues = Array.from(
      new Set([...selectedValues, ...allFilteredValues])
    );
    onSelectionChange(uniqueValues);
  }, [filteredOptions, selectedValues, onSelectionChange]);

  // Clear all selections
  const handleClearAll = useCallback(() => {
    onSelectionChange([]);
  }, [onSelectionChange]);

  // Clear search
  const handleClearSearch = useCallback(() => {
    setSearchTerm('');
  }, []);

  const selectedCount = selectedValues.length;
  const totalCount = options.length;
  const isAllSelected = filteredOptions.length > 0 && filteredOptions.every((opt) =>
    selectedValues.includes(opt.value)
  );

  return (
    <div className={`flex flex-col gap-3 ${className}`}>
      {/* Header: Search + Actions */}
      <div className="flex flex-col gap-2">
        {/* Search input */}
        <div className="relative">
          <input
            type="text"
            value={searchTerm}
            onChange={(e) => setSearchTerm(e.target.value)}
            placeholder={searchPlaceholder}
            className="w-full px-3 py-2 pr-8 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
            aria-label="Filter options"
          />
          {searchTerm && (
            <button
              onClick={handleClearSearch}
              className="absolute right-2 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600"
              aria-label="Clear search"
              type="button"
            >
              ✕
            </button>
          )}
        </div>

        {/* Action buttons and count */}
        <div className="flex items-center justify-between gap-2">
          <div className="flex gap-2">
            <button
              onClick={handleSelectAll}
              disabled={isAllSelected}
              className="px-3 py-1 text-sm font-medium text-blue-600 hover:text-blue-700 hover:bg-blue-50 rounded disabled:opacity-50 disabled:cursor-not-allowed"
              type="button"
            >
              {selectAllLabel}
            </button>
            <button
              onClick={handleClearAll}
              disabled={selectedCount === 0}
              className="px-3 py-1 text-sm font-medium text-gray-600 hover:text-gray-700 hover:bg-gray-50 rounded disabled:opacity-50 disabled:cursor-not-allowed"
              type="button"
            >
              {clearAllLabel}
            </button>
          </div>

          {showSelectedCount && (
            <span className="text-sm text-gray-600" aria-live="polite">
              {selectedCount} / {totalCount} selected
            </span>
          )}
        </div>
      </div>

      {/* Virtualized checkbox list */}
      <div
        ref={parentRef}
        className="border border-gray-200 rounded-md overflow-auto"
        style={{ height: `${containerHeight}px` }}
        role="group"
        aria-label="Checkbox options"
      >
        {filteredOptions.length === 0 ? (
          <div className="flex items-center justify-center h-full text-gray-500">
            No options found
          </div>
        ) : (
          <div
            style={{
              height: `${virtualizer.getTotalSize()}px`,
              width: '100%',
              position: 'relative',
            }}
          >
            {virtualizer.getVirtualItems().map((virtualItem) => {
              const option = filteredOptions[virtualItem.index];
              const isChecked = selectedValues.includes(option.value);

              return (
                <label
                  key={option.value}
                  className="flex items-center gap-3 px-4 py-2 hover:bg-gray-50 cursor-pointer"
                  style={{
                    position: 'absolute',
                    top: 0,
                    left: 0,
                    width: '100%',
                    height: `${virtualItem.size}px`,
                    transform: `translateY(${virtualItem.start}px)`,
                  }}
                >
                  <input
                    type="checkbox"
                    checked={isChecked}
                    onChange={() => handleToggle(option.value)}
                    className="w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-2 focus:ring-blue-500"
                    aria-label={option.label}
                  />
                  <span className="text-sm text-gray-900 select-none">
                    {option.label}
                  </span>
                </label>
              );
            })}
          </div>
        )}
      </div>
    </div>
  );
}
