/**
 * PayPal Webhook Idempotency
 *
 * Prevents duplicate processing of PayPal webhook events.
 * Uses the PayPalEvent table with a unique constraint on paypal_event_id.
 * Race conditions are handled by catching Prisma P2002 (unique violation).
 */

import { PrismaClient } from '@prisma/client';
import { logger } from './logger';

const prisma = new PrismaClient();

/**
 * Execute a webhook handler with idempotency protection.
 *
 * @param eventId - PayPal event ID (from event.id)
 * @param eventType - PayPal event type (e.g., 'BILLING.SUBSCRIPTION.ACTIVATED')
 * @param resourceId - PayPal resource ID (e.g., subscription or payment ID)
 * @param payload - Full webhook payload (stored for debugging)
 * @param handler - The actual webhook processing function
 * @returns true if the event was a duplicate (already processed), false if it was new and processed
 */
export async function withIdempotency(
  eventId: string,
  eventType: string,
  resourceId: string | undefined,
  payload: any,
  handler: () => Promise<void>
): Promise<boolean> {
  try {
    // Try to insert the event record first (optimistic approach)
    await prisma.payPalEvent.create({
      data: {
        paypal_event_id: eventId,
        event_type: eventType,
        resource_id: resourceId || null,
        payload: payload,
      },
    });

    // If insert succeeded, this is a new event — process it
    await handler();
    return false; // Not a duplicate
  } catch (error: any) {
    // P2002 = unique constraint violation = duplicate event
    if (error?.code === 'P2002') {
      await prisma.payPalEvent.updateMany({
        where: { paypal_event_id: eventId },
        data: { retry_count: { increment: 1 }, last_retry_at: new Date() },
      });
      logger.info('Duplicate PayPal webhook event detected, retry_count incremented', {
        eventId,
        eventType,
      });
      return true; // Duplicate
    }

    // Re-throw any other errors
    logger.error('Webhook idempotency check failed', {
      eventId,
      eventType,
      error: error instanceof Error ? error.message : 'Unknown error',
    });
    throw error;
  }
}
