/**
 * Webhook Queue Helper
 *
 * Provides a simple interface for queueing webhook calls
 * with automatic retries and timeout handling.
 *
 * Replaces synchronous webhook calls in API routes with async jobs.
 */

import { enqueueWebhook } from './bullmq';
import type { WebhookJobPayload } from './bullmq';
import { logger } from '@/lib/logger';
import { redisConfigured } from '@/lib/redis';

export interface QueuedWebhookOptions {
  url: string;
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
  headers?: Record<string, string>;
  body?: Record<string, unknown> | string;
  timeout?: number;
  metadata?: Record<string, unknown>;
  /** Delay before sending (ms) */
  delayMs?: number;
  /** Priority (1-10, higher = more important) */
  priority?: number;
  /** Max retry attempts (default: 4) */
  maxAttempts?: number;
}

/**
 * Queue a webhook call for background processing
 *
 * @example
 * await queueWebhook({
 *   url: 'https://n8n.example.com/webhook/demo',
 *   method: 'POST',
 *   body: { event: 'demo_booked', data: { ... } },
 *   headers: { 'Authorization': 'Bearer token' },
 * });
 */
export async function queueWebhook(options: QueuedWebhookOptions): Promise<string> {
  const useQueue = process.env.WEBHOOK_QUEUE_ENABLED !== 'false' && redisConfigured;

  if (!useQueue) {
    // Fallback: Call webhook synchronously (not recommended for production)
    logger.warn('Webhook queue disabled, calling synchronously', {
      url: options.url,
      method: options.method,
    });

    const response = await fetch(options.url, {
      method: options.method || 'POST',
      headers: {
        'Content-Type': 'application/json',
        ...options.headers,
      },
      body: options.body
        ? typeof options.body === 'string'
          ? options.body
          : JSON.stringify(options.body)
        : undefined,
    });

    if (!response.ok) {
      throw new Error(`Webhook failed: ${response.status} ${response.statusText}`);
    }

    return `direct-${Date.now()}`;
  }

  // Queue webhook for background processing
  const payload: WebhookJobPayload = {
    url: options.url,
    method: options.method || 'POST',
    headers: options.headers,
    body: options.body,
    timeout: options.timeout,
    metadata: options.metadata,
  };

  const jobId = await enqueueWebhook(payload, {
    delay: options.delayMs,
    priority: options.priority ?? 3,
    attempts: options.maxAttempts,
  });

  logger.debug('Webhook queued for background processing (BullMQ)', {
    jobId,
    url: options.url,
    method: options.method,
  });

  return jobId;
}

/**
 * Queue a demo booking webhook (n8n integration)
 */
export async function queueDemoBookingWebhook(
  bookingId: string,
  bookingData: Record<string, unknown>
): Promise<string> {
  const webhookUrl = process.env.N8N_WEBHOOK_URL;

  if (!webhookUrl) {
    logger.warn('N8N_WEBHOOK_URL not configured, skipping webhook');
    return 'skipped-no-url';
  }

  return queueWebhook({
    url: webhookUrl,
    method: 'POST',
    body: {
      event: 'demo_booking_created',
      timestamp: new Date().toISOString(),
      booking: {
        id: bookingId,
        ...bookingData,
      },
    },
    priority: 5, // High priority
    metadata: {
      bookingId,
      type: 'demo_booking',
    },
  });
}

/**
 * Queue a Stripe webhook retry
 */
export async function queueStripeWebhook(
  eventType: string,
  eventData: Record<string, unknown>
): Promise<string> {
  return queueWebhook({
    url: process.env.STRIPE_WEBHOOK_URL || '',
    method: 'POST',
    body: {
      type: eventType,
      data: eventData,
    },
    priority: 6, // High priority for payment events
    metadata: {
      eventType,
      source: 'stripe',
    },
  });
}
