"use client";

/*
 * O catálogo da XBZ dentro da Ktalogu.
 *
 * A busca lê a cópia do catálogo guardada no servidor (baixada inteira, com
 * preço e estoque, como o desenvolvedor da API recomendou), então digitar não
 * gasta nenhuma das 24 consultas do dia. Cada linha é um modelo com todas as
 * cores; o detalhe mostra tudo o que a XBZ informa, e o cadastro leva para o
 * catálogo da empresa o que dá para levar: cores como variação, fotos, custo,
 * peso, medidas, NCM e o pedido mínimo.
 */

import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { createPortal } from "react-dom";
import Link from "next/link";
import { toast } from "sonner";
import {
  Check,
  ExternalLink,
  ImageIcon,
  Loader2,
  PackagePlus,
  PackageSearch,
  RefreshCcw,
  Search,
  ShoppingCart,
  X,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Aviso } from "@/components/ui/aviso";
import { EntradaDecimal } from "@/components/ui/campo-decimal";
import { nomeParaLoja, type CorDoCatalogo, type ModeloDoCatalogo } from "@/lib/xbz/xbz.catalogo";
import {
  importXbzModel,
  refreshXbzCatalog,
  searchXbzProducts,
  xbzCatalogStatus,
  type ResultadoDoCadastro,
  type SituacaoDoCatalogo,
} from "@/lib/xbz/xbz.client";
import { dia, emReais, faixaDePreco, horaDe, medidas, ncmLegivel, peso, quantidade, tomDaCor } from "./formato";

const MARGEM_SUGERIDA = 100;

function Foto({ src, alt, className }: { src: string | null; alt: string; className: string }) {
  const [quebrou, setQuebrou] = useState(false);
  if (!src || quebrou) {
    return (
      <span className={`flex items-center justify-center bg-slate-50 text-slate-300 ${className}`}>
        <ImageIcon className="h-5 w-5" />
      </span>
    );
  }
  // eslint-disable-next-line @next/next/no-img-element
  return <img src={src} alt={alt} loading="lazy" onError={() => setQuebrou(true)} className={`bg-white object-contain ${className}`} />;
}

function Bolinha({ rotulo, tamanho = "h-3.5 w-3.5" }: { rotulo: string; tamanho?: string }) {
  return (
    <span
      title={rotulo}
      className={`inline-block shrink-0 rounded-full border border-black/10 ${tamanho}`}
      style={{ background: tomDaCor(rotulo) }}
    />
  );
}

function Selo({ children, tom = "neutro" }: { children: React.ReactNode; tom?: "neutro" | "bom" | "ruim" | "marca" }) {
  const cores = {
    neutro: "bg-slate-100 text-slate-600",
    bom: "bg-emerald-50 text-emerald-700",
    ruim: "bg-rose-50 text-rose-600",
    marca: "bg-[var(--ks-color-primary)]/10 text-[var(--ks-color-primary)]",
  } as const;
  return <span className={`inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[11px] font-semibold ${cores[tom]}`}>{children}</span>;
}

function regraDeCompra(modelo: { pedidoMinimo: number | null; multiploDe: number | null }) {
  if (modelo.multiploDe && modelo.pedidoMinimo && modelo.multiploDe !== modelo.pedidoMinimo) {
    return `mínimo de ${quantidade(modelo.pedidoMinimo)}, em múltiplos de ${quantidade(modelo.multiploDe)}`;
  }
  if (modelo.multiploDe) return `só em múltiplos de ${quantidade(modelo.multiploDe)}`;
  if (modelo.pedidoMinimo) return `pedido mínimo de ${quantidade(modelo.pedidoMinimo)}`;
  return null;
}

