// api/webhook-asaas.js
//
// Escuta os avisos automáticos do Asaas. URL depois de publicado:
//   POST /api/webhook-asaas   (cadastrada no Asaas em Integrações → Webhooks)
//
// REGRA DE OURO: nada é liberado só porque "chegou um aviso".
// Antes de liberar qualquer coisa, este arquivo:
//   1. exige o token secreto do Asaas (sem token configurado, recusa tudo);
//   2. PERGUNTA DIRETO AO ASAAS o estado real do pagamento;
//   3. confere que o pagamento é mesmo DESTE pedido, está CONFIRMADO/RECEBIDO
//      e tem EXATAMENTE o valor esperado.
// Se qualquer item falhar, não libera e avisa a equipe.
//
// Depois de confirmado:
//   • compra feita no site (pessoa nova)     → e-mail com o link para criar o acesso
//   • compra feita de dentro da plataforma   → produto liberado NA HORA + e-mail
//
// Eventos que o webhook precisa ter marcados no Asaas:
//   PAYMENT_CONFIRMED, PAYMENT_RECEIVED         (venda)
//   PAYMENT_REFUNDED, PAYMENT_CHARGEBACK_REQUESTED  (avisa a equipe)

import { servicos, acessoDoPedido, mesclarAcesso, nomesDoPedido } from './_servicos.js';

const WEBHOOK_TOKEN = process.env.ASAAS_WEBHOOK_TOKEN;
const STATUS_PAGOS = ['CONFIRMED', 'RECEIVED', 'RECEIVED_IN_CASH'];

// O pagamento que o Asaas descreve pertence mesmo a este pedido?
function pertence(real, pedido) {
  return real.externalReference === pedido.id
    || real.id === pedido.asaas_payment_id
    || (!!real.installment && real.installment === pedido.asaas_installment_id);
}

// Devolve null se estiver tudo certo, ou o motivo da recusa.
export function motivoDeRecusa(real, pedido) {
  if (!real) return 'pagamento não existe no Asaas';
  if (!STATUS_PAGOS.includes(real.status)) return `status no Asaas é ${real.status}`;
  if (!pertence(real, pedido)) return 'pagamento não pertence a este pedido';
  if (pedido.asaas_customer_id && real.customer && real.customer !== pedido.asaas_customer_id) return 'cliente diferente do esperado';
  if (pedido.valor_esperado != null && Math.abs(Number(real.value) - Number(pedido.valor_esperado)) > 0.02) {
    return `valor pago (${real.value}) diferente do esperado (${pedido.valor_esperado})`;
  }
  return null;
}

