import { useEffect, useMemo, useRef, useState } from "react";
import type { KeyboardEvent } from "react";
import type { Locale, LocaleOption } from "@/hooks/useI18n";

type Props = {
  locale: Locale;
  onChange: (code: Locale) => void;
  options: LocaleOption[];
  label: string;
  searchPlaceholder: string;
};

export function LocaleSelector({ locale, onChange, options, label, searchPlaceholder }: Props) {
  const dropdownRef = useRef<HTMLDivElement | null>(null);
  const searchRef = useRef<HTMLInputElement | null>(null);
  const [open, setOpen] = useState(false);
  const [search, setSearch] = useState("");
  const [focusedIndex, setFocusedIndex] = useState(-1);

  const selected = useMemo(
    () => options.find((opt) => opt.code === locale) || options[0],
    [locale, options]
  );

  const filtered = useMemo(() => {
    const term = search.trim().toLowerCase();
    return term ? options.filter((opt) => opt.name.toLowerCase().includes(term)) : options;
  }, [options, search]);

  useEffect(() => {
    if (!open) return;
    const clickHandler = (e: MouseEvent) => {
      if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) {
        setOpen(false);
        setSearch("");
        setFocusedIndex(-1);
      }
    };
    document.addEventListener("click", clickHandler);
    setTimeout(() => searchRef.current?.focus(), 0);
    return () => document.removeEventListener("click", clickHandler);
  }, [open]);

  const toggle = () => setOpen((prev) => !prev);
  const close = () => {
    setOpen(false);
    setSearch("");
    setFocusedIndex(-1);
  };

  const select = (opt: LocaleOption) => {
    onChange(opt.code);
    close();
  };

  const onKeyDownList = (e: KeyboardEvent<HTMLUListElement>) => {
    if (!open) return;
    const list = filtered;
    if (!list.length) return;
    if (e.key === "ArrowDown") {
      e.preventDefault();
      setFocusedIndex((prev) => {
        const next = (prev + 1) % list.length;
        scrollIntoView(next);
        return next;
      });
    } else if (e.key === "ArrowUp") {
      e.preventDefault();
      setFocusedIndex((prev) => {
        const next = (prev - 1 + list.length) % list.length;
        scrollIntoView(next);
        return next;
      });
    } else if (e.key === "Enter" && focusedIndex >= 0) {
      e.preventDefault();
      select(list[focusedIndex]);
    } else if (e.key === "Escape") {
      e.preventDefault();
      close();
    }
  };

  const scrollIntoView = (index: number) => {
    requestAnimationFrame(() => {
      const items = dropdownRef.current?.querySelectorAll(".locale-panel-item");
      const el = items?.[index] as HTMLElement | undefined;
      el?.scrollIntoView({ block: "nearest" });
    });
  };

  const handleItemKeyDown = (e: KeyboardEvent<HTMLLIElement>, opt: LocaleOption) => {
    if (e.key === "Enter" || e.key === " ") {
      e.preventDefault();
      select(opt);
    }
  };

  return (
    <div ref={dropdownRef} className="locale-dropdown" tabIndex={-1} role="group">
      <p className="locale-label">{label}</p>
      <button
        type="button"
        className="locale-toggle"
        aria-expanded={open}
        aria-haspopup="menu"
        onClick={toggle}
      >
        <span className="locale-flag" aria-hidden>
          {selected?.emoji}
        </span>
        <span className="locale-name">{selected?.name}</span>
        <svg
          className={`locale-arrow ${open ? "open" : ""}`}
          xmlns="http://www.w3.org/2000/svg"
          fill="none"
          viewBox="0 0 24 24"
          stroke="currentColor"
        >
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 9l-7 7-7-7" />
        </svg>
      </button>

      {open && (
        <div className="locale-panel" role="menu" tabIndex={-1}>
          <div className="locale-panel-search">
            <input
              ref={searchRef}
              value={search}
              onChange={(e) => setSearch(e.target.value)}
              type="text"
              placeholder={searchPlaceholder}
            />
          </div>
          <ul className="locale-panel-list" role="menu" tabIndex={0} onKeyDown={onKeyDownList}>
            {filtered.map((opt, index) => (
              <li
                key={opt.code}
                className={`locale-panel-item ${index === focusedIndex ? "focused" : ""}`}
                role="menuitem"
                tabIndex={0}
                onClick={() => select(opt)}
                onKeyDown={(e) => handleItemKeyDown(e, opt)}
                onMouseEnter={() => setFocusedIndex(index)}
              >
                <span className="locale-item-flag" aria-hidden>
                  {opt.emoji}
                </span>
                <span className="locale-item-label">{opt.name}</span>
              </li>
            ))}
            {filtered.length === 0 && <li className="locale-no-results">No languages found.</li>}
          </ul>
        </div>
      )}
    </div>
  );
}
