import React, { useState, useRef, useEffect } from 'react';
import { Check, ChevronsUpDown } from 'lucide-react';
import {
  useFloating,
  autoUpdate,
  offset,
  flip,
  shift,
  useClick,
  useDismiss,
  useRole,
  useInteractions,
  FloatingFocusManager,
  FloatingPortal,
  useId,
  Placement
} from '@floating-ui/react';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';

export interface DropdownOption {
  label: string;
  value: string;
}

interface DropdownProps {
  options: DropdownOption[];
  value?: string;
  onValueChange?: (value: string) => void;
  placeholder?: string;
  emptyMessage?: string;
  className?: string;
  containerClassName?: string;
  disabled?: boolean;
  side?: 'top' | 'bottom';
}

export function Dropdown({
  options,
  value,
  onValueChange,
  placeholder = 'Select option...',
  emptyMessage = 'No options found.',
  className,
  containerClassName,
  disabled = false,
  side = 'bottom',
}: DropdownProps) {
  const [open, setOpen] = useState(false);
  const [searchValue, setSearchValue] = useState('');
  const [activeIndex, setActiveIndex] = useState<number | null>(null);
  const [width, setWidth] = useState<number | null>(null);

  const selectedOption = options.find(option => option.value === value);
  const headingId = useId();
  const searchRef = useRef<HTMLInputElement>(null);
  const optionsContainerRef = useRef<HTMLDivElement>(null);
  const selectedOptionRef = useRef<HTMLDivElement>(null);

  const placement: Placement = side === 'top' ? 'top-start' : 'bottom-end';

  const { refs, floatingStyles, context } = useFloating({
    open,
    onOpenChange: setOpen,
    placement,
    middleware: [
      offset(8),
      flip({
        fallbackPlacements: ['bottom-start', 'top-start'],
        padding: 16
      }),
      shift({ padding: 8 }),
    ],
    whileElementsMounted: autoUpdate,
  });

  const click = useClick(context);
  const dismiss = useDismiss(context, {
    outsidePress: true,
  });
  const role = useRole(context);

  const { getReferenceProps, getFloatingProps } = useInteractions([
    click,
    dismiss,
    role,
  ]);

  // Update width when reference element changes
  useEffect(() => {
    if (refs.reference.current && 'getBoundingClientRect' in refs.reference.current) {
      const element = refs.reference.current as HTMLElement;
      setWidth(element.getBoundingClientRect().width);
    }
  }, [refs.reference.current]);

  useEffect(() => {
    if (open && searchRef.current) {
      searchRef.current.focus();
    }
  }, [open]);

  // Scroll to selected option when dropdown opens
  useEffect(() => {
    if (open && optionsContainerRef.current && selectedOptionRef.current && value) {
      // Delay the scroll to ensure the dropdown is fully rendered
      setTimeout(() => {
        selectedOptionRef.current?.scrollIntoView({ block: 'center', behavior: 'auto' });
      }, 50);
    }
  }, [open, value]);

  const filteredOptions = options.filter(option =>
    option.label.toLowerCase().includes(searchValue.toLowerCase())
  );

  const handleSelect = (option: DropdownOption) => {
    onValueChange?.(option.value);
    setOpen(false);
    setSearchValue('');
  };

  return (
    <div className={cn("relative w-full", containerClassName)}>
      <Button
        ref={refs.setReference}
        variant="outline"
        role="combobox"
        aria-expanded={open}
        aria-controls={open ? headingId : undefined}
        className={cn("w-full justify-between", className)}
        disabled={disabled}
        type="button"
        {...getReferenceProps()}
      >
        <span className="truncate mr-2">{selectedOption ? selectedOption.label : placeholder}</span>
        <ChevronsUpDown className="ml-auto h-4 w-4 shrink-0 opacity-50 flex-shrink-0" />
      </Button>

      {open && (
        <FloatingPortal>
          <FloatingFocusManager context={context} modal={false}>
            <div
              ref={refs.setFloating}
              style={{
                ...floatingStyles,
                width: width ? `${Math.max(width, 180)}px` : 'auto',
                maxWidth: '300px',
                zIndex: 10000,
              }}
              className="floating-ui-dropdown shadow-md rounded-md overflow-hidden border border-zinc-200 dark:border-zinc-800"
              aria-labelledby={headingId}
              {...getFloatingProps()}
            >
              <div className="p-2 border-b border-input bg-white dark:bg-zinc-900">
                <input
                  ref={searchRef}
                  type="text"
                  value={searchValue}
                  onChange={(e) => {
                    setSearchValue(e.target.value);
                    setActiveIndex(0);
                  }}
                  onKeyDown={(e) => {
                    if (e.key === 'Enter' && activeIndex !== null && filteredOptions[activeIndex]) {
                      handleSelect(filteredOptions[activeIndex]);
                    } else if (e.key === 'ArrowDown') {
                      e.preventDefault();
                      setActiveIndex(prev =>
                        prev === null || prev === filteredOptions.length - 1 ? 0 : prev + 1
                      );
                    } else if (e.key === 'ArrowUp') {
                      e.preventDefault();
                      setActiveIndex(prev =>
                        prev === null || prev === 0 ? filteredOptions.length - 1 : prev - 1
                      );
                    } else if (e.key === 'Escape') {
                      setOpen(false);
                    }
                  }}
                  className="w-full p-2 text-sm border border-input rounded-md focus:outline-none focus:ring-2 focus:ring-ring bg-white dark:bg-zinc-950 text-foreground"
                  placeholder="Search..."
                />
              </div>

              <div
                ref={optionsContainerRef}
                className="max-h-64 overflow-auto p-1 bg-white dark:bg-zinc-900"
              >
                {filteredOptions.length === 0 ? (
                  <div className="p-2 text-sm text-muted-foreground">{emptyMessage}</div>
                ) : (
                  filteredOptions.map((option, index) => (
                    <div
                      key={option.value}
                      ref={option.value === value ? selectedOptionRef : null}
                      onClick={() => handleSelect(option)}
                      onMouseEnter={() => setActiveIndex(index)}
                      className={cn(
                        "flex items-center gap-2 p-2 text-sm rounded-md cursor-pointer text-foreground",
                        activeIndex === index ? "bg-accent text-accent-foreground" : "",
                        value === option.value ? "bg-accent/50" : "hover:bg-accent/50",
                      )}
                    >
                      <Check
                        className={cn(
                          "h-4 w-4 flex-shrink-0",
                          value === option.value ? "opacity-100" : "opacity-0"
                        )}
                      />
                      <span className="truncate">{option.label}</span>
                    </div>
                  ))
                )}
              </div>
            </div>
          </FloatingFocusManager>
        </FloatingPortal>
      )}
    </div>
  );
} 