'use client';

import { Check, ChevronsUpDown } from 'lucide-react';
import type { ButtonHTMLAttributes } from 'react';
import { useMemo, useState } from 'react';

import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { cn } from '@/lib/utils';

export type PartySelectorOption = {
  id: string;
  label: string;
  description?: string;
  searchableText?: string;
};

export type PartySelectorProps = {
  value: string;
  options: PartySelectorOption[];
  placeholder?: string;
  searchPlaceholder?: string;
  emptyLabel?: string;
  open?: boolean;
  onOpenChange?: (open: boolean) => void;
  onValueChange: (id: string) => void;
  footerAction?: React.ReactNode;
  buttonClassName?: string;
} & Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'type' | 'value'>;

export function PartySelector({
  value,
  options,
  placeholder,
  searchPlaceholder,
  emptyLabel,
  open,
  onOpenChange,
  onValueChange,
  footerAction,
  buttonClassName,
  ...buttonProps
}: PartySelectorProps) {
  const [query, setQuery] = useState('');
  const [internalOpen, setInternalOpen] = useState(false);

  const isControlled = open !== undefined;
  const resolvedOpen = isControlled ? open : internalOpen;
  const handleOpenChange = (next: boolean) => {
    if (!isControlled) setInternalOpen(next);
    onOpenChange?.(next);
  };

  const selected = useMemo(() => options.find((option) => option.id === value), [options, value]);
  const filtered = useMemo(() => {
    const normalized = query.trim().toLowerCase();
    if (!normalized) return options;

    return options.filter((option) => {
      const haystack = `${option.label} ${option.description ?? ''} ${option.searchableText ?? ''}`.toLowerCase();
      return haystack.includes(normalized);
    });
  }, [options, query]);

  return (
    <Popover open={resolvedOpen} onOpenChange={handleOpenChange}>
      <PopoverTrigger asChild>
        <Button
          {...buttonProps}
          type="button"
          variant="outline"
          role="combobox"
          className={cn(
            'w-full h-9 justify-between text-sm',
            !selected && 'text-muted-foreground',
            buttonClassName,
            buttonProps.className
          )}
        >
          {selected?.label ?? placeholder ?? 'Select option'}
          <ChevronsUpDown className="ms-2 h-4 w-4 shrink-0 opacity-50" />
        </Button>
      </PopoverTrigger>
      <PopoverContent className="w-[--radix-popover-trigger-width] p-0">
        <div className="p-2 border-b">
          <Input
            placeholder={searchPlaceholder ?? 'Search...'}
            value={query}
            onChange={(event) => setQuery(event.target.value)}
            autoFocus
          />
        </div>

        <div className="max-h-60 overflow-y-auto">
          {filtered.length > 0 ? (
            filtered.map((option) => (
              <button
                key={option.id}
                type="button"
                onClick={() => {
                  onValueChange(option.id);
                  handleOpenChange(false);
                  setQuery('');
                }}
                className={cn(
                  'w-full flex items-center gap-2 text-start px-2 py-1.5 text-sm hover:bg-accent',
                  option.id === value && 'bg-accent'
                )}
              >
                <Check className={cn('h-4 w-4', option.id === value ? 'opacity-100' : 'opacity-0')} />
                <span className="flex-1">{option.label}</span>
                {option.description ? (
                  <span className="text-xs text-muted-foreground">{option.description}</span>
                ) : null}
              </button>
            ))
          ) : (
            <div className="px-3 py-4 text-center text-sm text-muted-foreground">
              {emptyLabel ?? 'No results'}
            </div>
          )}
        </div>

        {footerAction ? <div className="border-t p-2">{footerAction}</div> : null}
      </PopoverContent>
    </Popover>
  );
}
