import type { SelectOption } from 'types';
import * as React from 'react';
import { useNavigate } from 'react-router';
import { cn } from 'helpers/cn';
import { Check, ChevronsUpDown } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem } from '@/components/ui/command';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { Separator } from '@/components/ui/separator';

type ComboboxProps<T> = {
  options: SelectOption[];
  value: string | number;
  onChange: (value: T) => void;
  placeholder?: string;
  className?: string;
};
export const Combobox = <T extends string | number>({
  options,
  value,
  onChange,
  placeholder = 'Select...',
  className,
}: ComboboxProps<T>) => {
  const navigate = useNavigate();
  const [open, setOpen] = React.useState(false);

  return (
    <Popover open={open} onOpenChange={setOpen}>
      <PopoverTrigger asChild>
        <Button
          variant="outline"
          role="combobox"
          aria-expanded={open}
          className={cn('w-[200px] justify-between', className)}
        >
          <span className="block truncate">
            {value ? options?.find((option) => option.value === value)?.label : placeholder}
          </span>
          <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
        </Button>
      </PopoverTrigger>
      <PopoverContent className={cn('w-[200px] justify-between', className)}>
        <Command>
          <CommandInput placeholder={placeholder} />
          <CommandEmpty></CommandEmpty>
          <CommandGroup className="max-h-96 overflow-auto">
            {options?.map((option) => (
              <div key={option.value}>
                <CommandItem
                  value={option?.label || '' + option.value}
                  onSelect={(currentValue) => {
                    if (option.href) {
                      return navigate(option.href);
                    }
                    const newValue = options.find(
                      (option) => option.label?.toLowerCase() === currentValue.toLowerCase(),
                    )?.value;
                    if (value && value !== newValue) {
                      const setValue = typeof value === 'number' ? Number(newValue) : '' + newValue;
                      onChange(setValue as T);
                    }
                    setOpen(false);
                  }}
                >
                  <Check className={cn('mr-2 h-4 w-4', value === option.value ? 'opacity-100' : 'opacity-0')} />
                  {option.label}
                </CommandItem>
                {option.href && <Separator className="my-2" />}
              </div>
            ))}
          </CommandGroup>
        </Command>
      </PopoverContent>
    </Popover>
  );
};
