/**
 * SelectCell Component
 *
 * Searchable dropdown select cell for single-value selection.
 * Uses Command component for built-in search filtering.
 * Memoized to prevent unnecessary re-renders when parent table updates.
 */

import { useState, useCallback, useRef, useMemo, memo } from 'react';
import { Check, ChevronsUpDown, Loader2, AlertCircle } from 'lucide-react';
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 {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from '@/components/ui/tooltip';
import { Skeleton } from '@/components/ui/skeleton';
import { cn } from '@/lib/utils';
import type { Field, SelectOption } from '../../../../types';
import type { ValidationError } from '../../store/types';
import { ErrorType } 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 SelectCellProps {
  value: unknown;
  field: Field<string>;
  options?: SelectOption[];
  rowIndex: number;
  isValidating: boolean;
  errors: ValidationError[];
  onChange: (value: unknown) => void;
  onBlur: (value: unknown) => void;
  onFetchOptions?: () => Promise<SelectOption[]>;
  isLoadingOptions?: boolean; // External loading state (e.g., when company changes)
}

const SelectCellComponent = ({
  value,
  field,
  options = [],
  isValidating,
  errors,
  onChange: _onChange,
  onBlur,
  onFetchOptions,
  isLoadingOptions: externalLoadingOptions = false,
}: SelectCellProps) => {
  const [open, setOpen] = useState(false);
  const [isFetchingOptions, setIsFetchingOptions] = 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);

  // Combined loading state - either internal fetch or external loading
  const isLoadingOptions = isFetchingOptions || externalLoadingOptions;

  const stringValue = String(value ?? '');
  
  // Process errors - show icon only for non-required errors when field has value
  const hasError = errors.length > 0;
  const isRequiredError = errors.length === 1 && errors[0]?.type === ErrorType.Required;
  const valueIsEmpty = !stringValue;
  const showErrorIcon = hasError && !(valueIsEmpty && isRequiredError);
  const errorMessage = errors.filter(e => !(valueIsEmpty && e.type === ErrorType.Required))
    .map(e => e.message).join('\n');

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

  // Find display label for current value
  // IMPORTANT: We need to match against both string and number value types
  const displayLabel = useMemo(() => {
    if (!stringValue) return '';
    // Try exact string match first, then loose match
    const found = options.find((opt) =>
      String(opt.value) === stringValue || opt.value === stringValue
    );
    return found?.label ?? null; // Return null if not found (don't fallback to ID)
  }, [options, stringValue]);

  // Check if we have a value but couldn't find its label in options
  // This indicates options haven't loaded yet
  const valueWithoutLabel = stringValue && displayLabel === null;

  // Show loading skeleton when:
  // - Validating
  // - Have a value but no options and couldn't find label
  // - External loading state (e.g., fetching lines after company change)
  const showLoadingSkeleton = isValidating || (valueWithoutLabel && options.length === 0) || externalLoadingOptions;

  if (showLoadingSkeleton) {
    return (
      <div className={cn(
        'h-8 w-full flex items-center border rounded-md px-2',
        hasError && 'border-destructive'
      )}>
        <Skeleton className="h-4 w-full" />
      </div>
    );
  }

  return (
    <div className="relative w-full">
      <Popover open={open} onOpenChange={handleOpenChange}>
        <PopoverTrigger asChild>
          <Button
            variant="outline"
            role="combobox"
            aria-expanded={open}
            disabled={isValidating}
            className={cn(
              'h-8 w-full justify-between text-sm font-normal',
              hasError && 'border-destructive focus:ring-destructive',
              isValidating && 'opacity-50',
              !stringValue && 'text-muted-foreground',
              showErrorIcon && 'pr-8'
            )}
          >
            <span className="truncate">
              {/* Show label if found, placeholder if no value, or loading indicator if value but no label */}
              {displayLabel ? displayLabel : !stringValue ? field.label : (
                <span className="text-muted-foreground italic">Loading...</span>
              )}
            </span>
            <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
          </Button>
        </PopoverTrigger>
        <PopoverContent
          className="p-0 w-[var(--radix-popover-trigger-width)]"
          align="start"
          sideOffset={4}
        >
          <Command shouldFilter={true}>
            <CommandInput
              placeholder="Search..."
              className="h-9"
              onValueChange={handleSearchChange}
            />
            <CommandList>
              {isLoadingOptions ? (
                <div className="flex items-center justify-center py-4">
                  <Loader2 className="h-4 w-4 animate-spin" />
                </div>
              ) : (
                <>
                  <CommandEmpty>No results 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}
                          onSelect={() => handleSelect(option.value)}
                          className="cursor-pointer"
                        >
                          {option.label}
                          {String(option.value) === stringValue && (
                            <Check className="ml-auto h-4 w-4" />
                          )}
                        </CommandItem>
                      ))}
                    </CommandGroup>
                  </div>
                </>
              )}
            </CommandList>
          </Command>
        </PopoverContent>
      </Popover>
      
      {/* Error icon with tooltip - only for non-required errors */}
      {showErrorIcon && (
        <div className="absolute right-2 top-1/2 -translate-y-1/2 z-10">
          <TooltipProvider>
            <Tooltip delayDuration={200}>
              <TooltipTrigger asChild>
                <div className="cursor-help">
                  <AlertCircle className="h-4 w-4 text-destructive" />
                </div>
              </TooltipTrigger>
              <TooltipContent className="max-w-[300px]">
                <p className="whitespace-pre-wrap">{errorMessage}</p>
              </TooltipContent>
            </Tooltip>
          </TooltipProvider>
        </div>
      )}
    </div>
  );
};

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