"use client";
import { useState, useRef, useEffect, useId } from "react";
import { motion, AnimatePresence } from "motion/react";
import { ChevronDown } from "@/components/ui/icons";
import { cn } from "@/lib/utils";

type Option = {
  value: string;
  label: string;
};

type SelectProps = {
  options: Option[];
  placeholder?: string;
  label?: string;
  labelClassName?: string;
  value?: string;
  onChange?: (value: string) => void;
  className?: string;
  search?: boolean;
};

const listVariants = {
  hidden: { opacity: 0, maxHeight: 0 },
  visible: {
    opacity: 1,
    maxHeight: "10.875rem",
    transition: {
      duration: 0.2,
      when: "beforeChildren",
      staggerChildren: 0.03,
    },
  },
  exit: {
    opacity: 0,
    maxHeight: 0,
    transition: { duration: 0.2 },
  },
};

const itemVariants = {
  hidden: { opacity: 0, y: -6 },
  visible: { opacity: 1, y: 0 },
};

const Select = ({
  options,
  placeholder = "Seleccionar...",
  label,
  labelClassName,
  value,
  onChange,
  className,
  search = false,
}: SelectProps) => {
  const [isOpen, setIsOpen] = useState(false);
  const [selected, setSelected] = useState<string | undefined>(value);
  const [searchTerm, setSearchTerm] = useState("");
  const [debounced, setDebounced] = useState("");

  const ref = useRef<HTMLDivElement>(null);
  const id = useId();

  useEffect(() => {
    const handler = setTimeout(() => setDebounced(searchTerm), 250);
    return () => clearTimeout(handler);
  }, [searchTerm]);

  useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      if (ref.current && !ref.current.contains(event.target as Node)) {
        setIsOpen(false);
        setSearchTerm("");
      }
    };
    document.addEventListener("mousedown", handleClickOutside);
    return () => document.removeEventListener("mousedown", handleClickOutside);
  }, []);

  const handleSelect = (option: Option) => {
    setSelected(option.value);
    onChange?.(option.value);
    setIsOpen(false);
    setSearchTerm("");
  };

  const selectedLabel = options.find((o) => o.value === selected)?.label || placeholder;

  const filteredOptions =
    search && debounced.length > 0
      ? options.filter((o) => o.label.toLowerCase().includes(debounced.toLowerCase()))
      : options;

  return (
    <div ref={ref} className={cn("relative w-full", className)}>
      {label && (
        <label
          htmlFor={id}
          className={cn("block mb-2 text-[1.125rem] lg:text-[1.375rem] font-medium text-contigo-negro", labelClassName)}
        >
          {label}
        </label>
      )}

      <button
        id={id}
        type="button"
        className={cn(
          "w-full flex items-center justify-between rounded-[0.375rem] text-contigo-negro border border-[#D9D9D9] bg-contigo-gris-claro px-3 py-2.5 text-[1rem]",
          "hover:border-gray-400 focus:outline-none focus:ring-2 focus:ring-contigo-verde"
        )}
        onClick={() => setIsOpen((prev) => !prev)}
        aria-expanded={isOpen}
        aria-haspopup="listbox"
      >
        <span className={cn("truncate", !selected && "text-inherit")}>{selectedLabel}</span>
        <motion.div animate={{ rotate: isOpen ? 180 : 0 }} transition={{ duration: 0.2 }}>
          <ChevronDown className="w-[0.875rem]" />
        </motion.div>
      </button>

      <AnimatePresence>
        {isOpen && (
          <motion.div
            initial={{ opacity: 0, y: -4 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -4 }}
            transition={{ duration: 0.15 }}
            className="absolute z-10 mt-1 w-full rounded-inherit border border-gray-200 scrollbar-contigo bg-contigo-gris-claro"
          >
            {search && (
              <div className="px-3 py-2 border-b border-gray-200 bg-white">
                <input
                  type="text"
                  placeholder="Buscar..."
                  value={searchTerm}
                  onChange={(e) => setSearchTerm(e.target.value)}
                  className="w-full px-2 py-1 rounded border border-gray-300 text-sm focus-visible:border-contigo-verde focus-visible:ring-contigo-verde outline-none focus-visible:ring-1"
                  autoFocus
                />
              </div>
            )}

            <motion.ul className="max-h-[10.875rem] overflow-auto" role="listbox">
              {filteredOptions.length === 0 && (
                <li className="px-4 py-2 text-sm text-gray-500">No se encontraron resultados</li>
              )}

              {filteredOptions.map((option) => (
                <motion.li
                  key={option.value}
                  whileHover={{ backgroundColor: "rgba(0,0,0,0.05)" }}
                  className={cn(
                    "cursor-pointer px-4 py-2 text-[0.9375rem]",
                    selected === option.value && "bg-contigo-verde text-white pointer-events-none"
                  )}
                  onClick={() => handleSelect(option)}
                  role="option"
                  aria-selected={selected === option.value}
                >
                  {option.label}
                </motion.li>
              ))}
            </motion.ul>
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  );
};

export default Select;
