"use client";

import { useCallback, useEffect, useState } from "react";
import { AlertCircle, CheckCircle2, Info, Loader2, Save, Settings2 } from "lucide-react";
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { CustomSelect } from "@/components/ui/custom-select";

/*
  A engrenagem: quem recebe o quê, e onde.

  Antes desta tela, conectar o Asaas DESLIGAVA o Mercado Pago, porque o sistema
  só sabia responder "quem cobra?" com um provedor por conta. Era uma troca
  binária imposta a quem quer as duas coisas — o Pix da loja numa conta e o
  cartão na outra.

  DUAS REGRAS DE DESENHO, e as duas existem para a tela não mentir:

    1. Menu só aparece onde existe escolha. Onde um provedor só faz aquilo, a
       linha é uma afirmação, não um seletor. Menu de uma opção só é menu que
       finge que você decide.
    2. O que não dá, diz por quê. "Cartão: Mercado Pago" com a explicação ao
       lado evita o lojista procurar por dez minutos um botão que não existe.

  A grade toda vem pronta do servidor. Esta tela não calcula nada sobre quem
  cobra o quê — se calculasse, existiriam duas regras, e um dia elas
  discordariam.
*/

type Opcao = { provedor: string; rotulo: string; disponivel: boolean };

type LinhaDoMeio = {
  meio: string;
  rotulo: string;
  opcoes: Opcao[];
  ativo: string | null;
  escolhido: string | null;
  escolhaIgnorada: boolean;
  indisponiveis: Array<{ provedor: string; motivo: string | null }>;
};

type BlocoDoLocal = {
  local: string;
  rotulo: string;
  explicacao: string;
  meios: LinhaDoMeio[];
};

type Provedor = { nome: string; rotulo: string; conectado: boolean; conta: string | null };

const AUTOMATICO = "";

