/**
 * ComboboxCell Component
 *
 * Combobox-style dropdown for fields with many options (50+).
 * Uses Command (cmdk) with built-in fuzzy search filtering.
 *
 * PERFORMANCE: Unlike SelectCell which renders ALL options upfront,
 * ComboboxCell only renders filtered results. When a user types,
 * cmdk filters the list and only matching items are rendered.
 * This dramatically improves performance for 100+ option lists.
 */

import { useState, useCallback, useRef, useMemo, memo } from 'react';
import { Check, ChevronsUpDown, Loader2 } from 'lucide-react';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
} from '@/components/ui/command';
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from '@/components/ui/popover';
import type { Field, SelectOption } from '../../../../types';
import type { ValidationError } from '../../store/types';
import { useValidationStore } from '../../store/validationStore';

/** Time window (ms) during which this cell should not open after a popover closes */
const POPOVER_CLOSE_DELAY = 150;

interface ComboboxCellProps {
  value: unknown;
  field: Field<string>;
  options?: SelectOption[];
  rowIndex: number;
  isValidating: boolean;
  errors: ValidationError[];
  onChange: (value: unknown) => void;
  onBlur: (value: unknown) => void;
  onFetchOptions?: () => Promise<SelectOption[]>;
}

const ComboboxCellComponent = ({
  value,
  field,
  options = [],
  isValidating,
  errors,
  onChange: _onChange, // Unused - onBlur handles both update and validation
  onBlur,
  onFetchOptions,
}: ComboboxCellProps) => {
  const [open, setOpen] = useState(false);
  const [isLoadingOptions, setIsLoadingOptions] = useState(false);
  const hasFetchedRef = useRef(false);
  const scrollContainerRef = useRef<HTMLDivElement>(null);

  // Get store state for coordinating with popover close behavior
  const cellPopoverClosedAt = useValidationStore((s) => s.cellPopoverClosedAt);

  const stringValue = String(value ?? '');
  const hasError = errors.length > 0;
  const errorMessage = errors[0]?.message;

  // Find display label for current value
  const selectedOption = options.find((opt) => opt.value === stringValue);
  const displayLabel = selectedOption?.label || stringValue;

  // Handle popover open - trigger fetch if needed
  const handleOpenChange = useCallback(
    (isOpen: boolean) => {
      // Block opening if a popover was just closed (click-outside behavior)
      if (isOpen && Date.now() - cellPopoverClosedAt < POPOVER_CLOSE_DELAY) {
        return;
      }
      // Reset scroll position when opening
      if (isOpen && scrollContainerRef.current) {
        scrollContainerRef.current.scrollTop = 0;
      }
      setOpen(isOpen);
      if (isOpen && onFetchOptions && options.length === 0 && !hasFetchedRef.current) {
        hasFetchedRef.current = true;
        setIsLoadingOptions(true);
        onFetchOptions().finally(() => {
          setIsLoadingOptions(false);
        });
      }
    },
    [onFetchOptions, options.length, cellPopoverClosedAt]
  );

  // Reset scroll position when search filters the list
  const handleSearchChange = useCallback(() => {
    if (scrollContainerRef.current) {
      scrollContainerRef.current.scrollTop = 0;
    }
  }, []);

  // Handle selection
  const handleSelect = useCallback(
    (selectedValue: string) => {
      onBlur(selectedValue);
      setOpen(false);
    },
    [onBlur]
  );

  // Handle wheel scroll in dropdown - stop propagation to prevent table scroll
  const handleWheel = useCallback((e: React.WheelEvent<HTMLDivElement>) => {
    e.stopPropagation();
    e.currentTarget.scrollTop += e.deltaY;
  }, []);

  // Sort options alphabetically by label for consistent display
  const sortedOptions = useMemo(() => {
    return [...options].sort((a, b) => a.label.localeCompare(b.label));
  }, [options]);

  return (
    <div className="relative w-full">
      <Popover open={open} onOpenChange={handleOpenChange}>
        <PopoverTrigger asChild>
          <Button
            variant="outline"
            role="combobox"
            aria-expanded={open}
            className={cn(
              'w-full h-8 justify-between text-sm font-normal',
              hasError && 'border-destructive focus:ring-destructive',
              isValidating && 'opacity-50',
              !stringValue && 'text-muted-foreground'
            )}
            disabled={isValidating}
            title={errorMessage}
          >
            <span className="truncate">
              {displayLabel || field.label}
            </span>
            <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
          </Button>
        </PopoverTrigger>
        <PopoverContent className="w-[250px] p-0" align="start">
          <Command>
            <CommandInput
              placeholder={`Search ${field.label.toLowerCase()}...`}
              onValueChange={handleSearchChange}
            />
            <CommandList>
              {isLoadingOptions ? (
                <div className="flex items-center justify-center py-6">
                  <Loader2 className="h-4 w-4 animate-spin" />
                </div>
              ) : (
                <>
                  <CommandEmpty>No {field.label.toLowerCase()} found.</CommandEmpty>
                  <div
                    ref={scrollContainerRef}
                    className="max-h-[200px] overflow-y-auto overscroll-contain"
                    onWheel={handleWheel}
                  >
                    <CommandGroup>
                      {sortedOptions.map((option) => (
                        <CommandItem
                          key={option.value}
                          value={option.label} // cmdk filters by this value
                          onSelect={() => handleSelect(option.value)}
                        >
                          <Check
                            className={cn(
                              'mr-2 h-4 w-4',
                              stringValue === option.value ? 'opacity-100' : 'opacity-0'
                            )}
                          />
                          {option.label}
                        </CommandItem>
                      ))}
                    </CommandGroup>
                  </div>
                </>
              )}
            </CommandList>
          </Command>
        </PopoverContent>
      </Popover>
      {isValidating && (
        <div className="absolute right-8 top-1/2 -translate-y-1/2">
          <Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
        </div>
      )}
    </div>
  );
};

// Memoize to prevent re-renders when parent table state changes
export const ComboboxCell = memo(ComboboxCellComponent);
