"use client";

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

import { descricaoDoCodigo, procurarCodigo, type TipoDeTabela } from "@/lib/fiscal/tabelas";

/**
 * Campo de código fiscal com a tabela junto.
 *
 * O contador digita o número que já sabe; quem não sabe clica na lupa e procura
 * por palavra ("revenda", "brinde", "adesivo"). Escolhido o código, a descrição
 * aparece embaixo — é assim que a pessoa confere que marcou o certo sem decorar
 * tabela nenhuma. O campo nunca trava no que está na lista: código fora dela
 * continua sendo aceito, porque a tabela oficial é maior do que cabe aqui.
 */
export function CampoDeCodigo({
  tipo,
  valor,
  aoMudar,
  placeholder,
  maximoDeDigitos = 6,
  somenteDigitos = true,
  zerosNaFrente = false,
  id,
  desabilitado = false,
}: {
  tipo: TipoDeTabela;
  valor: string;
  aoMudar: (codigo: string) => void;
  placeholder?: string;
  maximoDeDigitos?: number;
  somenteDigitos?: boolean;
  /* Código que a tela mostra já completo com zeros (000001): o que se digita
     entra no fim e passa do tamanho, então valem os últimos números. Cortando
     pelo começo, "000001" virava 000000 e o 1 nunca entrava. */
  zerosNaFrente?: boolean;
  id?: string;
  desabilitado?: boolean;
}) {
  const [aberta, setAberta] = useState(false);
  const [termo, setTermo] = useState("");
  const caixa = useRef<HTMLDivElement>(null);

  const resultados = useMemo(() => procurarCodigo(tipo, termo), [tipo, termo]);
  const descricao = descricaoDoCodigo(tipo, valor);

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

  const limpar = (bruto: string) => {
    const texto = somenteDigitos ? bruto.replace(/\D/g, "") : bruto.replace(/[^\d.]/g, "");
    return zerosNaFrente ? texto.slice(-maximoDeDigitos) : texto.slice(0, maximoDeDigitos);
  };

  return (
    <div ref={caixa} className="relative">
      <div className="flex items-stretch gap-2">
        <input
          id={id}
          value={valor}
          onChange={(e) => aoMudar(limpar(e.target.value))}
          placeholder={placeholder}
          inputMode={somenteDigitos ? "numeric" : "text"}
          disabled={desabilitado}
          className="ks-field tabular-nums"
        />
        <button
          type="button"
          onClick={() => {
            setTermo("");
            setAberta((antes) => !antes);
          }}
          disabled={desabilitado}
          title="Procurar na tabela"
          aria-label="Procurar na tabela"
          className="flex h-[42px] w-[42px] shrink-0 items-center justify-center rounded-xl border border-[var(--ks-color-border)] text-[var(--ks-color-text-muted)] transition-colors hover:border-[var(--ks-color-primary)] hover:text-[var(--ks-color-primary)] disabled:opacity-50"
        >
          <Search size={16} />
        </button>
      </div>

      {descricao && !aberta ? (
        <p className="mt-1 text-xs leading-4 text-[var(--ks-color-text-muted)]">{descricao}</p>
      ) : null}

      {aberta ? (
        <div className="absolute left-0 right-0 top-[calc(100%+6px)] z-30 overflow-hidden rounded-2xl border border-[var(--ks-color-border)] bg-[var(--ks-color-bg-elevated)] shadow-[0_18px_40px_rgba(26,26,43,0.18)]">
          <div className="border-b border-[var(--ks-color-border)] p-2">
            <input
              autoFocus
              value={termo}
              onChange={(e) => setTermo(e.target.value)}
              placeholder="Procure pelo número ou pelo nome"
              className="ks-field h-9 text-sm"
            />
          </div>
          <ul className="max-h-64 overflow-y-auto">
            {resultados.length === 0 ? (
              <li className="px-3 py-3 text-xs text-[var(--ks-color-text-muted)]">
                Nada com esse nome na lista. Digite o código direto no campo — ele continua valendo.
              </li>
            ) : (
              resultados.map((item) => (
                <li key={item.codigo}>
                  <button
                    type="button"
                    onClick={() => {
                      aoMudar(item.codigo);
                      setAberta(false);
                    }}
                    className="flex w-full flex-col gap-0.5 px-3 py-2 text-left transition-colors hover:bg-[var(--ks-color-bg-subtle)]"
                  >
                    <span className="text-sm font-bold tabular-nums text-[var(--ks-color-text-primary)]">{item.codigo}</span>
                    <span className="text-xs leading-4 text-[var(--ks-color-text-secondary)]">{item.descricao}</span>
                    {item.ajuda ? <span className="text-[11px] leading-4 text-[var(--ks-color-text-soft)]">{item.ajuda}</span> : null}
                  </button>
                </li>
              ))
            )}
          </ul>
        </div>
      ) : null}
    </div>
  );
}
