"use client";

import { useCallback, useEffect, useState } from "react";
import { CheckCircle2, CreditCard, Loader2, ReceiptText, ShoppingBag } from "lucide-react";

import { Anel, CabecalhoDoPainel, Etiqueta, Eyebrow, FaixaDeAcao, NumeroAnimado, Opcao, Painel, Preco } from "@/components/assinatura/primitivos";
import { Aviso } from "@/components/ui/aviso";

import { dataCurta, diasParaVirarOMes, mesPorExtenso, moeda, pedirFiscal, SeloDoStatus } from "./comum";

export type PacoteDeNotas = { id: string; nome: string; descricao: string | null; quantidade: number; preco: number; destaque: boolean };

export type PainelDeNotas = {
  ambiente: string;
  competencia: string;
  saldo: { competencia: string; entradas: number; usadas: number; reservadas: number; disponiveis: number };
  pacotes: PacoteDeNotas[];
  vendasAbertas: boolean;
  /** Empresa que contestou um pagamento: não compra de novo até o suporte olhar. */
  bloqueioDeCompra?: string | null;
  avisoSaldoBaixo: number;
  podeComprar: boolean;
  extrato: Array<{ id: string; competencia: string; tipo: string; quantidade: number; descricao: string | null; created_at: string }>;
  compras: Array<{
    id: string;
    pacote_nome: string;
    quantidade: number;
    preco: number;
    status: string;
    forma_pagamento: string | null;
    checkout_url: string | null;
    aprovada_em: string | null;
    created_at: string;
  }>;
};

type CompraConferida = {
  id: string;
  pacoteNome: string;
  quantidade: number;
  status: string;
  mpStatus: string | null;
  mpStatusDetalhe: string | null;
  formaPagamento: string | null;
  checkoutUrl: string | null;
};

const STATUS_DA_COMPRA: Record<string, { rotulo: string; cor: string }> = {
  pendente: { rotulo: "Aguardando pagamento", cor: "bg-violet-500/10 text-violet-700" },
  aprovada: { rotulo: "Paga", cor: "bg-emerald-500/10 text-emerald-700" },
  recusada: { rotulo: "Recusada", cor: "bg-rose-500/10 text-rose-700" },
  cancelada: { rotulo: "Cancelada", cor: "bg-slate-500/10 text-slate-600" },
  reembolsada: { rotulo: "Reembolsada", cor: "bg-slate-500/10 text-slate-600" },
  contestada: { rotulo: "Contestada", cor: "bg-rose-500/10 text-rose-700" },
};

const FORMA_DE_PAGAMENTO: Record<string, string> = {
  bank_transfer: "Pix",
  account_money: "saldo em conta",
  credit_card: "cartão",
  debit_card: "cartão de débito",
  ticket: "boleto",
};

const TIPO_NO_EXTRATO: Record<string, string> = {
  compra: "Pacote",
  cortesia: "Cortesia",
  consumo: "Nota autorizada",
  reembolso: "Estorno",
  ajuste: "Ajuste",
};

function plural(n: number, um: string, varios: string) {
  return `${n} ${n === 1 ? um : varios}`;
}

/**
 * Os pacotes de notas fiscais: saldo do mês, o que está à venda e o histórico.
 * Vive na aba "Notas fiscais" da Assinatura; `aoCarregar` devolve o painel
 * para quem precisa do saldo fora daqui (a contagem na aba).
 */
