import { createNextWebhookHandler } from '@gpmpay/sdk/webhooks';

// Signature verification uses node:crypto, so keep this off the edge runtime.
export const runtime = 'nodejs';

// Deliveries must never be served from a cache.
export const dynamic = 'force-dynamic';

/**
 * Replace with a real table plus a unique constraint on the transaction id.
 * An in-memory Set does not survive a restart or scale past one instance.
 */
const processed = new Set<string>();

function claim(transactionId: string): boolean {
  if (processed.has(transactionId)) return false;
  processed.add(transactionId);
  return true;
}

export const POST = createNextWebhookHandler({
  secret: process.env.GPMPAY_WEBHOOK_SECRET!,

  onEvent: async (event) => {
    const { id: transactionId, transferType, transferAmount, content } =
      event.payload;

    // GPM Pay retries on 10s/30s/2m/10m/1h/6h — up to 6 attempts. The same
    // transaction WILL arrive more than once.
    if (!claim(transactionId)) return;

    // You receive every transaction on the account, outgoing ones included.
    if (transferType !== 'in') return;

    // The code you minted in createPayment(). Match with a regex, not `===`:
    // banks normalize the content and some prepend their own prefix.
    const code = /ORD(\w+)/.exec(content)?.[0];
    if (!code) {
      console.log(`unmatched transfer ${transferAmount} — "${content}"`);
      return;
    }

    // Nothing checks the amount for you — this comparison is the whole point.
    // const cart = await db.carts.findByPaymentCode(code);
    // if (!cart || cart.total !== transferAmount) return;

    // await db.carts.markPaid(code);
    // await sendConfirmationEmail(code);

    console.log(`${code} paid ${transferAmount}`);
  },
});

// The handler answers 200 as soon as the signature checks out, and 401 with a
// `reason` when it does not — so a wrong secret is obvious in GPM Pay's
// delivery history rather than silently swallowed.
