/**
 * MultiSelectCell Component
 *
 * Multi-select cell for choosing multiple values.
 * Memoized to prevent unnecessary re-renders when parent table updates.
 *
 * PERFORMANCE: Uses uncontrolled open state for Popover.
 * Controlled open state can cause delays due to React state processing.
 *
 * AI SUGGESTIONS: For categories, themes, and colors fields, this component
 * displays AI-powered suggestions based on product embeddings. Suggestions
 * appear at the top of the dropdown with similarity scores.
 */

import { useCallback, useMemo, memo, useState } from 'react';
import { Check, ChevronsUpDown, AlertCircle, Sparkles, Loader2 } 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 { Badge } from '@/components/ui/badge';
import { Skeleton } from '@/components/ui/skeleton';
import { cn } from '@/lib/utils';
import type { Field, SelectOption } from '../../../../types';
import type { ValidationError, TaxonomySuggestion } from '../../store/types';
import { ErrorType } from '../../store/types';
import { useCellSuggestions } from '../../contexts/AiSuggestionsContext';
import { useValidationStore } from '../../store/validationStore';

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

// Extended option type to include hex color values
interface MultiSelectOption extends SelectOption {
  hex?: string;
  hexColor?: string;
  hex_color?: string;
}

interface MultiSelectCellProps {
  value: unknown;
  field: Field<string>;
  options?: SelectOption[];
  rowIndex: number;
  /** Product's unique __index for AI suggestions */
  productIndex?: string;
  isValidating: boolean;
  errors: ValidationError[];
  onChange: (value: unknown) => void;
  onBlur: (value: unknown) => void;
  onFetchOptions?: () => void;
}

// Fields that support AI suggestions
const SUGGESTION_FIELDS = ['categories', 'themes', 'colors'] as const;
type SuggestionField = typeof SUGGESTION_FIELDS[number];

/**
 * Helper to extract hex color from option
 * Supports hex, hexColor, and hex_color field names
 */
const getOptionHex = (option: MultiSelectOption): string | undefined => {
  if (option.hex) return option.hex.startsWith('#') ? option.hex : `#${option.hex}`;
  if (option.hexColor) return option.hexColor.startsWith('#') ? option.hexColor : `#${option.hexColor}`;
  if (option.hex_color) return option.hex_color.startsWith('#') ? option.hex_color : `#${option.hex_color}`;
  return undefined;
};

/**
 * Check if a color is white or near-white (needs border)
 */
const isWhiteColor = (hex: string): boolean => {
  const normalized = hex.toLowerCase();
  return normalized === '#ffffff' || normalized === '#fff' || normalized === 'ffffff' || normalized === 'fff';
};

