/**
 * Email Queue Service
 * 
 * Service for queuing email jobs to AWS SQS
 * This service is injected into other services (Registration, Payment, etc.)
 * to queue emails instead of sending them synchronously
 */

import { Injectable } from '@nestjs/common';
import { SqsClientService } from './sqs-client.service';
import { QueueEmailDto } from '../dto/queue-email.dto';
import { EmailQueueMessage } from '../interfaces/queue-message.interface';
import { QUEUE_CONSTANTS } from '../constants/queue.constants';
import { getQueueUrls, getQueueFeatureFlags } from '../config/sqs.config';
import { AppLoggerService } from 'src/common/services/logger.service';

@Injectable()
export class EmailQueueService {
  private readonly queueUrl: string;
  private readonly queueEnabled: boolean;

  constructor(
    private readonly sqsClient: SqsClientService,
    private readonly logger: AppLoggerService,
  ) {
    const queueUrls = getQueueUrls();
    const featureFlags = getQueueFeatureFlags();
    
    // Emails now go to the communication queue
    this.queueUrl = queueUrls.communication || '';
    this.queueEnabled = featureFlags.communicationQueueEnabled && !!this.queueUrl;

    if (!this.queueEnabled) {
      this.logger.warn(
        'Communication queue is disabled or not configured. ' +
        'Email queue operations will be skipped.'
      );
    }
  }

  /**
   * Queue an email for async sending
   * 
   * @param emailData - Email data to queue
   * @param correlationId - Optional correlation ID for tracking
   * @param userId - Optional user ID who triggered the email
   * @returns Message ID if successful, null if queue is disabled
   */
  async queueEmail(
    emailData: QueueEmailDto,
    correlationId?: string,
    userId?: string,
  ): Promise<string | null> {
    if (!this.queueEnabled) {
      this.logger.debug('Email queue is disabled - skipping queue operation');
      return null;
    }

    try {
      const message: EmailQueueMessage = {
        queueType: QUEUE_CONSTANTS.QUEUE_TYPES.COMMUNICATION,
        subType: QUEUE_CONSTANTS.COMMUNICATION_TYPES.EMAIL,
        timestamp: new Date().toISOString(),
        correlationId: correlationId || `email-${Date.now()}`,
        userId,
        data: {
          to: emailData.to,
          from: emailData.from,
          subject: emailData.subject,
          htmlBody: emailData.htmlBody,
          textBody: emailData.textBody,
          templateKey: emailData.templateKey,
          templateData: emailData.templateData,
          cc: emailData.cc,
          bcc: emailData.bcc,
          attachments: emailData.attachments,
          replyTo: emailData.replyTo,
        },
        metadata: emailData.metadata,
      };

      const messageId = await this.sqsClient.sendMessage(this.queueUrl, message);

      this.logger.log(
        `Email queued successfully: ${emailData.to.emailAddress}, MessageId: ${messageId}`
      );

      return messageId;
    } catch (error) {
      this.logger.error(`Failed to queue email: ${emailData.to.emailAddress}`, '', {
        error: error instanceof Error ? error.message : String(error),
        stack: error instanceof Error ? error.stack : undefined,
        to: emailData.to.emailAddress,
        templateKey: emailData.templateKey,
        correlationId,
        queueUrl: this.queueUrl,
      });
      return null;
    }
  }

  /**
   * Queue multiple emails in batch
   * Note: SQS doesn't have true batch send in SDK v3, so we send them individually
   * but return all message IDs
   * 
   * @param emails - Array of email data to queue
   * @returns Array of message IDs
   */
  async queueBulkEmails(
    emails: QueueEmailDto[],
    correlationId?: string,
  ): Promise<string[]> {
    if (!this.queueEnabled) {
      this.logger.debug('Email queue is disabled - skipping bulk queue operation');
      return [];
    }

    const results = await Promise.allSettled(
      emails.map((email, index) =>
        this.queueEmail(
          email,
          correlationId ? `${correlationId}-${index}` : undefined,
          email.userId,
        ),
      ),
    );

    const messageIds: string[] = [];
    let failures = 0;

    for (const result of results) {
      if (result.status === 'fulfilled') {
        if (result.value) messageIds.push(result.value);
      } else {
        failures++;
      }
    }

    if (failures > 0) {
      this.logger.warn('Some emails failed to queue in bulk', {
        total: emails.length,
        queued: messageIds.length,
        failed: failures,
        correlationId,
      });
    }

    this.logger.log(`Queued ${messageIds.length} emails in bulk`, {
      total: emails.length,
      correlationId,
    });
    return messageIds;
  }

  /**
   * Check if email queue is enabled and configured
   */
  isQueueEnabled(): boolean {
    return this.queueEnabled;
  }

  /**
   * Get queue URL (useful for monitoring/debugging)
   */
  getQueueUrl(): string {
    return this.queueUrl;
  }
}