export function CatalogoDaXbz({
  catalogoInicial,
  margemInicial,
  conectado,
  aoComprar,
  aoMudarCatalogo,
}: {
  catalogoInicial: SituacaoDoCatalogo | null;
  margemInicial: number | null;
  conectado: boolean;
  aoComprar: (modelo: ModeloDoCatalogo, cor: CorDoCatalogo) => void;
  aoMudarCatalogo?: (catalogo: SituacaoDoCatalogo) => void;
}) {
  const [busca, setBusca] = useState("");
  const [buscaFeita, setBuscaFeita] = useState("");
  const [carregando, setCarregando] = useState(false);
  const [erro, setErro] = useState<string | null>(null);
  const [modelos, setModelos] = useState<ModeloDoCatalogo[]>([]);
  const [catalogo, setCatalogo] = useState<SituacaoDoCatalogo | null>(catalogoInicial);
  const [atualizandoAgora, setAtualizandoAgora] = useState(false);
  const [aberto, setAberto] = useState<ModeloDoCatalogo | null>(null);
  const [corVista, setCorVista] = useState<string | null>(null);
  const [cadastro, setCadastro] = useState<{ modelo: ModeloDoCatalogo; cores: Set<string>; margem: number; nome: string } | null>(null);
  const [cadastrando, setCadastrando] = useState(false);
  const [cadastrado, setCadastrado] = useState<ResultadoDoCadastro | null>(null);
  const ultimaBusca = useRef(0);

  useEffect(() => setCatalogo(catalogoInicial), [catalogoInicial]);

  const mudarCatalogo = useCallback(
    (novo: SituacaoDoCatalogo) => {
      setCatalogo(novo);
      aoMudarCatalogo?.(novo);
    },
    [aoMudarCatalogo]
  );

  const buscar = useCallback(
    async (texto: string) => {
      const termo = texto.trim();
      setBuscaFeita(termo);
      if (termo.length < 2) {
        setModelos([]);
        setErro(null);
        return;
      }
      const esta = ++ultimaBusca.current;
      setCarregando(true);
      setErro(null);
      try {
        const resposta = await searchXbzProducts(termo);
        if (esta !== ultimaBusca.current) return;
        setModelos(resposta.modelos ?? []);
        if (resposta.catalogo) mudarCatalogo(resposta.catalogo);
      } catch (falha) {
        if (esta !== ultimaBusca.current) return;
        setErro(falha instanceof Error ? falha.message : "Não foi possível buscar agora.");
        setModelos([]);
      } finally {
        if (esta === ultimaBusca.current) setCarregando(false);
      }
    },
    [mudarCatalogo]
  );

  /* Digitar busca sozinho: a cópia é daqui, não custa consulta da XBZ. */
  useEffect(() => {
    const espera = window.setTimeout(() => void buscar(busca), 350);
    return () => window.clearTimeout(espera);
  }, [busca, buscar]);

  /* Enquanto a XBZ manda o catálogo, pergunta de tempos em tempos; quando
     chega, refaz a busca com os preços e estoques novos. */
  const atualizando = Boolean(catalogo?.atualizando);
  useEffect(() => {
    if (!atualizando) return;
    const relogio = window.setInterval(async () => {
      try {
        const { catalogo: novo } = await xbzCatalogStatus();
        mudarCatalogo(novo);
        if (!novo.atualizando) {
          if (novo.erro) toast.error(novo.erro);
          else toast.success(`Catálogo da XBZ atualizado: ${quantidade(novo.itens)} itens.`);
          void buscar(buscaFeita);
        }
      } catch {
        /* A próxima volta tenta de novo. */
      }
    }, 4000);
    return () => window.clearInterval(relogio);
  }, [atualizando, buscaFeita, buscar, mudarCatalogo]);

  async function atualizarAgora() {
    setAtualizandoAgora(true);
    try {
      const resposta = await refreshXbzCatalog();
      mudarCatalogo(resposta.catalogo);
      toast.success("Baixando o catálogo da XBZ. Leva uns 30 segundos.");
    } catch (falha) {
      toast.error(falha instanceof Error ? falha.message : "Não foi possível atualizar agora.");
    } finally {
      setAtualizandoAgora(false);
    }
  }

  function abrir(modelo: ModeloDoCatalogo) {
    setAberto(modelo);
    setCorVista([...modelo.cores].sort((a, b) => b.estoque - a.estoque)[0]?.codigoXbz ?? null);
  }

  function prepararCadastro(modelo: ModeloDoCatalogo) {
    setCadastrado(null);
    setCadastro({
      modelo,
      cores: new Set(modelo.cores.map((cor) => cor.codigoXbz)),
      margem: margemInicial ?? MARGEM_SUGERIDA,
      nome: nomeParaLoja(modelo.nome),
    });
  }

  async function cadastrar() {
    if (!cadastro || !cadastro.cores.size) return;
    setCadastrando(true);
    try {
      const { product } = await importXbzModel({
        modelo: cadastro.modelo.codigo,
        cores: [...cadastro.cores],
        margem: cadastro.margem,
        nome: cadastro.nome,
      });
      setCadastrado(product);
      if (product.jaExistia) toast.message("Esse produto já está no seu catálogo.");
      else toast.success(`"${product.nome}" cadastrado no catálogo.`);
      for (const aviso of product.avisos ?? []) toast.message(aviso);
    } catch (falha) {
      toast.error(falha instanceof Error ? falha.message : "Não foi possível cadastrar agora.");
    } finally {
      setCadastrando(false);
    }
  }

  const corDoDetalhe = useMemo(
    () => aberto?.cores.find((cor) => cor.codigoXbz === corVista) ?? aberto?.cores[0] ?? null,
    [aberto, corVista]
  );

  const custoDoCadastro = useMemo(() => {
    if (!cadastro) return null;
    const precos = cadastro.modelo.cores
      .filter((cor) => cadastro.cores.has(cor.codigoXbz) && cor.preco !== null)
      .map((cor) => cor.preco as number);
    return precos.length ? Math.min(...precos) : null;
  }, [cadastro]);

  const semCatalogo = !catalogo?.atualizadoEm;

  return (
    <div className="ks-surface overflow-hidden rounded-xl border border-[var(--ks-color-border-subtle)] shadow-sm">
      <div className="flex flex-wrap items-center justify-between gap-x-4 gap-y-3 border-b border-[var(--ks-color-border-subtle)] bg-[var(--ks-color-bg-subtle)]/30 p-4">
        <div className="min-w-[220px] max-w-md flex-1">
          <Input
            icon={<Search className="h-4 w-4" />}
            placeholder="Caneca, squeeze azul, 06520..."
            value={busca}
            onChange={(evento) => setBusca(evento.target.value)}
            disabled={!conectado}
          />
        </div>
        <div className="flex flex-wrap items-center gap-4 text-xs font-medium text-slate-500">
          {catalogo?.atualizadoEm ? (
            <>
              <span className="flex items-center gap-1.5">
                <span className="h-1.5 w-1.5 rounded-full bg-[var(--ks-color-primary)]" />
                {quantidade(catalogo.modelos)} produtos
              </span>
              <span className="flex items-center gap-1.5">
                <span className="h-1.5 w-1.5 rounded-full bg-emerald-500" />
                {quantidade(catalogo.itens)} itens com cor
              </span>
              <span className="flex items-center gap-1.5">
                <span className="h-1.5 w-1.5 rounded-full bg-slate-300" />
                preços e estoque de {horaDe(catalogo.atualizadoEm)}
              </span>
            </>
          ) : null}
          <Button
            variant="outline"
            size="sm"
            onClick={() => void atualizarAgora()}
            disabled={!conectado || atualizando || atualizandoAgora || Boolean(catalogo?.podeAtualizarEm)}
            title={
              catalogo?.podeAtualizarEm
                ? `Atualizado há pouco. Volta a valer ${horaDe(catalogo.podeAtualizarEm)}.`
                : "Baixa de novo o catálogo inteiro da XBZ (usa uma das 24 consultas do dia)"
            }
            icon={atualizando || atualizandoAgora ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : <RefreshCcw className="h-3.5 w-3.5" />}
          >
            {atualizando ? "Atualizando" : "Atualizar catálogo"}
          </Button>
        </div>
      </div>

      {atualizando ? (
        <div className="flex items-center gap-2 border-b border-[var(--ks-color-border-subtle)] px-6 py-3 text-sm text-[var(--ks-color-text-soft)]">
          <Loader2 className="h-4 w-4 animate-spin text-[var(--ks-color-primary)]" />
          {semCatalogo
            ? "Baixando o catálogo da XBZ pela primeira vez: são quase 12 mil itens com preço e estoque. Leva uns 30 segundos."
            : "Atualizando preços e estoque com a XBZ. Enquanto isso, a busca usa a cópia anterior."}
        </div>
      ) : null}

      {catalogo?.erro && !atualizando ? (
        <div className="p-4">
          <Aviso
            tom="ruim"
            titulo="A XBZ não mandou o catálogo"
            acao={
              <Button size="sm" variant="outline" onClick={() => void atualizarAgora()} disabled={atualizandoAgora || Boolean(catalogo.podeAtualizarEm)}>
                Tentar de novo
              </Button>
            }
          >
            {catalogo.erro}
          </Aviso>
        </div>
      ) : null}

      {!conectado ? (
        <Vazio titulo="Ligue a sua conta da XBZ primeiro" texto="Na aba Configuração, salve o CNPJ e o token que a XBZ mandou para você." />
      ) : erro ? (
        <div className="p-4">
          <Aviso tom="ruim" titulo="A busca não deu certo">
            {erro}
          </Aviso>
        </div>
      ) : buscaFeita.length < 2 ? (
        <Vazio
          titulo="Procure no catálogo da XBZ"
          texto="Pelo nome, pela cor ou pelo código: caneca, squeeze azul, 06520. A busca é feita aqui, sem gastar as consultas do dia."
        />
      ) : carregando && !modelos.length ? (
        <div className="flex justify-center py-16">
          <Loader2 className="h-7 w-7 animate-spin text-[var(--ks-color-primary)]" />
        </div>
      ) : !modelos.length ? (
        <Vazio
          titulo={semCatalogo ? "O catálogo ainda está chegando" : "Nada com essas palavras"}
          texto={semCatalogo ? "Assim que a XBZ mandar a lista, a busca aparece aqui." : "Tente menos palavras ou o código do produto."}
        />
      ) : (
        <div className="overflow-x-auto">
          <div className="min-w-[700px]">
            <div className="grid grid-cols-[minmax(0,1fr)_128px_120px_110px_84px] gap-3 px-6 py-3 text-[10px] font-semibold uppercase tracking-[0.14em] text-slate-400">
              <span>Produto</span>
              <span>Cores</span>
              <span>Preço da XBZ</span>
              <span>Estoque</span>
              <span />
            </div>
            {modelos.map((modelo) => {
              const regra = regraDeCompra(modelo);
              const detalhes = [`Cód. ${modelo.codigo}`, peso(Math.max(0, ...modelo.cores.map((cor) => cor.pesoG ?? 0)) || null), regra].filter(Boolean);
              return (
                <div
                  key={modelo.codigo}
                  onClick={() => abrir(modelo)}
                  title="Ver tudo o que a XBZ informa"
                  className="grid cursor-pointer grid-cols-[minmax(0,1fr)_128px_120px_110px_84px] items-center gap-3 border-t border-slate-100/60 px-6 py-3 transition-colors hover:bg-[var(--ks-color-bg-subtle)]/50"
                >
                  <div className="flex min-w-0 items-center gap-3">
                    <Foto src={modelo.imagem} alt="" className="h-11 w-11 shrink-0 rounded-xl border border-slate-100" />
                    <div className="min-w-0">
                      <p className="line-clamp-2 text-sm font-semibold leading-5 text-[var(--ks-color-text-primary)]">{nomeParaLoja(modelo.nome)}</p>
                      <p className="truncate text-[11px] text-slate-400">{detalhes.join(" · ")}</p>
                    </div>
                  </div>
                  <div className="flex items-center gap-1">
                    {modelo.cores.slice(0, 6).map((cor) => (
                      <Bolinha key={cor.codigoXbz} rotulo={cor.cor} />
                    ))}
                    {modelo.cores.length > 6 ? <span className="ml-0.5 text-[11px] font-semibold text-slate-400">+{modelo.cores.length - 6}</span> : null}
                  </div>
                  <div className="text-sm font-bold tabular-nums text-[var(--ks-color-text-primary)]">
                    {faixaDePreco(modelo.precoMinimo, modelo.precoMaximo)}
                  </div>
                  <div>
                    {modelo.estoque > 0 ? (
                      <>
                        <span className="text-base font-bold tabular-nums text-[var(--ks-color-text-primary)]">{quantidade(modelo.estoque)}</span>
                        <span className="ml-1 text-xs text-slate-400">un</span>
                      </>
                    ) : (
                      <Selo tom="ruim">{modelo.reposicaoPrevista ? `Chega ${dia(modelo.reposicaoPrevista)}` : "Sem estoque"}</Selo>
                    )}
                    {modelo.pontaDeEstoque ? (
                      <div className="mt-0.5">
                        <Selo tom="marca">Ponta de estoque</Selo>
                      </div>
                    ) : null}
                  </div>
                  <div className="flex items-center justify-end gap-1">
                    <Button
                      size="icon"
                      variant="ghost"
                      title="Cadastrar no meu catálogo"
                      onClick={(evento) => {
                        evento.stopPropagation();
                        prepararCadastro(modelo);
                      }}
                    >
                      <PackagePlus className="h-4 w-4 text-[var(--ks-color-primary)]" />
                    </Button>
                    <Button
                      size="icon"
                      variant="ghost"
                      title="Comprar da XBZ"
                      onClick={(evento) => {
                        evento.stopPropagation();
                        const cor = [...modelo.cores].sort((a, b) => b.estoque - a.estoque)[0];
                        if (cor) aoComprar(modelo, cor);
                      }}
                    >
                      <ShoppingCart className="h-4 w-4 text-emerald-600" />
                    </Button>
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      )}

      {aberto && corDoDetalhe ? (
        <Janela aoFechar={() => setAberto(null)} largura="max-w-4xl">
          <div className="flex items-start justify-between gap-4 px-6 pb-3 pt-5">
            <div className="min-w-0">
              <h3 className="text-lg font-bold text-[var(--ks-color-text-primary)]">{nomeParaLoja(aberto.nome)}</h3>
              <p className="text-sm text-[var(--ks-color-text-soft)]">
                Código {aberto.codigo} na XBZ · {aberto.cores.length} {aberto.cores.length === 1 ? "cor" : "cores"}
                {aberto.ncm ? ` · NCM ${ncmLegivel(aberto.ncm)}` : ""}
              </p>
            </div>
            <BotaoFechar aoFechar={() => setAberto(null)} />
          </div>

          <div className="grid max-h-[70vh] gap-6 overflow-y-auto px-6 pb-5 md:grid-cols-[280px_minmax(0,1fr)]">
            <div className="space-y-3">
              <Foto src={corDoDetalhe.imagem} alt={corDoDetalhe.cor} className="aspect-square w-full rounded-2xl border border-slate-100 p-3" />
              <div className="flex flex-wrap gap-1.5">
                {aberto.cores.map((cor) => (
                  <button
                    key={cor.codigoXbz}
                    type="button"
                    onClick={() => setCorVista(cor.codigoXbz)}
                    className={`flex items-center gap-1.5 rounded-full border px-2.5 py-1 text-xs font-medium transition-colors ${
                      cor.codigoXbz === corDoDetalhe.codigoXbz
                        ? "border-[var(--ks-color-primary)] bg-[var(--ks-color-primary)]/5 text-[var(--ks-color-primary)]"
                        : "border-slate-200 text-slate-600 hover:border-slate-300"
                    }`}
                  >
                    <Bolinha rotulo={cor.cor} tamanho="h-3 w-3" />
                    {cor.cor}
                  </button>
                ))}
              </div>
            </div>

            <div className="min-w-0 space-y-4">
              <div className="grid grid-cols-2 gap-x-6 gap-y-3 text-sm sm:grid-cols-3">
                <Dado rotulo="Preço da XBZ (seu custo)" valor={emReais(corDoDetalhe.preco)} forte />
                <Dado
                  rotulo="Estoque desta cor"
                  valor={`${quantidade(corDoDetalhe.estoque)} un`}
                  detalhe={corDoDetalhe.estoquePrincipal !== corDoDetalhe.estoque ? `${quantidade(corDoDetalhe.estoquePrincipal)} no depósito principal` : null}
                  forte
                />
                <Dado rotulo="Reposição prevista" valor={dia(corDoDetalhe.reposicaoPrevista) ?? "Sem previsão"} />
                <Dado rotulo="Peso" valor={peso(corDoDetalhe.pesoG) ?? "Não informado"} />
                <Dado rotulo="Medidas (A × L × P)" valor={medidas(corDoDetalhe.alturaCm, corDoDetalhe.larguraCm, corDoDetalhe.profundidadeCm) ?? "Não informadas"} />
                <Dado rotulo="Compra mínima" valor={regraDeCompra(corDoDetalhe) ?? "Sem mínimo informado"} />
                <Dado rotulo="Código desta cor" valor={`${corDoDetalhe.codigoComposto} · ${corDoDetalhe.codigoXbz}`} />
                <Dado rotulo="NCM" valor={ncmLegivel(corDoDetalhe.ncm) ?? "—"} />
                <Dado rotulo="Estoque de todas as cores" valor={`${quantidade(aberto.estoque)} un`} />
              </div>

              {corDoDetalhe.confiabilidade ? (
                <p className="flex items-start gap-2 text-xs text-[var(--ks-color-text-soft)]">
                  <Check className={`mt-0.5 h-3.5 w-3.5 shrink-0 ${corDoDetalhe.estoqueConfiavel ? "text-emerald-500" : "text-slate-400"}`} />
                  {corDoDetalhe.confiabilidade}
                </p>
              ) : null}

              {aberto.descricao ? <p className="text-sm leading-6 text-[var(--ks-color-text-secondary)]">{aberto.descricao}</p> : null}

              {aberto.cores.length > 1 ? (
                <div className="overflow-hidden rounded-xl border border-[var(--ks-color-border-subtle)]">
                  <div className="grid grid-cols-[minmax(0,1fr)_96px_96px_110px] gap-2 px-4 py-2 text-[10px] font-semibold uppercase tracking-[0.14em] text-slate-400">
                    <span>Cor</span>
                    <span>Preço</span>
                    <span>Estoque</span>
                    <span>Reposição</span>
                  </div>
                  {aberto.cores.map((cor) => (
                    <button
                      key={cor.codigoXbz}
                      type="button"
                      onClick={() => setCorVista(cor.codigoXbz)}
                      className="grid w-full grid-cols-[minmax(0,1fr)_96px_96px_110px] items-center gap-2 border-t border-slate-100/60 px-4 py-2 text-left text-sm hover:bg-[var(--ks-color-bg-subtle)]/50"
                    >
                      <span className="flex min-w-0 items-center gap-2">
                        <Bolinha rotulo={cor.cor} />
                        <span className="truncate font-medium text-[var(--ks-color-text-primary)]">{cor.cor}</span>
                        <span className="truncate text-[11px] text-slate-400">{cor.codigoComposto}</span>
                      </span>
                      <span className="tabular-nums">{emReais(cor.preco)}</span>
                      <span className={`tabular-nums ${cor.estoque > 0 ? "" : "text-rose-600"}`}>{quantidade(cor.estoque)}</span>
                      <span className="text-[var(--ks-color-text-soft)]">{dia(cor.reposicaoPrevista) ?? "—"}</span>
                    </button>
                  ))}
                </div>
              ) : null}

              {aberto.siteLink ? (
                <a
                  href={aberto.siteLink}
                  target="_blank"
                  rel="noreferrer"
                  className="inline-flex items-center gap-1.5 text-sm font-semibold text-[var(--ks-color-primary)] hover:underline"
                >
                  Ver no site da XBZ
                  <ExternalLink className="h-3.5 w-3.5" />
                </a>
              ) : null}
            </div>
          </div>

          <div className="flex flex-wrap items-center justify-end gap-2 border-t border-[var(--ks-color-border-subtle)] bg-[var(--ks-color-bg-subtle)]/30 px-6 py-4">
            <Button
              variant="outline"
              icon={<ShoppingCart size={16} />}
              onClick={() => {
                aoComprar(aberto, corDoDetalhe);
                setAberto(null);
              }}
            >
              Comprar {aberto.cores.length > 1 ? `na cor ${corDoDetalhe.cor.toLowerCase()}` : "da XBZ"}
            </Button>
            <Button
              icon={<PackagePlus size={16} />}
              onClick={() => {
                prepararCadastro(aberto);
                setAberto(null);
              }}
            >
              Cadastrar no meu catálogo
            </Button>
          </div>
        </Janela>
      ) : null}

      {cadastro ? (
        <Janela aoFechar={() => !cadastrando && setCadastro(null)} largura="max-w-xl">
          <div className="flex items-start justify-between gap-4 px-6 pb-3 pt-5">
            <div>
              <h3 className="text-lg font-bold text-[var(--ks-color-text-primary)]">Cadastrar no meu catálogo</h3>
              <p className="text-sm text-[var(--ks-color-text-soft)]">
                {cadastro.modelo.cores.length > 1
                  ? "Um produto só, com as cores como opção para o cliente escolher."
                  : "O produto entra com a foto e os dados da XBZ."}
              </p>
            </div>
            <BotaoFechar aoFechar={() => !cadastrando && setCadastro(null)} />
          </div>

          {cadastrado ? (
            <div className="space-y-4 px-6 pb-6">
              <Aviso tom="bom" titulo={cadastrado.jaExistia ? "Esse produto já está no seu catálogo" : "Cadastrado"}>
                {cadastrado.jaExistia
                  ? "Ele veio da XBZ antes. Abra o produto para conferir ou mudar o que quiser."
                  : `${cadastrado.cores && cadastrado.cores > 1 ? `${cadastrado.cores} cores, ` : ""}preço de venda ${emReais(cadastrado.preco)}${
                      cadastrado.naLoja ? ", já aparecendo na loja" : ", fora da loja até ter preço"
                    }. As fotos chegam em alguns segundos.`}
              </Aviso>
              <div className="flex justify-end gap-2">
                <Button variant="outline" onClick={() => setCadastro(null)}>
                  Fechar
                </Button>
                <Link href={`/dashboard/products/${cadastrado.id}`} className="ks-button ks-button-primary">
                  Abrir produto
                </Link>
              </div>
            </div>
          ) : (
            <>
              <div className="max-h-[65vh] space-y-4 overflow-y-auto px-6 pb-4">
                <Input
                  label="Nome na sua loja"
                  value={cadastro.nome}
                  maxLength={150}
                  onChange={(evento) => setCadastro((atual) => (atual ? { ...atual, nome: evento.target.value } : atual))}
                />
                <div className="grid items-end gap-3 sm:grid-cols-[180px_minmax(0,1fr)]">
                  <EntradaDecimal
                    label="Margem sobre a XBZ"
                    valor={cadastro.margem}
                    aoMudar={(margem) => setCadastro((atual) => (atual ? { ...atual, margem } : atual))}
                    casas={1}
                    suffix="%"
                    className="min-w-0"
                  />
                  <p className="pb-2 text-sm text-[var(--ks-color-text-soft)]">
                    {custoDoCadastro === null ? (
                      "A XBZ não informa preço para esta escolha: o produto entra sem preço e fora da loja."
                    ) : (
                      <>
                        Custo {emReais(custoDoCadastro)} → venda{" "}
                        <strong className="text-[var(--ks-color-text-primary)]">
                          {emReais(Math.round(custoDoCadastro * (1 + Math.max(0, cadastro.margem) / 100) * 100) / 100)}
                        </strong>
                      </>
                    )}
                  </p>
                </div>

                {cadastro.modelo.cores.length > 1 ? (
                  <div className="space-y-2">
                    <div className="flex items-center justify-between">
                      <span className="text-sm font-semibold text-[var(--ks-color-text-primary)]">Cores que entram</span>
                      <div className="flex gap-3 text-xs font-semibold text-[var(--ks-color-primary)]">
                        <button
                          type="button"
                          onClick={() => setCadastro((atual) => (atual ? { ...atual, cores: new Set(atual.modelo.cores.map((cor) => cor.codigoXbz)) } : atual))}
                        >
                          Todas
                        </button>
                        <button
                          type="button"
                          onClick={() =>
                            setCadastro((atual) =>
                              atual ? { ...atual, cores: new Set(atual.modelo.cores.filter((cor) => cor.estoque > 0).map((cor) => cor.codigoXbz)) } : atual
                            )
                          }
                        >
                          Só com estoque
                        </button>
                      </div>
                    </div>
                    <div className="flex flex-wrap gap-1.5">
                      {cadastro.modelo.cores.map((cor) => {
                        const marcada = cadastro.cores.has(cor.codigoXbz);
                        return (
                          <button
                            key={cor.codigoXbz}
                            type="button"
                            onClick={() =>
                              setCadastro((atual) => {
                                if (!atual) return atual;
                                const cores = new Set(atual.cores);
                                if (cores.has(cor.codigoXbz)) cores.delete(cor.codigoXbz);
                                else cores.add(cor.codigoXbz);
                                return { ...atual, cores };
                              })
                            }
                            className={`flex items-center gap-1.5 rounded-full border px-2.5 py-1 text-xs font-medium transition-colors ${
                              marcada
                                ? "border-[var(--ks-color-primary)] bg-[var(--ks-color-primary)]/5 text-[var(--ks-color-primary)]"
                                : "border-slate-200 text-slate-400 line-through"
                            }`}
                          >
                            <Bolinha rotulo={cor.cor} tamanho="h-3 w-3" />
                            {cor.cor}
                            <span className="text-[10px] font-normal opacity-70">{cor.estoque > 0 ? quantidade(cor.estoque) : "sem estoque"}</span>
                          </button>
                        );
                      })}
                    </div>
                  </div>
                ) : null}

                <p className="text-xs leading-5 text-[var(--ks-color-text-soft)]">
                  Vai junto: a foto de cada cor (guardada na Ktalogu, sem o endereço da XBZ), a descrição, o custo, o peso e as medidas para o
                  frete, o NCM para a nota{regraDeCompra(cadastro.modelo) ? ` e o ${regraDeCompra(cadastro.modelo)}` : ""}. O estoque da XBZ não vira
                  estoque seu: ele continua aqui, na tela da XBZ.
                </p>
              </div>
              <div className="flex items-center justify-end gap-2 border-t border-[var(--ks-color-border-subtle)] bg-[var(--ks-color-bg-subtle)]/30 px-6 py-4">
                <Button variant="outline" onClick={() => setCadastro(null)} disabled={cadastrando}>
                  Cancelar
                </Button>
                <Button onClick={() => void cadastrar()} disabled={cadastrando || !cadastro.cores.size || !cadastro.nome.trim()}>
                  {cadastrando ? <Loader2 className="h-4 w-4 animate-spin" /> : "Cadastrar"}
                </Button>
              </div>
            </>
          )}
        </Janela>
      ) : null}
    </div>
  );
}

function Vazio({ titulo, texto }: { titulo: string; texto: string }) {
  return (
    <div className="flex flex-col items-center justify-center px-6 py-16 text-center">
      <div className="mb-3 rounded-full bg-slate-50 p-4">
        <PackageSearch className="h-8 w-8 text-slate-300" />
      </div>
      <h3 className="text-base font-semibold text-slate-900">{titulo}</h3>
      <p className="mt-1 max-w-md text-sm text-slate-500">{texto}</p>
    </div>
  );
}

function Dado({ rotulo, valor, detalhe, forte }: { rotulo: string; valor: string; detalhe?: string | null; forte?: boolean }) {
  return (
    <div className="min-w-0">
      <p className="text-[11px] font-medium text-slate-400">{rotulo}</p>
      <p className={`truncate ${forte ? "text-base font-bold tabular-nums text-[var(--ks-color-text-primary)]" : "text-sm text-[var(--ks-color-text-secondary)]"}`}>{valor}</p>
      {detalhe ? <p className="text-[11px] text-slate-400">{detalhe}</p> : null}
    </div>
  );
}

function BotaoFechar({ aoFechar }: { aoFechar: () => void }) {
  return (
    <button type="button" onClick={aoFechar} className="rounded-full p-1.5 text-slate-400 hover:bg-slate-100 hover:text-slate-600" aria-label="Fechar">
      <X className="h-4 w-4" />
    </button>
  );
}

/* Vai direto para o <body>: dentro da lista (que corta o que passa da borda)
   e debaixo da animação de entrada da página, a janela ficava presa e
   invisível. */
export function Janela({ aoFechar, largura, children }: { aoFechar: () => void; largura: string; children: React.ReactNode }) {
  const fechar = useRef(aoFechar);
  useEffect(() => {
    fechar.current = aoFechar;
  });

  useEffect(() => {
    const aoTeclar = (evento: KeyboardEvent) => {
      if (evento.key === "Escape") fechar.current();
    };
    window.addEventListener("keydown", aoTeclar);
    const antes = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    return () => {
      window.removeEventListener("keydown", aoTeclar);
      document.body.style.overflow = antes;
    };
  }, []);

  if (typeof document === "undefined") return null;
  return createPortal(
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4" onClick={() => fechar.current()}>
      <div className={`w-full overflow-hidden rounded-2xl bg-white shadow-xl ${largura}`} onClick={(evento) => evento.stopPropagation()}>
        {children}
      </div>
    </div>,
    document.body
  );
}