const MultiSelectCellComponent = ({
  value,
  field,
  options = [],
  productIndex,
  isValidating,
  errors,
  onChange: _onChange, // Unused - onBlur handles both update and validation
  onBlur,
}: MultiSelectCellProps) => {
  const [open, setOpen] = useState(false);

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

  // Handle popover open/close with check for recent popover close
  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;
    }
    setOpen(isOpen);
  }, [cellPopoverClosedAt]);

  // Get AI suggestions for categories, themes, and colors
  const supportsSuggestions = SUGGESTION_FIELDS.includes(field.key as SuggestionField);
  const suggestions = useCellSuggestions(productIndex || '');

  // Get the right suggestions based on field type
  const fieldSuggestions: TaxonomySuggestion[] = useMemo(() => {
    if (!supportsSuggestions || !productIndex) return [];
    switch (field.key) {
      case 'categories': return suggestions.categories;
      case 'themes': return suggestions.themes;
      case 'colors': return suggestions.colors;
      default: return [];
    }
  }, [supportsSuggestions, productIndex, field.key, suggestions]);

  // 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;
  }, []);

  // Parse value to array
  const selectedValues = useMemo(() => {
    if (Array.isArray(value)) return value.map(String);
    if (typeof value === 'string' && value) {
      const separator = 'separator' in field.fieldType ? field.fieldType.separator : ',';
      return value.split(separator || ',').map((v) => v.trim()).filter(Boolean);
    }
    return [];
  }, [value, field.fieldType]);

  // 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 = selectedValues.length === 0;
  const showErrorIcon = hasError && !(valueIsEmpty && isRequiredError);
  const errorMessage = errors.filter(e => !(valueIsEmpty && e.type === ErrorType.Required))
    .map(e => e.message).join('\n');

  // Only call onBlur - it handles both the cell update AND validation
  // Calling onChange separately would cause a redundant store update
  const handleSelect = useCallback(
    (optionValue: string) => {
      let newValues: string[];
      if (selectedValues.includes(optionValue)) {
        newValues = selectedValues.filter((v) => v !== optionValue);
      } else {
        newValues = [...selectedValues, optionValue];
      }
      onBlur(newValues);
    },
    [selectedValues, onBlur]
  );

  // Get labels for selected values (including hex color for colors field)
  const selectedLabels = useMemo(() => {
    return selectedValues.map((val) => {
      const option = options.find((opt) => opt.value === val) as MultiSelectOption | undefined;
      const hexColor = field.key === 'colors' && option ? getOptionHex(option) : undefined;
      return { value: val, label: option?.label || val, hex: hexColor };
    });
  }, [selectedValues, options, field.key]);

  // Show loading skeleton when validating or when we have values but no options (not yet loaded)
  const showLoadingSkeleton = isValidating || (selectedValues.length > 0 && options.length === 0);

  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',
              selectedValues.length === 0 && 'text-muted-foreground',
              showErrorIcon && 'pr-8'
            )}
          >
            <div className="flex items-center w-full justify-between overflow-hidden">
              <div className="flex items-center gap-2 overflow-hidden">
                {selectedLabels.length === 0 ? (
                  <span className="text-muted-foreground truncate">Select...</span>
                ) : selectedLabels.length === 1 ? (
                  <div className="flex items-center gap-1.5 truncate">
                    {field.key === 'colors' && selectedLabels[0].hex && (
                      <span
                        className={cn(
                          'inline-block h-3 w-3 rounded-full flex-shrink-0',
                          isWhiteColor(selectedLabels[0].hex) && 'border border-black'
                        )}
                        style={{ backgroundColor: selectedLabels[0].hex }}
                      />
                    )}
                    <span className="truncate">{selectedLabels[0].label}</span>
                  </div>
                ) : (
                  <>
                    <Badge variant="secondary" className="shrink-0 whitespace-nowrap">
                      {selectedLabels.length} selected
                    </Badge>
                    <div className="flex items-center gap-1 truncate">
                      {field.key === 'colors' ? (
                        // Show color swatches for colors field
                        selectedLabels.slice(0, 5).map((v, i) => (
                          v.hex ? (
                            <span
                              key={i}
                              className={cn(
                                'inline-block h-3 w-3 rounded-full flex-shrink-0',
                                isWhiteColor(v.hex) && 'border border-black'
                              )}
                              style={{ backgroundColor: v.hex }}
                              title={v.label}
                            />
                          ) : null
                        ))
                      ) : (
                        <span className="truncate">
                          {selectedLabels.map((v) => v.label).join(', ')}
                        </span>
                      )}
                    </div>
                  </>
                )}
              </div>
            </div>
            <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
          </Button>
        </PopoverTrigger>
        <PopoverContent className="w-[var(--radix-popover-trigger-width)] p-0" align="start">
          <Command>
            <CommandInput placeholder={`Search ${field.label}...`} />
            <CommandList>
              <CommandEmpty>No options found.</CommandEmpty>
              <div
                className="max-h-[250px] overflow-y-auto overscroll-contain"
                onWheel={handleWheel}
              >
                {/* Selected items section - floats to top of dropdown */}
                {selectedValues.length > 0 && (
                  <CommandGroup>
                    <div className="flex items-center gap-2 px-2 py-1.5 text-xs font-medium text-green-600 dark:text-green-400 bg-green-50/80 dark:bg-green-950/40 border-b border-green-100 dark:border-green-900">
                      <Check className="h-3 w-3" />
                      <span>Selected ({selectedValues.length})</span>
                    </div>
                    {selectedValues.map((selectedVal) => {
                      const option = options.find((opt) => opt.value === selectedVal) as MultiSelectOption | undefined;
                      const hexColor = field.key === 'colors' && option ? getOptionHex(option) : undefined;
                      const isWhite = hexColor ? isWhiteColor(hexColor) : false;
                      const label = option?.label || selectedVal;

                      return (
                        <CommandItem
                          key={`selected-${selectedVal}`}
                          value={`selected-${label}`}
                          onSelect={() => handleSelect(selectedVal)}
                          className="bg-green-50/50 dark:bg-green-950/30"
                        >
                          <Check className="mr-2 h-4 w-4 opacity-100 text-green-600" />
                          {field.key === 'colors' && hexColor && (
                            <span
                              className={cn(
                                'inline-block h-3.5 w-3.5 rounded-full mr-2 flex-shrink-0',
                                isWhite && 'border border-black'
                              )}
                              style={{ backgroundColor: hexColor }}
                            />
                          )}
                          {label}
                        </CommandItem>
                      );
                    })}
                  </CommandGroup>
                )}

                {/* AI Suggestions section - shown below selected items */}
                {supportsSuggestions && (fieldSuggestions.length > 0 || suggestions.isLoading) && (
                  <CommandGroup>
                    <div className="flex items-center gap-2 px-2 py-1.5 text-xs font-medium text-purple-600 dark:text-purple-400 bg-purple-50/80 dark:bg-purple-950/40 border-b border-purple-100 dark:border-purple-900">
                      <Sparkles className="h-3 w-3" />
                      <span>Suggested</span>
                      {suggestions.isLoading && <Loader2 className="h-3 w-3 animate-spin" />}
                    </div>
                    {fieldSuggestions.slice(0, 5).map((suggestion) => {
                      const isSelected = selectedValues.includes(String(suggestion.id));
                      // Skip suggestions that are already in the Selected section
                      if (isSelected) return null;
                      const similarityPercent = Math.round(suggestion.similarity * 100);
                      const hexColor = field.key === 'colors'
                        ? options.find(o => o.value === String(suggestion.id)) as MultiSelectOption | undefined
                        : undefined;
                      const suggestionHex = hexColor ? getOptionHex(hexColor) : undefined;

                      return (
                        <CommandItem
                          key={`suggestion-${suggestion.id}`}
                          value={`suggestion-${suggestion.name}`}
                          onSelect={() => handleSelect(String(suggestion.id))}
                          className="bg-purple-50/30 dark:bg-purple-950/20"
                        >
                          <div className="flex items-center gap-2 min-w-0 flex-1">
                            <Check className="h-4 w-4 flex-shrink-0 opacity-0" />
                            {/* Color circle for colors */}
                            {field.key === 'colors' && suggestionHex && (
                              <span
                                className={cn(
                                  'inline-block h-3.5 w-3.5 rounded-full flex-shrink-0',
                                  isWhiteColor(suggestionHex) && 'border border-black'
                                )}
                                style={{ backgroundColor: suggestionHex }}
                              />
                            )}
                            {/* Show full path for categories/themes, just name for colors */}
                            <span className="" title={suggestion.fullPath || suggestion.name}>
                              {field.key === 'colors' ? suggestion.name : (suggestion.fullPath || suggestion.name)}
                            </span>
                          </div>
                          <span className="text-xs text-purple-500 dark:text-purple-400 ml-2 flex-shrink-0">
                            {similarityPercent}%
                          </span>
                        </CommandItem>
                      );
                    })}
                  </CommandGroup>
                )}

                {/* Regular options - excludes selected items (shown in Selected section above) */}
                <CommandGroup heading={selectedValues.length > 0 || (supportsSuggestions && fieldSuggestions.length > 0) ? "All Options" : undefined}>
                  {options
                    .filter((option) => !selectedValues.includes(option.value))
                    .map((option) => {
                      const hexColor = field.key === 'colors' ? getOptionHex(option as MultiSelectOption) : undefined;
                      const isWhite = hexColor ? isWhiteColor(hexColor) : false;

                      return (
                        <CommandItem
                          key={option.value}
                          value={option.label}
                          onSelect={() => handleSelect(option.value)}
                        >
                          <Check className="mr-2 h-4 w-4 opacity-0" />
                          {/* Color circle for colors field */}
                          {field.key === 'colors' && hexColor && (
                            <span
                              className={cn(
                                'inline-block h-3.5 w-3.5 rounded-full mr-2 flex-shrink-0',
                                isWhite && 'border border-black'
                              )}
                              style={{ backgroundColor: hexColor }}
                            />
                          )}
                          {option.label}
                        </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 MultiSelectCell = memo(MultiSelectCellComponent);
