"use client";

import { useEffect, useRef, useState } from "react";
import { BadgeCheck, Check, Copy, ExternalLink, Loader2, MessageSquareWarning } from "lucide-react";
import type { DocumentoDoBanner } from "@/lib/banner-editor/documento";
import { enviarParaOOrcamento } from "@/lib/banner-editor/arte-no-orcamento";
import { ProvasIndisponiveis, criarProva, itensDoOrcamento, linkDaProva, listarProvas, orcamentosEPedidos, type ResumoDaProva } from "@/lib/banner-editor/provas";

/*
  "Aprovação" do editor de artes: gera um link da arte como está agora (todas
  as páginas) para o cliente aprovar ou pedir alteração, sem login. Cada link
  é uma versão: mexeu na arte, gera outro. Mostra a situação e o último
  comentário de cada versão.

  Ligada a um ITEM do orçamento, a versão vai junto para a arte do item (as
  imagens trocam, a aprovação volta a pendente) e a resposta do cliente entra
  lá: status da arte, mensagem na conversa da arte (que vai ao Chats e ao
  sino). Sem item, a resposta avisa no sino e fica aqui.
*/

const SITUACOES: Record<ResumoDaProva["situacao"], { rotulo: string; classe: string }> = {
  aguardando: { rotulo: "Aguardando o cliente", classe: "bg-[#F1EFF6] text-[#4B4760]" },
  aprovada: { rotulo: "Aprovada", classe: "bg-[#DCFCE7] text-[#166534]" },
  alteracao: { rotulo: "Pediu alteração", classe: "bg-[#FFF7E6] text-[#8A5300]" },
};

