"use client";

import { useEffect, useMemo, useRef, useState } from "react";
import { Check, Loader2, Search, X } from "lucide-react";

/*
  Escolher vários (categorias, produtos, clientes): os escolhidos ficam em
  fichas que saem no X; a busca abre a lista logo abaixo, com a marca de
  quem já está dentro. Lista grande não pesa: só os primeiros 40 que batem
  com a busca aparecem. Com `buscar`, a lista vem do banco (clientes).
*/

export type ItemParaEscolher = { id: string; nome: string; detalhe?: string | null };

export function EscolhaDeVarios({
  rotulo,
  itens,
  escolhidos,
  aoMudar,
  placeholder = "Buscar",
  vazio = "Nada com esse nome.",
  buscar,
  nomesConhecidos,
  cor = "var(--ks-brand-600)",
}: {
  rotulo: string;
  itens?: ItemParaEscolher[];
  escolhidos: string[];
  aoMudar: (ids: string[]) => void;
  placeholder?: string;
  vazio?: string;
  /** Busca no banco (para listas que não cabem na tela, como clientes). */
  buscar?: (termo: string) => Promise<ItemParaEscolher[]>;
  /** Nomes dos escolhidos que não estão em `itens` (vindos do banco). */
  nomesConhecidos?: Record<string, string>;
  cor?: string;
}) {
  const [termo, setTermo] = useState("");
  const [aberto, setAberto] = useState(false);
  const [remotos, setRemotos] = useState<ItemParaEscolher[]>([]);
  const [buscando, setBuscando] = useState(false);
  const caixa = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (!aberto) return;
    const fora = (e: MouseEvent) => {
      if (caixa.current && !caixa.current.contains(e.target as Node)) setAberto(false);
    };
    document.addEventListener("mousedown", fora);
    return () => document.removeEventListener("mousedown", fora);
  }, [aberto]);

  useEffect(() => {
    if (!buscar || !aberto) return;
    let vivo = true;
    setBuscando(true);
    const espera = window.setTimeout(async () => {
      const achados = await buscar(termo.trim()).catch(() => []);
      if (!vivo) return;
      setRemotos(achados);
      setBuscando(false);
    }, 250);
    return () => {
      vivo = false;
      window.clearTimeout(espera);
    };
  }, [buscar, termo, aberto]);

  const nomes = useMemo(() => {
    const mapa: Record<string, string> = { ...(nomesConhecidos ?? {}) };
    for (const i of itens ?? []) mapa[i.id] = i.nome;
    for (const i of remotos) mapa[i.id] = i.nome;
    return mapa;
  }, [itens, remotos, nomesConhecidos]);

  const lista = useMemo(() => {
    if (buscar) return remotos;
    const t = termo.trim().toLowerCase();
    return (itens ?? []).filter((i) => !t || i.nome.toLowerCase().includes(t)).slice(0, 40);
  }, [buscar, remotos, itens, termo]);

  const alternar = (id: string) => {
    aoMudar(escolhidos.includes(id) ? escolhidos.filter((x) => x !== id) : [...escolhidos, id]);
  };

  return (
    <div ref={caixa} className="relative" data-lista-aberta={aberto ? "sim" : undefined}>
      {escolhidos.length ? (
        <div className="mb-2 flex flex-wrap gap-1.5">
          {escolhidos.map((id) => (
            <span
              key={id}
              className="inline-flex max-w-full items-center gap-1 rounded-full py-1 pl-2.5 pr-1 text-xs font-semibold text-white"
              style={{ backgroundColor: cor }}
            >
              <span className="truncate">{nomes[id] ?? "Item removido"}</span>
              <button
                type="button"
                onClick={() => alternar(id)}
                className="rounded-full p-0.5 text-white/80 transition hover:bg-white/20 hover:text-white"
                aria-label={`Tirar ${nomes[id] ?? "item"}`}
              >
                <X size={12} />
              </button>
            </span>
          ))}
        </div>
      ) : null}
      <div className="relative">
        <Search className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-[var(--ks-color-text-soft)]" />
        <input
          value={termo}
          onChange={(e) => {
            setTermo(e.target.value);
            setAberto(true);
          }}
          onFocus={() => setAberto(true)}
          onKeyDown={(e) => {
            if (e.key === "Escape") {
              e.stopPropagation();
              setAberto(false);
            }
          }}
          placeholder={placeholder}
          aria-label={rotulo}
          className="ks-field"
          style={{ paddingLeft: 36 }}
        />
      </div>
      {aberto ? (
        <div className="absolute inset-x-0 top-full z-20 mt-1.5 max-h-64 overflow-y-auto rounded-xl border border-[var(--ks-color-border-subtle)] bg-white p-1 shadow-[var(--ks-shadow-overlay)]">
          {buscando && !lista.length ? (
            <div className="flex items-center gap-2 px-3 py-3 text-xs text-[var(--ks-color-text-muted)]">
              <Loader2 className="h-3.5 w-3.5 animate-spin" /> Buscando...
            </div>
          ) : !lista.length ? (
            <p className="px-3 py-3 text-xs text-[var(--ks-color-text-muted)]">{vazio}</p>
          ) : (
            lista.map((item) => {
              const dentro = escolhidos.includes(item.id);
              return (
                <button
                  key={item.id}
                  type="button"
                  onClick={() => alternar(item.id)}
                  className={`flex w-full items-center gap-2.5 rounded-lg px-2.5 py-2 text-left transition-colors ${dentro ? "bg-[var(--ks-brand-50)]" : "hover:bg-[var(--ks-color-bg-hover)]"}`}
                >
                  <span
                    className={`flex h-[18px] w-[18px] shrink-0 items-center justify-center rounded-md border-2 ${dentro ? "border-[var(--ks-brand-600)] bg-[var(--ks-brand-600)] text-white" : "border-[var(--ks-color-border-strong)]"}`}
                  >
                    {dentro ? <Check size={12} strokeWidth={3} /> : null}
                  </span>
                  <span className="min-w-0">
                    <span className="block truncate text-sm font-semibold text-[var(--ks-color-text-primary)]">{item.nome}</span>
                    {item.detalhe ? <span className="block truncate text-[11px] text-[var(--ks-color-text-muted)]">{item.detalhe}</span> : null}
                  </span>
                </button>
              );
            })
          )}
        </div>
      ) : null}
    </div>
  );
}
