import { cn } from '@/lib/utils';
import { CaretDownIcon, CheckIcon } from '@phosphor-icons/react';
import { useEffect, useRef, useState } from 'react';
import { Button } from './button';
import { Input } from './input';
import { Popover, PopoverContent, PopoverTrigger } from './popover';

export type ComboboxOption = {
  label: string;
  value: string;
};

type ComboboxVariant = 'default';

type ComboboxProps = {
  options: ComboboxOption[];
  value?: string;
  onChange?: (value: string) => void;
  placeholder?: string;
  searchPlaceholder?: string;
  disabled?: boolean;
  className?: string;
  variant?: ComboboxVariant;
};

const TRIGGER_VARIANTS: Record<ComboboxVariant, string> = {
  default:
    'h-11 w-full justify-between rounded-md border border-black/5 bg-black/5 font-normal',
};

const CONTENT_VARIANTS: Record<ComboboxVariant, string> = {
  default: '',
};

const SEARCH_VARIANTS: Record<ComboboxVariant, string> = {
  default: 'h-8 border-0 bg-transparent px-1 shadow-none focus-visible:ring-0',
};

const ITEM_VARIANTS: Record<ComboboxVariant, string> = {
  default:
    'flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm hover:bg-accent hover:text-accent-foreground',
};

export function Combobox({
  options,
  value,
  onChange,
  placeholder = 'Select...',
  searchPlaceholder = 'Search...',
  disabled,
  className,
  variant = 'default',
}: ComboboxProps) {
  const [open, setOpen] = useState(false);
  const [search, setSearch] = useState('');
  const inputRef = useRef<HTMLInputElement>(null);

  const selectedLabel =
    options.find((o) => o.value === value)?.label ?? value ?? '';

  const filtered = search
    ? options.filter(
        (o) =>
          o.label.toLowerCase().includes(search.toLowerCase()) ||
          o.value.toLowerCase().includes(search.toLowerCase()),
      )
    : options;

  // Reset search when closing, focus input when opening
  const handleOpenChange = (next: boolean) => {
    if (!next) setSearch('');
    setOpen(next);
  };

  useEffect(() => {
    if (open) {
      setTimeout(() => inputRef.current?.focus(), 0);
    }
  }, [open]);

  return (
    <Popover open={open} onOpenChange={handleOpenChange}>
      <PopoverTrigger asChild>
        <Button
          type="button"
          variant="outline"
          disabled={disabled}
          className={cn(
            TRIGGER_VARIANTS[variant],
            !selectedLabel && 'text-muted-foreground',
            className,
          )}
        >
          <span className="truncate text-black dark:text-white">
            {selectedLabel || placeholder}
          </span>
          <CaretDownIcon
            weight="bold"
            className="ml-2 size-4 shrink-0 opacity-50"
          />
        </Button>
      </PopoverTrigger>
      <PopoverContent
        className={cn(
          'w-[var(--radix-popover-trigger-width)] p-0',
          CONTENT_VARIANTS[variant],
        )}
        align="start"
      >
        <div className="border-b border-inherit p-2">
          <Input
            ref={inputRef}
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            placeholder={searchPlaceholder}
            className={SEARCH_VARIANTS[variant]}
          />
        </div>
        <div className="max-h-60 overflow-y-auto p-1">
          {filtered.length === 0 ? (
            <p className="py-6 text-center text-sm text-muted-foreground">
              No results found.
            </p>
          ) : (
            filtered.map((opt) => (
              <button
                key={opt.value}
                type="button"
                className={ITEM_VARIANTS[variant]}
                onClick={() => {
                  onChange?.(opt.value);
                  handleOpenChange(false);
                }}
              >
                <CheckIcon
                  weight="bold"
                  className={cn(
                    'size-4 shrink-0',
                    value === opt.value ? 'opacity-100' : 'opacity-0',
                  )}
                />
                {opt.label}
              </button>
            ))
          )}
        </div>
      </PopoverContent>
    </Popover>
  );
}