export function BotaoDeAprovacao({
  vinculo = null,
  dono,
  arteId,
  nome,
  documento,
  paginas,
  antesDeCriar,
  aoAvisar,
}: {
  /* A arte veio do item de um orçamento: a prova já nasce ligada a ele. */
  vinculo?: { orcamento: string; item: string | null; rotulo: string } | null;
  dono: string | null;
  arteId: string | null;
  nome: string;
  /* A arte como está agora (todas as páginas, com as fontes da marca). */
  documento: () => DocumentoDoBanner | null;
  /* As páginas, para irem como imagens da arte do item do orçamento. */
  paginas: () => DocumentoDoBanner[];
  /* Guarda a arte antes (a prova fica ligada a ela). */
  antesDeCriar: () => Promise<string | null>;
  aoAvisar: (texto: string, tom?: "bom" | "ruim") => void;
}) {
  const [aberto, setAberto] = useState(false);
  const [provas, setProvas] = useState<ResumoDaProva[] | null>(null);
  const [indisponivel, setIndisponivel] = useState(false);
  const [criando, setCriando] = useState<string | null>(null);
  const [copiado, setCopiado] = useState<string | null>(null);
  const [ligacao, setLigacao] = useState(vinculo ? `orcamento:${vinculo.orcamento}` : "");
  const [itens, setItens] = useState<Array<{ id: string; titulo: string }> | null>(null);
  const [item, setItem] = useState<string>(vinculo?.item ?? "");
  const [opcoes, setOpcoes] = useState<{ orcamentos: Array<{ id: string; rotulo: string }>; pedidos: Array<{ id: string; rotulo: string }> } | null>(null);
  const caixa = useRef<HTMLDivElement | null>(null);
  const [tipo, idDaLigacao] = ligacao.split(":");
  const orcamento = tipo === "orcamento" ? idDaLigacao : null;

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

  /* Os itens do orçamento escolhido: com um item só, ele já vem marcado. */
  useEffect(() => {
    if (!aberto || !orcamento) return;
    let vivo = true;
    itensDoOrcamento(orcamento)
      .then((lista) => {
        if (!vivo) return;
        setItens(lista);
        setItem((atual) => (lista.some((i) => i.id === atual) ? atual : lista.length === 1 ? lista[0].id : ""));
      })
      .catch(() => {
        if (vivo) setItens([]);
      });
    return () => {
      vivo = false;
    };
  }, [aberto, orcamento]);

  const abrir = async () => {
    const vai = !aberto;
    setAberto(vai);
    if (!vai) return;
    if (dono && !opcoes) orcamentosEPedidos(dono).then(setOpcoes).catch(() => setOpcoes({ orcamentos: [], pedidos: [] }));
    if (!arteId) {
      setProvas([]);
      return;
    }
    try {
      setProvas(await listarProvas(arteId));
    } catch (erro) {
      if (erro instanceof ProvasIndisponiveis) setIndisponivel(true);
      setProvas([]);
    }
  };

  const tituloDoItem = itens?.find((i) => i.id === item)?.titulo ?? null;
  const faltaOItem = Boolean(orcamento && itens && itens.length > 1 && !item);

  const criar = async () => {
    const doc = documento();
    if (!dono || !doc || faltaOItem) return;
    setCriando("Guardando a arte…");
    try {
      const id = (await antesDeCriar()) ?? arteId;
      /* Ligada a um item: esta versão vira a arte do item (o que o cliente vê também no orçamento). */
      if (orcamento && item) {
        await enviarParaOOrcamento({ vinculo: { orcamento, item }, paginas: paginas(), nome, substituir: true, aoAndar: (feitas, total) => setCriando(`Mandando para o orçamento ${feitas}/${total}…`) });
      }
      setCriando("Criando o link…");
      const nova = await criarProva(dono, { arteId: id, nome, documento: doc, quoteId: orcamento, orderId: tipo === "pedido" ? idDaLigacao : null, quoteItemId: orcamento && item ? item : null });
      setProvas((l) => [nova, ...(l || [])]);
      await navigator.clipboard.writeText(linkDaProva(nova.token)).catch(() => undefined);
      setCopiado(nova.id);
      aoAvisar(orcamento && item ? `Link copiado. A arte foi para o item ${tituloDoItem ?? ""} do orçamento; a resposta do cliente chega no sino, no Chats e na arte do item.` : "Link de aprovação criado e copiado. A resposta do cliente chega no sino.");
    } catch (erro) {
      if (erro instanceof ProvasIndisponiveis) setIndisponivel(true);
      else aoAvisar(erro instanceof Error ? erro.message : "Não deu para criar o link.", "ruim");
    } finally {
      setCriando(null);
    }
  };

  const copiar = async (prova: ResumoDaProva) => {
    await navigator.clipboard.writeText(linkDaProva(prova.token)).catch(() => undefined);
    setCopiado(prova.id);
  };

  return (
    <div ref={caixa} className="relative">
      <button type="button" onClick={() => void abrir()} className="flex h-10 shrink-0 items-center gap-2 whitespace-nowrap rounded-[10px] bg-white/15 px-4 text-[13.5px] font-bold text-white ring-1 ring-white/30 transition hover:bg-white/25" data-aprovacao data-botao-do-topo>
        <BadgeCheck size={16} /> Aprovação
      </button>
      {aberto ? (
        <div className="absolute right-0 top-[calc(100%+10px)] z-[60] w-[380px] rounded-[16px] bg-white p-4 text-[#1F1B2E] shadow-[0_18px_50px_rgba(20,11,43,0.28)] ring-1 ring-black/5" data-janela-do-topo>
          <p className="text-[14px] font-bold">Mandar para o cliente aprovar</p>
          <p className="mt-1 text-[12px] leading-snug text-[#8A849E]">O cliente abre o link (sem login), vê todas as páginas e aprova ou pede alteração. A resposta chega no sino; ligada a um item do orçamento, entra também na arte do item e no Chats.</p>
          {indisponivel ? (
            <p className="mt-3 rounded-[10px] bg-[#FFF7E6] px-3 py-2.5 text-[12px] leading-snug text-[#8A5300]">A aprovação pelo link ainda não foi ligada no banco (falta aplicar a migration 224).</p>
          ) : (
            <>
              <label className="mt-3 block text-[11.5px] font-semibold text-[#4B4760]">
                Ligar a um orçamento ou pedido (opcional)
                <select value={ligacao} onChange={(e) => setLigacao(e.target.value)} className="ks-field mt-1 h-9 w-full text-[12.5px]" data-ligacao-da-prova>
                  <option value="">Nenhum</option>
                  {vinculo && !opcoes?.orcamentos.some((o) => o.id === vinculo.orcamento) ? <option value={`orcamento:${vinculo.orcamento}`}>{vinculo.rotulo}</option> : null}
                  {opcoes?.orcamentos.length ? (
                    <optgroup label="Orçamentos">
                      {opcoes.orcamentos.map((o) => (
                        <option key={o.id} value={`orcamento:${o.id}`}>
                          {o.rotulo}
                        </option>
                      ))}
                    </optgroup>
                  ) : null}
                  {opcoes?.pedidos.length ? (
                    <optgroup label="Pedidos">
                      {opcoes.pedidos.map((o) => (
                        <option key={o.id} value={`pedido:${o.id}`}>
                          {o.rotulo}
                        </option>
                      ))}
                    </optgroup>
                  ) : null}
                </select>
              </label>
              {orcamento && itens && itens.length > 1 ? (
                <label className="mt-2 block text-[11.5px] font-semibold text-[#4B4760]">
                  De qual item é esta arte?
                  <select value={item} onChange={(e) => setItem(e.target.value)} className="ks-field mt-1 h-9 w-full text-[12.5px]" data-item-da-prova>
                    <option value="">Escolha o item</option>
                    {itens.map((i) => (
                      <option key={i.id} value={i.id}>
                        {i.titulo}
                      </option>
                    ))}
                  </select>
                </label>
              ) : null}
              {orcamento && item && tituloDoItem ? <p className="mt-2 text-[11.5px] leading-snug text-[#5B21B6]">Esta versão vira a arte do item <b>{tituloDoItem}</b> no orçamento, e a resposta do cliente entra lá.</p> : null}
              <button type="button" onClick={() => void criar()} disabled={Boolean(criando) || !dono || faltaOItem} className="mt-3 flex h-11 w-full items-center justify-center gap-2 rounded-[10px] bg-[#7C3AED] text-[13.5px] font-bold text-white transition hover:bg-[#6D28D9] disabled:opacity-70" data-criar-prova>
                {criando ? <Loader2 size={16} className="animate-spin" /> : <BadgeCheck size={16} />}
                {criando || (faltaOItem ? "Escolha o item do orçamento" : "Criar link de aprovação")}
              </button>
            </>
          )}
          {provas?.length ? (
            <div className="mt-4 max-h-[300px] space-y-2 overflow-y-auto">
              {provas.map((prova, i) => {
                const ultima = prova.respostas?.at(-1);
                return (
                  <div key={prova.id} className="rounded-[12px] bg-[#F6F4FB] p-3">
                    <div className="flex items-center justify-between gap-2">
                      <span className="text-[12px] font-bold text-[#1F1B2E]">Versão {provas.length - i} · {new Date(prova.created_at).toLocaleDateString("pt-BR")}</span>
                      <span className={`rounded-full px-2 py-0.5 text-[10.5px] font-bold ${SITUACOES[prova.situacao].classe}`}>{SITUACOES[prova.situacao].rotulo}</span>
                    </div>
                    {ultima?.comentario ? (
                      <p className="mt-1.5 flex gap-1.5 text-[12px] leading-snug text-[#4B4760]">
                        <MessageSquareWarning size={13} className="mt-[2px] shrink-0" />
                        <span className="whitespace-pre-line">
                          {ultima.nome ? <b>{ultima.nome}: </b> : null}
                          {ultima.comentario}
                        </span>
                      </p>
                    ) : null}
                    <div className="mt-2 flex gap-1.5">
                      <button type="button" onClick={() => void copiar(prova)} className="flex h-8 items-center gap-1.5 rounded-[8px] bg-white px-2.5 text-[11.5px] font-semibold text-[#4B4760] ring-1 ring-black/5 hover:text-[#1F1B2E]">
                        {copiado === prova.id ? <Check size={13} /> : <Copy size={13} />} {copiado === prova.id ? "Copiado" : "Copiar link"}
                      </button>
                      <a href={linkDaProva(prova.token)} target="_blank" rel="noreferrer" className="flex h-8 items-center gap-1.5 rounded-[8px] bg-white px-2.5 text-[11.5px] font-semibold text-[#4B4760] ring-1 ring-black/5 hover:text-[#1F1B2E]">
                        <ExternalLink size={13} /> Abrir
                      </a>
                      {prova.quote_id ? (
                        <a href={`/dashboard/quotes/${prova.quote_id}`} target="_blank" rel="noreferrer" className="flex h-8 items-center gap-1.5 rounded-[8px] bg-white px-2.5 text-[11.5px] font-semibold text-[#4B4760] ring-1 ring-black/5 hover:text-[#1F1B2E]">
                          <ExternalLink size={13} /> Orçamento
                        </a>
                      ) : null}
                    </div>
                  </div>
                );
              })}
            </div>
          ) : null}
        </div>
      ) : null}
    </div>
  );
}