export function PacotesDeNotas({ aoCarregar }: { aoCarregar?: (painel: PainelDeNotas) => void }) {
  const [painel, setPainel] = useState<PainelDeNotas | null>(null);
  const [erro, setErro] = useState<string | null>(null);
  const [escolhidoId, setEscolhidoId] = useState<string | null>(null);
  const [comprando, setComprando] = useState(false);
  const [compra, setCompra] = useState<CompraConferida | null>(null);
  const [conferindo, setConferindo] = useState(false);
  const [historico, setHistorico] = useState<"compras" | "extrato">("compras");

  const carregar = useCallback(async () => {
    try {
      const json = await pedirFiscal<PainelDeNotas>("/api/fiscal/creditos");
      setPainel(json);
      aoCarregar?.(json);
    } catch (e) {
      setErro(e instanceof Error ? e.message : "Não foi possível carregar os pacotes.");
    }
  }, [aoCarregar]);

  useEffect(() => {
    let vivo = true;
    pedirFiscal<PainelDeNotas>("/api/fiscal/creditos")
      .then((json) => {
        if (!vivo) return;
        setPainel(json);
        aoCarregar?.(json);
      })
      .catch((e: unknown) => {
        if (vivo) setErro(e instanceof Error ? e.message : "Não foi possível carregar os pacotes.");
      });
    return () => {
      vivo = false;
    };
  }, [aoCarregar]);

  /* Voltou da página de pagamento: confere a compra na hora, sem esperar o aviso. */
  useEffect(() => {
    const busca = new URLSearchParams(window.location.search);
    const compraId = busca.get("compra");
    if (!compraId) return;
    let voltas = 0;
    let parar = false;
    const conferir = async () => {
      voltas += 1;
      if (voltas === 1) setConferindo(true);
      try {
        const json = await pedirFiscal<{ compra: CompraConferida }>(`/api/fiscal/compras/${compraId}`);
        if (parar) return;
        setCompra(json.compra);
        if (json.compra.status !== "pendente" || voltas >= 20) {
          setConferindo(false);
          void carregar();
          return;
        }
      } catch {
        if (voltas >= 3) {
          setConferindo(false);
          return;
        }
      }
      if (!parar) setTimeout(() => void conferir(), 3000);
    };
    const primeira = setTimeout(() => void conferir(), 0);
    return () => {
      clearTimeout(primeira);
      parar = true;
    };
  }, [carregar]);

  const pacotes = painel?.pacotes ?? [];
  /* Começa marcado no pacote em destaque; sem destaque, no primeiro. */
  const escolhido = pacotes.find((p) => p.id === escolhidoId) ?? pacotes.find((p) => p.destaque) ?? pacotes[0] ?? null;

  const comprar = async () => {
    if (!escolhido) return;
    setComprando(true);
    setErro(null);
    try {
      const json = await pedirFiscal<{ checkoutUrl: string }>("/api/fiscal/compras", { method: "POST", json: { pacoteId: escolhido.id } });
      window.location.assign(json.checkoutUrl);
    } catch (e) {
      setErro(e instanceof Error ? e.message : "Não foi possível abrir o pagamento.");
      setComprando(false);
    }
  };

  const saldo = painel?.saldo;
  const dias = diasParaVirarOMes();
  const saldoBaixo = Boolean(saldo && saldo.entradas > 0 && saldo.disponiveis <= (painel?.avisoSaldoBaixo ?? 0));
  const compras = painel?.compras ?? [];
  const extrato = painel?.extrato ?? [];
  const viraOMes = dias === 0 ? "O mês vira hoje à meia-noite" : `O mês vira em ${plural(dias, "dia", "dias")}`;

  return (
    <div className="space-y-6">
      {erro ? (
        <Aviso tom="ruim" aoFechar={() => setErro(null)}>
          {erro}
        </Aviso>
      ) : null}

      {compra ? (
        compra.status === "aprovada" ? (
          <Aviso tom="bom" titulo="Pagamento aprovado" aoFechar={() => setCompra(null)}>
            {compra.quantidade} notas do pacote {compra.pacoteNome} liberadas para usar até o fim do mês.
          </Aviso>
        ) : compra.status === "pendente" ? (
          <Aviso
            tom="neutro"
            titulo={conferindo ? "Conferindo o pagamento…" : "Pagamento em análise"}
            acao={
              compra.checkoutUrl && !conferindo ? (
                <a href={compra.checkoutUrl} className="ks-button ks-button-soft ks-button-sm">
                  Continuar pagamento
                </a>
              ) : undefined
            }
          >
            {conferindo
              ? "Assim que o pagamento for confirmado, as notas entram no saldo."
              : "Pix e boleto podem levar alguns minutos. As notas entram no saldo sozinhas quando o pagamento for confirmado."}
          </Aviso>
        ) : (
          <Aviso tom="ruim" titulo="O pagamento não foi aprovado" aoFechar={() => setCompra(null)}>
            {compra.mpStatusDetalhe === "valor_divergente"
              ? "O valor pago não confere com o do pacote. Fale com o suporte."
              : "Tente de novo com outra forma de pagamento. Nenhum valor foi cobrado."}
          </Aviso>
        )
      ) : null}

      {!painel || !saldo ? (
        <div className="flex justify-center py-16">
          <Loader2 className="h-7 w-7 animate-spin text-[var(--ks-color-primary)]" />
        </div>
      ) : (
        <>
          <div className="grid gap-6 lg:grid-cols-12 lg:items-start">
            {/* O pacote do mês */}
            <Painel className="lg:col-span-5 xl:col-span-4">
              <div className="p-6">
                <div className="flex items-start justify-between gap-3">
                  <Eyebrow>Pacote de {mesPorExtenso(saldo.competencia)}</Eyebrow>
                  {saldo.entradas === 0 ? (
                    <SeloDoStatus tom="neutro" rotulo="Sem pacote este mês" />
                  ) : saldo.disponiveis <= 0 ? (
                    <SeloDoStatus tom="ruim" rotulo="Acabaram" />
                  ) : saldoBaixo ? (
                    <SeloDoStatus tom="atencao" rotulo="Poucas notas" />
                  ) : (
                    <SeloDoStatus tom="bom" rotulo="Com saldo" />
                  )}
                </div>

                <div className="mt-5 flex items-center gap-5">
                  <Anel fracao={saldo.entradas > 0 ? saldo.disponiveis / saldo.entradas : 0} tamanho={104} espessura={10}>
                    <NumeroAnimado valor={Math.max(0, saldo.disponiveis)} className="text-3xl font-extrabold text-[var(--ks-color-text-primary)]" />
                    {saldo.entradas > 0 ? (
                      <span className="mt-0.5 text-[10px] font-bold uppercase tracking-[0.12em] text-[var(--ks-color-text-soft)]">de {saldo.entradas}</span>
                    ) : null}
                  </Anel>
                  <div className="min-w-0 text-sm leading-6 text-[var(--ks-color-text-muted)]">
                    <p className="text-lg font-extrabold leading-tight text-[var(--ks-color-text-primary)]">
                      {saldo.disponiveis === 1 ? "nota disponível" : "notas disponíveis"}
                    </p>
                    <p>
                      {plural(saldo.usadas, "usada", "usadas")}
                      {saldo.reservadas > 0 ? ` · ${saldo.reservadas} aguardando autorização` : ""}
                    </p>
                    <p>{viraOMes}</p>
                  </div>
                </div>
              </div>
              <p className="border-t border-[var(--ks-color-border-subtle)] px-6 py-3 text-xs text-[var(--ks-color-text-soft)]">
                O que sobrar não passa para o mês seguinte. Só gasta nota que for autorizada.
              </p>
            </Painel>

            {/* O que está à venda */}
            <Painel className="lg:col-span-7 xl:col-span-8" atraso={0.06}>
              <CabecalhoDoPainel titulo="Pacotes de notas" texto="Valem até o fim do mês da compra, à parte da assinatura." />
              {!painel.vendasAbertas ? (
                <p className="px-6 py-6 text-sm text-[var(--ks-color-text-muted)]">A compra de pacotes está fechada no momento. Tente mais tarde ou fale com o suporte.</p>
              ) : painel.bloqueioDeCompra ? (
                <div className="p-6">
                  <Aviso tom="atencao" titulo="Compra de pacotes bloqueada">
                    {painel.bloqueioDeCompra}
                  </Aviso>
                </div>
              ) : pacotes.length === 0 ? (
                <p className="px-6 py-6 text-sm text-[var(--ks-color-text-muted)]">Nenhum pacote à venda no momento.</p>
              ) : (
                <>
                  {/* Duas colunas até a tela larga de verdade: em 1366 px, quatro pacotes em 3+1 deixavam um órfão. */}
                  <div role="radiogroup" aria-label="Pacote de notas" className="grid gap-4 p-6 sm:grid-cols-2 2xl:grid-cols-[repeat(auto-fit,minmax(13rem,1fr))]">
                    {pacotes.map((pacote) => (
                      <Opcao
                        key={pacote.id}
                        selecionada={escolhido?.id === pacote.id}
                        aoEscolher={() => setEscolhidoId(pacote.id)}
                        titulo={pacote.nome}
                        etiqueta={pacote.destaque ? <Etiqueta>Mais escolhido</Etiqueta> : undefined}
                      >
                        <span className="text-sm text-[var(--ks-color-text-muted)]">
                          <span className="ks-num text-base font-bold text-[var(--ks-color-text-primary)]">{pacote.quantidade}</span> notas no mês
                        </span>
                        <span className="flex flex-col gap-1">
                          <Preco valor={moeda(pacote.preco)} unidade="" />
                          <span className="text-xs text-[var(--ks-color-text-muted)]">{moeda(pacote.preco / pacote.quantidade)} por nota</span>
                        </span>
                        {pacote.descricao ? <span className="text-xs leading-5 text-[var(--ks-color-text-muted)]">{pacote.descricao}</span> : null}
                      </Opcao>
                    ))}
                  </div>

                  <FaixaDeAcao
                    resumo={
                      escolhido ? (
                        <>
                          <span className="font-semibold text-[var(--ks-color-text-primary)]">{escolhido.nome}</span> · {plural(escolhido.quantidade, "nota", "notas")} ·{" "}
                          <span className="ks-num">{moeda(escolhido.preco)}</span>
                          {dias <= 5 ? ` · vale só até o mês virar (${dias === 0 ? "hoje" : plural(dias, "dia", "dias")})` : ""}
                        </>
                      ) : null
                    }
                  >
                    {painel.podeComprar ? (
                      <button type="button" onClick={() => void comprar()} disabled={comprando || !escolhido} className="ks-button ks-button-primary w-full sm:w-auto">
                        {comprando ? <Loader2 size={16} className="animate-spin" /> : <ShoppingBag size={16} />}
                        Comprar
                      </button>
                    ) : (
                      <span className="text-xs text-[var(--ks-color-text-soft)]">Só quem gerencia a assinatura pode comprar.</span>
                    )}
                  </FaixaDeAcao>

                  <p className="flex flex-wrap items-center gap-x-2 gap-y-1 border-t border-[var(--ks-color-border-subtle)] px-6 py-3 text-xs text-[var(--ks-color-text-soft)]">
                    <CreditCard size={14} />
                    Pix, cartão ou boleto. As notas entram no saldo assim que o pagamento é confirmado.
                  </p>
                </>
              )}
            </Painel>
          </div>

          {/* Histórico */}
          {compras.length || extrato.length ? (
            <Painel atraso={0.12}>
              <div className="flex items-center gap-6 border-b border-[var(--ks-color-border-subtle)] px-6 pt-3">
                {(
                  [
                    { chave: "compras", rotulo: "Compras", quantos: compras.length },
                    { chave: "extrato", rotulo: "Extrato de notas", quantos: extrato.length },
                  ] as const
                ).map((aba) => {
                  const ativa = historico === aba.chave;
                  return (
                    <button
                      key={aba.chave}
                      type="button"
                      onClick={() => setHistorico(aba.chave)}
                      className={`-mb-px flex items-center gap-2 border-b-2 pb-3 text-sm font-semibold transition-colors ${
                        ativa ? "border-[var(--ks-color-primary)] text-[var(--ks-color-primary)]" : "border-transparent text-[var(--ks-color-text-soft)] hover:text-[var(--ks-color-text-primary)]"
                      }`}
                    >
                      {aba.rotulo}
                      {aba.quantos ? (
                        <span className={`ks-num rounded-full px-1.5 text-[11px] font-bold ${ativa ? "bg-[var(--ks-color-primary)] text-white" : "bg-[var(--ks-color-bg-inset)] text-[var(--ks-color-text-muted)]"}`}>
                          {aba.quantos}
                        </span>
                      ) : null}
                    </button>
                  );
                })}
              </div>

              {historico === "compras" ? (
                compras.length ? (
                  <ul>
                    {compras.map((item) => {
                      const status = STATUS_DA_COMPRA[item.status] ?? STATUS_DA_COMPRA.pendente;
                      const forma = item.forma_pagamento ? FORMA_DE_PAGAMENTO[item.forma_pagamento] ?? item.forma_pagamento : null;
                      return (
                        <li key={item.id} className="flex flex-wrap items-center gap-3 border-t border-slate-100/60 px-6 py-3 transition-colors first:border-t-0 hover:bg-[var(--ks-color-bg-hover)]">
                          {/* No celular o nome ocupa a linha inteira e o resto desce, em vez de quebrar palavra por palavra. */}
                          <div className="min-w-[11rem] flex-1">
                            <p className="text-sm font-semibold text-[var(--ks-color-text-primary)]">
                              {item.pacote_nome} · {plural(item.quantidade, "nota", "notas")}
                            </p>
                            <p className="text-[11px] text-[var(--ks-color-text-soft)]">
                              {dataCurta(item.aprovada_em || item.created_at)}
                              {forma ? ` · ${forma}` : ""}
                            </p>
                          </div>
                          <span className="ks-num text-sm font-semibold text-[var(--ks-color-text-primary)]">{moeda(Number(item.preco))}</span>
                          <span className={`rounded-full px-2.5 py-1 text-[11px] font-bold ${status.cor}`}>{status.rotulo}</span>
                          {item.status === "pendente" && item.checkout_url ? (
                            <a href={item.checkout_url} className="ks-button ks-button-soft ks-button-sm">
                              Pagar
                            </a>
                          ) : null}
                        </li>
                      );
                    })}
                  </ul>
                ) : (
                  <p className="px-6 py-6 text-sm text-[var(--ks-color-text-muted)]">Nenhuma compra ainda.</p>
                )
              ) : extrato.length ? (
                <ul>
                  {extrato.map((linha) => (
                    <li key={linha.id} className="flex items-center gap-3 border-t border-slate-100/60 px-6 py-2.5 transition-colors first:border-t-0 hover:bg-[var(--ks-color-bg-hover)]">
                      <span
                        className={`flex h-7 w-7 shrink-0 items-center justify-center rounded-lg ${
                          linha.quantidade > 0 ? "bg-[var(--ks-emerald-soft)] text-[var(--ks-color-status-success)]" : "bg-[var(--ks-brand-50)] text-[var(--ks-brand-600)]"
                        }`}
                      >
                        {linha.quantidade > 0 ? <CheckCircle2 size={15} /> : <ReceiptText size={15} />}
                      </span>
                      <div className="min-w-0 flex-1">
                        <p className="truncate text-sm text-[var(--ks-color-text-primary)]">{linha.descricao || TIPO_NO_EXTRATO[linha.tipo] || linha.tipo}</p>
                        <p className="text-[11px] text-[var(--ks-color-text-soft)]">
                          {TIPO_NO_EXTRATO[linha.tipo] ?? linha.tipo} · {dataCurta(linha.created_at)} · pacote de {mesPorExtenso(linha.competencia)}
                        </p>
                      </div>
                      <span className={`ks-num text-sm font-bold ${linha.quantidade > 0 ? "text-[var(--ks-color-status-success)]" : "text-[var(--ks-color-text-primary)]"}`}>
                        {linha.quantidade > 0 ? `+${linha.quantidade}` : linha.quantidade}
                      </span>
                    </li>
                  ))}
                </ul>
              ) : (
                <p className="px-6 py-6 text-sm text-[var(--ks-color-text-muted)]">Nada no extrato ainda.</p>
              )}
            </Painel>
          ) : null}
        </>
      )}
    </div>
  );
}