export function criarHandler({ dados, email, plataforma, asaas, config }) {
  return async function handler(req, res) {
    if (req.method !== 'POST') return res.status(405).json({ error: 'Método não permitido' });

    // Sem token configurado = recusa tudo (nunca aceitar aviso de qualquer um).
    if (!WEBHOOK_TOKEN) {
      console.error('ASAAS_WEBHOOK_TOKEN não configurado: webhook recusado por segurança.');
      return res.status(500).json({ error: 'Webhook não configurado' });
    }
    if (req.headers['asaas-access-token'] !== WEBHOOK_TOKEN) {
      return res.status(401).json({ error: 'Token inválido' });
    }

    try {
      const { event, payment } = req.body || {};
      console.log('Webhook recebido do Asaas:', event, payment && payment.id);
      if (!payment) return res.status(200).json({ received: true });

      const pedido = await dados.acharPedido({
        referencia: payment.externalReference,
        paymentId: payment.id,
        installmentId: payment.installment,
      });
      if (!pedido) {
        console.warn('Pedido não encontrado para o pagamento:', payment.id, payment.externalReference);
        return res.status(200).json({ received: true });
      }

      // ------------------------------------------------------------ VENDA
      if (event === 'PAYMENT_CONFIRMED' || event === 'PAYMENT_RECEIVED') {
        // Confirma DIRETO com o Asaas (o aviso sozinho não vale).
        let real = null;
        try {
          real = await asaas.consultarPagamento(payment.id);
        } catch (e) {
          if (e.status === 404) real = null;
          else {
            // Não deu pra perguntar agora (rede/Asaas fora): pedimos para o Asaas tentar de novo.
            console.error('Não foi possível confirmar com o Asaas:', e.message);
            return res.status(500).json({ error: 'Falha ao confirmar pagamento, tente novamente' });
          }
        }

        const motivo = motivoDeRecusa(real, pedido);
        if (motivo) {
          console.error('Pagamento NÃO liberado:', motivo, pedido.id);
          await email.avisarEquipe({
            assunto: `Atenção: pagamento não liberado (${pedido.nome})`,
            texto: `Chegou um aviso de pagamento, mas NADA foi liberado porque: ${motivo}.\n\nPedido: ${pedido.id}\nComprador: ${pedido.nome} (${pedido.email})\nCompra: ${pedido.rotulo}\nPagamento no Asaas: ${payment.id}\n\nConfira no painel do Asaas.`,
          });
          return res.status(200).json({ received: true });
        }

        // Marca como pago (só na 1ª vez; reenvios e parcelas 2..12 passam direto).
        const primeira = await dados.marcarPago(pedido.id, { asaas_payment_id: pedido.asaas_payment_id || payment.id });
        const atual = primeira || { ...pedido, status: 'pago' };

        if (primeira && atual.origem !== 'plataforma') {
          // Compra no site: manda o convite para criar o acesso.
          const link = `${config.SITE_URL}/criar-acesso.html?p=${atual.convite_token}`;
          const enviado = await email.enviarConvite({ para: atual.email, nome: atual.nome, link, rotulo: atual.rotulo });
          if (enviado) await dados.atualizarPedido(atual.id, { email_enviado_em: new Date().toISOString() });
          await email.avisarEquipe({
            assunto: `Nova venda: ${atual.nome} · ${atual.rotulo}`,
            texto: `Pagamento confirmado.\n\nComprador: ${atual.nome}\nE-mail: ${atual.email}\nWhatsApp: ${atual.telefone || '-'}\nCompra: ${atual.rotulo}\n\nO convite para criar o acesso ${enviado ? 'foi enviado por e-mail' : 'NÃO foi enviado (verifique o Resend)'}.\nLink do convite (se precisar reenviar): ${link}`,
          });
        }

        // Compra feita de DENTRO da plataforma: libera na hora (e tenta de novo
        // em qualquer aviso seguinte, caso algo tenha falhado antes).
        if (atual.origem === 'plataforma' && atual.casal_id) {
          const reservado = await dados.reservarLiberacao(atual.id);
          if (reservado) {
            try {
              const jaTinha = await plataforma.lerAcesso(atual.casal_id);
              await plataforma.gravarAcesso(atual.casal_id, mesclarAcesso(jaTinha, acessoDoPedido(atual)));
              const nomes = nomesDoPedido(atual);
              await email.enviarProdutoLiberado({ para: atual.email, nome: atual.nome, produtos: nomes, plataformaUrl: plataforma.url });
              await email.avisarEquipe({
                assunto: `Venda na plataforma: ${atual.nome} · ${nomes.join(', ')}`,
                texto: `Pagamento confirmado e produto liberado automaticamente.\n\nComprador: ${atual.nome}\nE-mail: ${atual.email}\nProduto: ${nomes.join(', ')}`,
              });
            } catch (e) {
              console.error('Falha ao liberar produto:', e);
              await dados.desfazerLiberacao(atual.id).catch(() => {});
              await email.avisarEquipe({
                assunto: `URGENTE: pagamento confirmado, mas o produto NÃO foi liberado (${atual.nome})`,
                texto: `O pagamento foi confirmado, mas deu erro ao liberar na plataforma.\n\nComprador: ${atual.nome}\nE-mail: ${atual.email}\nProduto: ${nomesDoPedido(atual).join(', ')}\nPedido: ${atual.id}\n\nLibere manualmente no painel admin. Se o Asaas reenviar o aviso, o sistema tenta de novo sozinho.`,
              });
            }
          }
        }

        if (!primeira) console.log('Pedido já estava pago (reenvio ou parcela seguinte):', pedido.id);
      }

      // -------------------------------------------- REEMBOLSO / ESTORNO
      if ((event === 'PAYMENT_REFUNDED' || event === 'PAYMENT_CHARGEBACK_REQUESTED') && pedido.status !== 'reembolsado') {
        if (event === 'PAYMENT_REFUNDED') await dados.atualizarPedido(pedido.id, { status: 'reembolsado' });
        await email.avisarEquipe({
          assunto: `${event === 'PAYMENT_REFUNDED' ? 'Reembolso' : 'CONTESTAÇÃO (chargeback)'}: ${pedido.nome} · ${pedido.rotulo}`,
          texto: `O Asaas registrou ${event === 'PAYMENT_REFUNDED' ? 'um reembolso' : 'uma contestação do pagamento'}.\n\nComprador: ${pedido.nome}\nE-mail: ${pedido.email}\nCompra: ${pedido.rotulo}\n\nSe a pessoa já tem acesso, bloqueie na plataforma (painel admin).`,
        });
      }

      return res.status(200).json({ received: true });
    } catch (err) {
      console.error(err);
      // 200 mesmo com erro interno, para não gerar reenvios em loop; o log registra.
      return res.status(200).json({ received: true, warning: 'erro interno, verifique os logs' });
    }
  };
}

export default criarHandler(servicos);
