import * as React from 'react';
import { Input } from '../input';
import { SelectOptionItem } from './SelectOptionItem';
import type { GroupedOptions, SelectOption } from './types';

interface SelectDropdownContentProps {
  searchable: boolean;
  search: string;
  onSearchChange: (v: string) => void;
  searchInputRef: React.RefObject<HTMLInputElement | null>;
  filteredOptions: GroupedOptions;
  multiple: boolean;
  isSelected: (value: string) => boolean;
  onSelect: (value: string) => void;
  ariaLabel?: string;
  name?: string;
  placeholder?: string;
}

export function SelectDropdownContent({
  searchable,
  search,
  onSearchChange,
  searchInputRef,
  filteredOptions,
  multiple,
  isSelected,
  onSelect,
  ariaLabel,
  name,
  placeholder,
}: SelectDropdownContentProps) {
  const listboxId = React.useId();
  const [highlightedIndex, setHighlightedIndex] = React.useState(-1);

  // Flatten all options for keyboard navigation
  const allOptions = React.useMemo(() => {
    const options: SelectOption[] = [...filteredOptions.ungrouped];
    Object.values(filteredOptions.groups).forEach((groupOptions) => {
      options.push(...groupOptions);
    });
    return options.filter((o) => !o.disabled);
  }, [filteredOptions]);

  const highlightedOptionId =
    highlightedIndex >= 0 && highlightedIndex < allOptions.length
      ? `${listboxId}-option-${allOptions[highlightedIndex].value}`
      : undefined;

  const handleKeyDown = (e: React.KeyboardEvent) => {
    switch (e.key) {
      case 'ArrowDown':
        e.preventDefault();
        setHighlightedIndex((prev) =>
          prev < allOptions.length - 1 ? prev + 1 : 0,
        );
        break;
      case 'ArrowUp':
        e.preventDefault();
        setHighlightedIndex((prev) =>
          prev > 0 ? prev - 1 : allOptions.length - 1,
        );
        break;
      case 'Enter':
      case ' ':
        if (highlightedIndex >= 0 && highlightedIndex < allOptions.length) {
          e.preventDefault();
          onSelect(allOptions[highlightedIndex].value);
        }
        break;
      case 'Home':
        e.preventDefault();
        setHighlightedIndex(0);
        break;
      case 'End':
        e.preventDefault();
        setHighlightedIndex(allOptions.length - 1);
        break;
    }
  };

  const hasOptions =
    filteredOptions.ungrouped.length > 0 ||
    Object.keys(filteredOptions.groups).length > 0;

  return (
    <div
      className="w-full min-w-48 max-h-72 overflow-y-auto"
      role="listbox"
      aria-label={ariaLabel || name || placeholder}
      aria-activedescendant={highlightedOptionId}
      onKeyDown={handleKeyDown}
    >
      {searchable && (
        <div className="p-2 border-b">
          <Input
            ref={searchInputRef}
            type="text"
            placeholder="Search..."
            value={search}
            onChange={(e) => onSearchChange(e.target.value)}
            onClick={(e) => e.stopPropagation()}
            onKeyDown={handleKeyDown}
            className="w-full"
          />
        </div>
      )}
      {filteredOptions.ungrouped.length > 0 && (
        <div className="py-1">
          {filteredOptions.ungrouped.map((option) => (
            <SelectOptionItem
              key={option.value}
              option={option}
              isSelected={isSelected(option.value)}
              isHighlighted={
                highlightedIndex >= 0 &&
                highlightedIndex < allOptions.length &&
                allOptions[highlightedIndex].value === option.value
              }
              multiple={multiple}
              onSelect={onSelect}
              optionId={`${listboxId}-option-${option.value}`}
            />
          ))}
        </div>
      )}
      {Object.entries(filteredOptions.groups).map(([groupLabel, groupOptions]) => (
        <div key={groupLabel} className="py-1">
          <div className="px-4 py-1.5 text-xs font-semibold text-muted-foreground uppercase">
            {groupLabel}
          </div>
          {groupOptions.map((option) => (
            <SelectOptionItem
              key={option.value}
              option={option}
              isSelected={isSelected(option.value)}
              isHighlighted={
                highlightedIndex >= 0 &&
                highlightedIndex < allOptions.length &&
                allOptions[highlightedIndex].value === option.value
              }
              multiple={multiple}
              onSelect={onSelect}
              optionId={`${listboxId}-option-${option.value}`}
            />
          ))}
        </div>
      ))}
      {!hasOptions && (
        <div className="px-4 py-2 text-sm text-muted-foreground text-center">
          No options found
        </div>
      )}
    </div>
  );
}
