/**
 * Email Queue Helper
 *
 * Provides a simple interface for sending emails through the job queue
 * with automatic retries and dead letter queue handling.
 *
 * When Redis is not available, falls back to direct email sending.
 *
 * Updated to use BullMQ for production-grade async processing.
 */

import { enqueueEmail } from './bullmq';
import { logger } from '@/lib/logger';
import { redisConfigured } from '@/lib/redis';
// Note: sendEmailImmediate is imported dynamically to avoid circular dependency
// lib/email.ts imports queueEmail from this file

export interface QueuedEmailOptions {
  to: string;
  subject: string;
  html: string;
  text: string;
  /** Optional category for tracking/analytics */
  category?: string;
  /** Additional metadata */
  metadata?: Record<string, unknown>;
  /** Delay before sending (ms) */
  delayMs?: number;
  /** High priority emails are processed first */
  priority?: 'high' | 'normal';
  /** Max retry attempts (default: 4) */
  maxAttempts?: number;
}

/**
 * Queue an email for background sending with retries.
 * Falls back to direct sending when Redis is not available.
 *
 * @example
 * await queueEmail({
 *   to: 'user@example.com',
 *   subject: 'Welcome!',
 *   html: '<h1>Welcome to Mawidi</h1>',
 *   text: 'Welcome to Mawidi',
 *   category: 'onboarding',
 * });
 */
export async function queueEmail(options: QueuedEmailOptions): Promise<string> {
  const useQueue = process.env.EMAIL_QUEUE_ENABLED !== 'false' && redisConfigured;

  // When Redis is available and queue is enabled, use BullMQ
  if (useQueue) {
    try {
      const jobId = await enqueueEmail(
        {
          to: options.to,
          subject: options.subject,
          html: options.html,
          text: options.text,
          category: options.category,
          metadata: options.metadata,
        },
        {
          delay: options.delayMs,
          priority: options.priority === 'high' ? 5 : 3,
          attempts: options.maxAttempts,
        }
      );

      logger.debug('Email queued for background sending (BullMQ)', {
        jobId,
        to: options.to,
        category: options.category,
      });

      return jobId;
    } catch (error) {
      logger.warn('Email enqueue failed, falling back to direct send', {
        error: error instanceof Error ? error.message : String(error),
        to: options.to,
        category: options.category,
      });
    }
  }

  // Fallback: Send email directly (synchronous)
  // Dynamic import to avoid circular dependency with lib/email.ts
  const { sendEmailImmediate } = await import('@/lib/email');
  const success = await sendEmailImmediate(options.to, {
    subject: options.subject,
    html: options.html,
    text: options.text,
  });

  if (!success) {
    throw new Error(`Failed to send email to ${options.to}`);
  }

  logger.debug('Email sent directly (queue unavailable)', {
    to: options.to,
    category: options.category,
  });

  return `direct-${Date.now()}`; // Return a pseudo job ID for consistency
}

/**
 * Queue multiple emails for batch sending
 *
 * @example
 * await queueEmailBatch([
 *   { to: 'user1@example.com', subject: 'Newsletter', ... },
 *   { to: 'user2@example.com', subject: 'Newsletter', ... },
 * ]);
 */
export async function queueEmailBatch(
  emails: QueuedEmailOptions[]
): Promise<string[]> {
  const jobIds = await Promise.all(emails.map((email) => queueEmail(email)));

  logger.info('Email batch queued', {
    count: emails.length,
    jobIds,
  });

  return jobIds;
}

/**
 * Queue a transactional email with high priority
 * (e.g., OTP, password reset, order confirmation)
 */
export async function queueTransactionalEmail(
  options: Omit<QueuedEmailOptions, 'priority'>
): Promise<string> {
  return queueEmail({
    ...options,
    priority: 'high',
    category: options.category || 'transactional',
  });
}

/**
 * Queue a marketing/newsletter email with normal priority
 */
export async function queueMarketingEmail(
  options: Omit<QueuedEmailOptions, 'priority'>
): Promise<string> {
  return queueEmail({
    ...options,
    priority: 'normal',
    category: options.category || 'marketing',
  });
}