export default function EngrenagemDePagamento({ podeSalvar }: { podeSalvar: boolean }) {
  const [aberta, setAberta] = useState(false);
  const [carregando, setCarregando] = useState(false);
  const [salvando, setSalvando] = useState(false);
  const [provedores, setProvedores] = useState<Provedor[]>([]);
  const [locais, setLocais] = useState<BlocoDoLocal[]>([]);
  const [escolhas, setEscolhas] = useState<Record<string, string>>({});
  const [aviso, setAviso] = useState<{ tipo: "success" | "error"; texto: string } | null>(null);

  const chave = (local: string, meio: string) => `${local}:${meio}`;

  const carregar = useCallback(async () => {
    try {
      setCarregando(true);
      setAviso(null);
      const resposta = await fetch("/api/integrations/roteamento", { cache: "no-store" });
      const corpo = (await resposta.json().catch(() => null)) as
        | { error?: string; provedores?: Provedor[]; locais?: BlocoDoLocal[] }
        | null;
      if (!resposta.ok || corpo?.error) throw new Error(corpo?.error || "Erro ao carregar.");

      setProvedores(corpo?.provedores || []);
      setLocais(corpo?.locais || []);

      const atuais: Record<string, string> = {};
      for (const bloco of corpo?.locais || []) {
        for (const linha of bloco.meios) atuais[chave(bloco.local, linha.meio)] = linha.escolhido || AUTOMATICO;
      }
      setEscolhas(atuais);
    } catch (erro) {
      console.error(erro);
      setAviso({ tipo: "error", texto: "Não foi possível carregar as opções de recebimento." });
    } finally {
      setCarregando(false);
    }
  }, []);

  useEffect(() => {
    if (aberta) void carregar();
  }, [aberta, carregar]);

  async function salvar() {
    setSalvando(true);
    setAviso(null);
    try {
      const rotas = Object.entries(escolhas)
        .filter(([, provedor]) => provedor !== AUTOMATICO)
        .map(([par, provider]) => {
          const [surface, method] = par.split(":");
          return { surface, method, provider };
        });

      const resposta = await fetch("/api/integrations/roteamento", {
        method: "PUT",
        headers: { "content-type": "application/json" },
        body: JSON.stringify({ rotas }),
      });
      const corpo = (await resposta.json().catch(() => null)) as { error?: string } | null;
      if (!resposta.ok || corpo?.error) throw new Error(corpo?.error || "Erro ao salvar.");

      setAviso({ tipo: "success", texto: "Recebimento atualizado." });
      await carregar();
    } catch (erro) {
      console.error(erro);
      setAviso({ tipo: "error", texto: erro instanceof Error ? erro.message : "Erro ao salvar." });
    } finally {
      setSalvando(false);
    }
  }

  /* Quantos provedores estão conectados agora. Com um só, a engrenagem não tem
     o que decidir, e a tela diz isso em vez de mostrar menus vazios. */
  const conectados = provedores.filter((p) => p.conectado);

  return (
    <>
      <button
        type="button"
        onClick={() => setAberta(true)}
        className="inline-flex items-center gap-2 rounded-xl border border-zinc-200 bg-white px-4 py-2.5 text-sm font-medium text-zinc-700 transition-all hover:bg-zinc-50"
        title="Escolher onde cada provedor recebe"
      >
        <Settings2 size={16} />
        Onde cada um recebe
      </button>

      <Dialog open={aberta} onOpenChange={setAberta}>
        <DialogContent className="max-w-2xl max-h-[85vh] overflow-y-auto">
          <DialogHeader>
            <DialogTitle>Onde cada provedor recebe</DialogTitle>
            <DialogDescription>
              O sistema cobra em quatro lugares. Aqui você decide quem recebe cada meio de pagamento em cada um deles.
            </DialogDescription>
          </DialogHeader>

          {carregando ? (
            <div className="flex h-40 items-center justify-center text-sm text-zinc-500">
              <Loader2 className="mr-2 h-4 w-4 animate-spin" />
              Carregando...
            </div>
          ) : (
            <div className="space-y-4">
              {conectados.length === 0 ? (
                <div className="rounded-xl border border-amber-100 bg-amber-50 p-3 text-sm text-amber-800">
                  Nenhum provedor conectado. Configure o Mercado Pago ou o Asaas primeiro.
                </div>
              ) : conectados.length === 1 ? (
                <div className="rounded-xl border border-blue-100 bg-blue-50 p-3 text-sm text-blue-800 flex items-start gap-2">
                  <Info size={16} className="mt-0.5 shrink-0" />
                  <span>
                    Só o <strong>{conectados[0].rotulo}</strong> está conectado, então ele recebe tudo. Conecte o outro
                    provedor para poder dividir.
                  </span>
                </div>
              ) : (
                <div className="rounded-xl border border-zinc-200 bg-zinc-50 p-3 text-sm text-zinc-600">
                  Conectados:{" "}
                  {conectados.map((p) => `${p.rotulo}${p.conta ? ` (${p.conta})` : ""}`).join(" e ")}. Escolher contas
                  diferentes para lugares diferentes funciona, mas lembre que o fechamento do dia vai somar duas contas.
                </div>
              )}

              {locais.map((bloco) => (
                <div key={bloco.local} className="rounded-2xl border border-zinc-200 bg-white p-4">
                  <div>
                    <h4 className="text-sm font-semibold text-zinc-900">{bloco.rotulo}</h4>
                    <p className="mt-0.5 text-xs leading-5 text-zinc-500">{bloco.explicacao}</p>
                  </div>

                  <div className="mt-3 space-y-2.5">
                    {bloco.meios.map((linha) => {
                      const selecionaveis = linha.opcoes.filter((o) => o.disponivel);
                      const podeEscolher = selecionaveis.length > 1;
                      const motivos = linha.indisponiveis.map((i) => i.motivo).filter(Boolean);

                      return (
                        <div key={linha.meio} className="grid gap-1.5 sm:grid-cols-[150px_1fr] sm:items-center">
                          <span className="text-sm font-medium text-zinc-700">{linha.rotulo}</span>

                          {podeEscolher && podeSalvar ? (
                            <CustomSelect
                              options={[
                                { value: AUTOMATICO, label: "Automático" },
                                ...selecionaveis.map((o) => ({ value: o.provedor, label: o.rotulo })),
                              ]}
                              value={escolhas[chave(bloco.local, linha.meio)] ?? AUTOMATICO}
                              onChange={(valor) =>
                                setEscolhas((antes) => ({ ...antes, [chave(bloco.local, linha.meio)]: valor }))
                              }
                              forceOpenDown
                              className="w-full"
                            />
                          ) : (
                            /* Sem escolha possível, a linha vira uma afirmação. */
                            <span className="text-sm text-zinc-600">
                              {linha.ativo
                                ? linha.opcoes.find((o) => o.provedor === linha.ativo)?.rotulo || linha.ativo
                                : "Nenhum provedor disponível"}
                              {motivos.length > 0 ? (
                                <span className="ml-1 text-xs text-zinc-400">· {motivos[0]}</span>
                              ) : null}
                            </span>
                          )}

                          {linha.escolhaIgnorada ? (
                            <span className="text-xs text-amber-700 sm:col-start-2">
                              Sua escolha não está valendo porque aquele provedor não pode cobrar aqui agora. Quem está
                              recebendo é o{" "}
                              {linha.opcoes.find((o) => o.provedor === linha.ativo)?.rotulo || linha.ativo}.
                            </span>
                          ) : null}
                        </div>
                      );
                    })}
                  </div>
                </div>
              ))}

              {aviso ? (
                <div
                  className={`rounded-xl border p-3 text-sm flex items-start gap-2 ${
                    aviso.tipo === "success"
                      ? "border-emerald-100 bg-emerald-50 text-emerald-700"
                      : "border-red-100 bg-red-50 text-red-700"
                  }`}
                >
                  {aviso.tipo === "success" ? (
                    <CheckCircle2 size={16} className="mt-0.5 shrink-0" />
                  ) : (
                    <AlertCircle size={16} className="mt-0.5 shrink-0" />
                  )}
                  <span>{aviso.texto}</span>
                </div>
              ) : null}

              {podeSalvar && conectados.length > 1 ? (
                <div className="flex justify-end">
                  <button
                    onClick={salvar}
                    disabled={salvando}
                    className="inline-flex items-center justify-center gap-2 rounded-xl bg-[var(--ks-color-primary)] px-5 py-2.5 text-sm font-medium text-white transition-all hover:bg-[var(--ks-color-primary-strong)] disabled:opacity-50"
                  >
                    {salvando ? <Loader2 size={16} className="animate-spin" /> : <Save size={16} />}
                    Salvar
                  </button>
                </div>
              ) : null}
            </div>
          )}
        </DialogContent>
      </Dialog>
    </>
  );
}
