/**
 * Webhook Worker
 *
 * Processes webhook jobs from the BullMQ webhook queue.
 * Handles external HTTP calls to n8n, Stripe, and other integrations.
 *
 * Features:
 * - Automatic retries with exponential backoff
 * - Timeout handling (30s default)
 * - Response validation
 * - Rate limiting (50 webhooks/minute)
 */

import 'server-only';
import { Job } from 'bullmq';
import { registerWorker, QUEUE_NAMES, WebhookJobPayload } from '../bullmq';
import { logger } from '@/lib/logger';

/**
 * Webhook job processor
 */
async function processWebhookJob(job: Job<WebhookJobPayload>): Promise<void> {
  const { url, method, headers, body, timeout, metadata } = job.data;

  logger.debug('[WebhookWorker] Processing webhook', {
    jobId: job.id,
    url,
    method,
    attempt: job.attemptsMade + 1,
  });

  // Validate webhook payload
  if (!url || !method) {
    throw new Error('Invalid webhook payload: missing url or method');
  }

  // Setup abort controller for timeout
  const controller = new AbortController();
  const timeoutMs = timeout ?? 30000; // 30s default
  const timeoutId = setTimeout(() => controller.abort(), timeoutMs);

  try {
    const response = await fetch(url, {
      method,
      headers: {
        'Content-Type': 'application/json',
        'User-Agent': 'Mawidi-BullMQ-Worker/1.0',
        ...headers,
      },
      body: body ? (typeof body === 'string' ? body : JSON.stringify(body)) : undefined,
      signal: controller.signal,
    });

    clearTimeout(timeoutId);

    // Check response status
    if (!response.ok) {
      const errorText = await response.text().catch(() => 'Unknown error');
      throw new Error(
        `Webhook failed with status ${response.status}: ${errorText.substring(0, 200)}`
      );
    }

    const responseData = await response.text();

    logger.info('[WebhookWorker] Webhook call successful', {
      jobId: job.id,
      url,
      method,
      status: response.status,
      responseLength: responseData.length,
      metadata,
    });
  } catch (error) {
    clearTimeout(timeoutId);

    if (error instanceof Error && error.name === 'AbortError') {
      throw new Error(`Webhook timeout after ${timeoutMs}ms: ${url}`);
    }

    throw error;
  }
}

/**
 * Start the webhook worker
 */
export function startWebhookWorker() {
  const worker = registerWorker<WebhookJobPayload>(
    QUEUE_NAMES.WEBHOOK,
    processWebhookJob,
    {
      concurrency: 5, // Process 5 webhooks concurrently
      limiter: {
        max: 50, // Max 50 webhooks
        duration: 60000, // Per minute
      },
    }
  );

  logger.info('[WebhookWorker] Started with concurrency=5, rate=50/min');

  return worker;
}
