"use client";

import { useEffect, useId, useRef, useState, type ReactNode } from "react";
import { Loader2, Search } from "lucide-react";

/**
 * O campo de busca com a lista logo abaixo (cliente, produto). Abre ao focar,
 * mostrando os recentes; filtra enquanto a pessoa digita; setas e Enter
 * escolhem sem tirar a mão do teclado.
 */
export function CaixaDeBusca<T extends { id: string }>({
  placeholder,
  buscar,
  renderizar,
  aoEscolher,
  vazio,
  titulo,
  rodape,
  desabilitado = false,
  limparAoEscolher = true,
  inputId,
}: {
  placeholder: string;
  buscar: (termo: string) => Promise<T[]>;
  renderizar: (item: T) => ReactNode;
  aoEscolher: (item: T) => void;
  vazio: (termo: string) => ReactNode;
  /** O rótulo acima da lista (ex.: "Clientes recentes" quando ainda não digitou). */
  titulo?: (termo: string) => string | null;
  rodape?: (fechar: () => void) => ReactNode;
  desabilitado?: boolean;
  limparAoEscolher?: boolean;
  inputId?: string;
}) {
  const [termo, setTermo] = useState("");
  const [aberta, setAberta] = useState(false);
  const [itens, setItens] = useState<T[]>([]);
  const [buscando, setBuscando] = useState(false);
  const [buscou, setBuscou] = useState(false);
  const [ativo, setAtivo] = useState(0);
  const caixa = useRef<HTMLDivElement>(null);
  const campo = useRef<HTMLInputElement>(null);
  const rodada = useRef(0);
  const buscarAtual = useRef(buscar);
  const listaId = useId();

  useEffect(() => {
    buscarAtual.current = buscar;
  }, [buscar]);

  useEffect(() => {
    if (!aberta) return;
    const minha = ++rodada.current;
    const relogio = setTimeout(
      async () => {
        setBuscando(true);
        try {
          const achados = await buscarAtual.current(termo.trim());
          if (minha !== rodada.current) return;
          setItens(achados);
          setAtivo(0);
          setBuscou(true);
        } catch {
          if (minha === rodada.current) {
            setItens([]);
            setBuscou(true);
          }
        } finally {
          if (minha === rodada.current) setBuscando(false);
        }
      },
      termo.trim() ? 280 : 0
    );
    return () => clearTimeout(relogio);
  }, [termo, aberta]);

  useEffect(() => {
    if (!aberta) return;
    const fechar = (evento: MouseEvent) => {
      if (caixa.current && !caixa.current.contains(evento.target as Node)) setAberta(false);
    };
    window.addEventListener("mousedown", fechar);
    return () => window.removeEventListener("mousedown", fechar);
  }, [aberta]);

  const escolher = (item: T) => {
    aoEscolher(item);
    if (limparAoEscolher) setTermo("");
    setAberta(false);
  };

  const rotulo = titulo?.(termo.trim()) ?? null;

  return (
    <div ref={caixa} className="relative">
      <Search className="pointer-events-none absolute left-4 top-1/2 h-[18px] w-[18px] -translate-y-1/2 text-[var(--ks-color-text-soft)]" />
      <input
        ref={campo}
        id={inputId}
        value={termo}
        disabled={desabilitado}
        onChange={(e) => {
          setTermo(e.target.value);
          setAberta(true);
        }}
        onFocus={() => setAberta(true)}
        onKeyDown={(e) => {
          if (e.key === "ArrowDown") {
            e.preventDefault();
            setAberta(true);
            setAtivo((atual) => Math.min(itens.length - 1, atual + 1));
          } else if (e.key === "ArrowUp") {
            e.preventDefault();
            setAtivo((atual) => Math.max(0, atual - 1));
          } else if (e.key === "Enter") {
            if (aberta && itens[ativo]) {
              e.preventDefault();
              escolher(itens[ativo]);
            }
          } else if (e.key === "Escape") {
            setAberta(false);
          }
        }}
        placeholder={placeholder}
        autoComplete="off"
        role="combobox"
        aria-expanded={aberta}
        aria-controls={listaId}
        className="ks-field"
        style={{ paddingLeft: "2.75rem", height: "3rem", fontSize: "15px" }}
      />
      {buscando ? <Loader2 className="absolute right-4 top-1/2 h-4 w-4 -translate-y-1/2 animate-spin text-[var(--ks-color-primary)]" /> : null}

      {aberta && !desabilitado ? (
        <div
          id={listaId}
          role="listbox"
          className="absolute left-0 right-0 top-[calc(100%+6px)] z-40 overflow-hidden rounded-2xl bg-[var(--ks-color-bg-elevated)] shadow-[0_24px_60px_rgba(26,26,43,0.22)] ring-1 ring-[var(--ks-color-border-subtle)]"
        >
          {rotulo ? (
            <p className="px-4 pb-1 pt-3 text-[11px] font-bold uppercase tracking-[0.14em] text-[var(--ks-color-text-soft)]">{rotulo}</p>
          ) : null}
          <ul className="max-h-[340px] overflow-y-auto py-1">
            {itens.map((item, indice) => (
              <li key={item.id} role="option" aria-selected={indice === ativo}>
                <button
                  type="button"
                  onMouseEnter={() => setAtivo(indice)}
                  onClick={() => escolher(item)}
                  className={`flex w-full items-center gap-3 px-4 py-2.5 text-left transition-colors ${
                    indice === ativo ? "bg-[var(--ks-color-bg-hover)]" : ""
                  }`}
                >
                  {renderizar(item)}
                </button>
              </li>
            ))}
          </ul>
          {buscou && !buscando && itens.length === 0 ? <div className="px-4 pb-4 pt-2 text-sm text-[var(--ks-color-text-muted)]">{vazio(termo.trim())}</div> : null}
          {rodape ? <div className="border-t border-[var(--ks-color-border-subtle)] px-2 py-2">{rodape(() => setAberta(false))}</div> : null}
        </div>
      ) : null}
    </div>
  );
}
