import { useMemo, useState, type WheelEvent } from "react";
import { Check, ChevronsUpDown, X } from "lucide-react";

import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
} from "@/components/ui/command";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { canonicalOptionLabel, dedupeOptions, normalizeOptionKey } from "@/lib/optionUtils";
import { cn } from "@/lib/utils";

function handleDropdownWheel(event: WheelEvent<HTMLDivElement>) {
  event.preventDefault();
  event.stopPropagation();
  event.currentTarget.scrollTop += event.deltaY;
}

interface SearchableMultiSelectProps {
  values: string[];
  options: string[];
  onValuesChange: (values: string[]) => void;
  placeholder?: string;
  searchPlaceholder?: string;
  emptyText?: string;
  disabled?: boolean;
  summaryLabel?: string;
}

function cleanValues(values: string[]) {
  return dedupeOptions(values.map((value) => canonicalOptionLabel(value)).filter(Boolean));
}

export function SearchableMultiSelect({
  values,
  options,
  onValuesChange,
  placeholder = "Seleccionar…",
  searchPlaceholder = "Buscar…",
  emptyText = "No hay resultados.",
  disabled = false,
  summaryLabel = "opciones seleccionadas",
}: SearchableMultiSelectProps) {
  const [open, setOpen] = useState(false);
  const selectedValues = useMemo(() => cleanValues(values), [values]);
  const normalizedSelected = useMemo(
    () => new Set(selectedValues.map((value) => normalizeOptionKey(value))),
    [selectedValues],
  );
  const cleanOptions = useMemo(
    () =>
      dedupeOptions([...options, ...selectedValues].map((option) => canonicalOptionLabel(option))),
    [options, selectedValues],
  );

  const selectedSummary = useMemo(() => {
    if (selectedValues.length === 0) return "";
    if (selectedValues.length <= 2) return selectedValues.join(", ");
    return `${selectedValues.length} ${summaryLabel}`;
  }, [selectedValues, summaryLabel]);

  const updateValues = (nextValues: string[]) => {
    onValuesChange(cleanValues(nextValues));
  };

  const toggleOption = (option: string) => {
    const cleanOption = canonicalOptionLabel(option);
    const optionKey = normalizeOptionKey(cleanOption);

    if (normalizedSelected.has(optionKey)) {
      updateValues(selectedValues.filter((value) => normalizeOptionKey(value) !== optionKey));
      return;
    }

    updateValues([...selectedValues, cleanOption]);
  };

  const removeOption = (option: string) => {
    const optionKey = normalizeOptionKey(option);
    updateValues(selectedValues.filter((value) => normalizeOptionKey(value) !== optionKey));
  };

  return (
    <div className="space-y-2">
      <Popover open={open} onOpenChange={setOpen}>
        <PopoverTrigger asChild>
          <Button
            type="button"
            variant="outline"
            role="combobox"
            aria-expanded={open}
            disabled={disabled}
            className={cn(
              "min-h-10 w-full justify-between rounded-md border-border bg-background px-3 font-normal hover:bg-background",
              !selectedSummary && "text-muted-foreground",
            )}
          >
            <span className="truncate text-left">{selectedSummary || placeholder}</span>
            <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
          </Button>
        </PopoverTrigger>
        <PopoverContent align="start" className="w-[var(--radix-popover-trigger-width)] p-0">
          <Command>
            <CommandInput placeholder={searchPlaceholder} />
            <CommandList className="overscroll-contain" onWheel={handleDropdownWheel}>
              <CommandEmpty>{emptyText}</CommandEmpty>
              <CommandGroup>
                {cleanOptions.map((option) => {
                  const selected = normalizedSelected.has(normalizeOptionKey(option));

                  return (
                    <CommandItem key={option} value={option} onSelect={() => toggleOption(option)}>
                      <Check
                        className={cn("mr-2 h-4 w-4", selected ? "opacity-100" : "opacity-0")}
                      />
                      <span className="truncate">{option}</span>
                    </CommandItem>
                  );
                })}
              </CommandGroup>
            </CommandList>
          </Command>
        </PopoverContent>
      </Popover>

      {selectedValues.length > 0 && (
        <div className="flex flex-wrap gap-1.5">
          {selectedValues.map((value) => (
            <Badge key={value} variant="secondary" className="gap-1 rounded-full px-2 py-0.5">
              <span className="max-w-[190px] truncate">{value}</span>
              <button
                type="button"
                onClick={() => removeOption(value)}
                className="rounded-full text-muted-foreground transition-colors hover:text-foreground"
                aria-label={`Quitar ${value}`}
              >
                <X className="h-3 w-3" />
              </button>
            </Badge>
          ))}
        </div>
      )}
    </div>
  );
}
