"use client";

import { useState } from "react";
import { Check, ChevronDown, Search } from "lucide-react";
import { Input } from "@/components/ui/input";

export type SearchableFilterOption = {
  value: string;
  label: string;
  description?: string;
};

export function SearchableFilterField({
  name,
  label,
  value,
  options,
  placeholder,
  helperText,
  onValueChange,
  allowCustomValue = true,
  disabled = false,
  required = false,
}: {
  name: string;
  label: string;
  value: string;
  options: readonly SearchableFilterOption[];
  placeholder?: string;
  helperText?: string;
  onValueChange: (value: string) => void;
  allowCustomValue?: boolean;
  disabled?: boolean;
  required?: boolean;
}) {
  const [open, setOpen] = useState(false);
  const [query, setQuery] = useState("");
  const [activeIndex, setActiveIndex] = useState(-1);
  const listId = `filter-options-${name}`;
  const selectedOption = options.find((option) => option.value === value);
  const inputValue = open ? query : selectedOption?.label ?? value;
  const normalizedQuery = query.trim().toLowerCase();
  const visibleOptions = options
    .filter((option) =>
      `${option.label} ${option.value} ${option.description ?? ""}`
        .toLowerCase()
        .includes(normalizedQuery),
    )
    .slice(0, 50);

  function closeOptions() {
    setOpen(false);
    setQuery("");
    setActiveIndex(-1);
  }

  function selectOption(option: SearchableFilterOption) {
    onValueChange(option.value);
    closeOptions();
  }

  return (
    <div className="min-w-0">
      <label className="field-label" htmlFor={`filter-${name}`}>
        {label}
        {required && <span className="text-destructive"> *</span>}
      </label>
      <input type="hidden" name={name} value={value} />
      <div className="relative">
        <Search
          aria-hidden="true"
          className="pointer-events-none absolute left-3 top-1/2 z-10 size-4 -translate-y-1/2 text-muted-foreground"
        />
        <Input
          id={`filter-${name}`}
          role="combobox"
          aria-autocomplete="list"
          aria-expanded={open}
          aria-controls={listId}
          aria-activedescendant={
            open && visibleOptions[activeIndex]
              ? `${listId}-option-${activeIndex}`
              : undefined
          }
          autoComplete="off"
          disabled={disabled}
          aria-required={required}
          placeholder={placeholder ?? `Search ${label.toLowerCase()}...`}
          value={inputValue}
          onFocus={() => {
            setOpen(true);
            setQuery("");
            setActiveIndex(-1);
          }}
          onClick={() => {
            if (!open) {
              setOpen(true);
              setQuery("");
              setActiveIndex(-1);
            }
          }}
          onBlur={closeOptions}
          onChange={(event) => {
            const nextValue = event.target.value;
            setOpen(true);
            setQuery(nextValue);
            setActiveIndex(0);
            const nextSelection = allowCustomValue ? nextValue : "";
            if (nextSelection !== value) onValueChange(nextSelection);
          }}
          onKeyDown={(event) => {
            if (event.key === "ArrowDown" && visibleOptions.length) {
              event.preventDefault();
              setOpen(true);
              setActiveIndex((index) =>
                index < 0 || index >= visibleOptions.length - 1 ? 0 : index + 1,
              );
            } else if (event.key === "ArrowUp" && visibleOptions.length) {
              event.preventDefault();
              setOpen(true);
              setActiveIndex((index) =>
                index <= 0 ? visibleOptions.length - 1 : index - 1,
              );
            } else if (
              event.key === "Enter" &&
              open &&
              visibleOptions[activeIndex]
            ) {
              event.preventDefault();
              selectOption(visibleOptions[activeIndex]);
            } else if (event.key === "Escape" && open) {
              event.preventDefault();
              event.stopPropagation();
              closeOptions();
            }
          }}
          className="pr-10 pl-10"
        />
        <ChevronDown
          aria-hidden="true"
          className="pointer-events-none absolute right-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground"
        />
        {open && (
          <div
            id={listId}
            role="listbox"
            aria-label={`${label} options`}
            className="absolute inset-x-0 top-[calc(100%+0.375rem)] z-[60] max-h-56 overflow-y-auto rounded-lg border bg-popover p-1 text-popover-foreground shadow-lg"
          >
            {visibleOptions.length ? (
              visibleOptions.map((option, index) => (
                <div
                  key={option.value}
                  id={`${listId}-option-${index}`}
                  role="option"
                  aria-selected={value === option.value}
                  className={`flex cursor-pointer items-start gap-3 rounded-md px-3 py-2.5 outline-none ${
                    index === activeIndex
                      ? "bg-accent text-accent-foreground"
                      : "hover:bg-muted"
                  }`}
                  onMouseEnter={() => setActiveIndex(index)}
                  onMouseDown={(event) => event.preventDefault()}
                  onClick={() => selectOption(option)}
                >
                  <span className="min-w-0 flex-1">
                    <span className="block truncate font-medium">
                      {option.label}
                    </span>
                    {(option.description || option.value !== option.label) && (
                      <span className="mt-0.5 block truncate text-xs text-muted-foreground">
                        {option.description ?? option.value}
                      </span>
                    )}
                  </span>
                  {value === option.value && (
                    <Check
                      aria-hidden="true"
                      className="mt-0.5 size-4 shrink-0 text-primary"
                    />
                  )}
                </div>
              ))
            ) : (
              <p className="px-3 py-3 text-sm text-muted-foreground">
                {allowCustomValue ? "No matching options. Paste an ID to filter directly." : "No matching options. Try another search."}
              </p>
            )}
          </div>
        )}
      </div>
      {selectedOption && open && !query && (
        <p className="mt-1.5 text-xs text-muted-foreground">
          Selected: {selectedOption.label}
        </p>
      )}
      {!selectedOption && value && open && !query && (
        <p className="mt-1.5 text-xs text-muted-foreground">
          Current ID: {value}
        </p>
      )}
      {helperText && (
        <p className="mt-1.5 text-xs leading-relaxed text-muted-foreground">
          {helperText}
        </p>
      )}
    </div>
  );
}
