/**
 * Queue Module
 * 
 * Main module for AWS SQS-based async job processing.
 * 
 * This module:
 * 1. Configures SQS client
 * 2. Registers all processors
 * 3. Starts the SQS poller (cron-based)
 * 4. Exports queue services for use in other modules
 * 
 * Architecture:
 * - SqsClientService: Low-level SQS operations
 * - ProcessorRegistry: Maps message types to processors
 * - SqsPoller: Polls queues every 10 seconds using @Cron
 * - Queue Services: High-level APIs for queuing jobs (EmailQueueService, etc.)
 * - Processors: Process messages from queue (EmailProcessor, etc.)
 * 
 * Usage in other modules:
 * ```typescript
 * @Module({
 *   imports: [QueueModule],
 *   ...
 * })
 * export class MyModule {}
 * 
 * // In your service:
 * constructor(private emailQueueService: EmailQueueService) {}
 * 
 * await this.emailQueueService.queueEmail(emailData);
 * ```
 */

import { Module, OnModuleInit, forwardRef } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { AppLoggerService } from 'src/common/services/logger.service';

// Core Services
import { SqsClientService } from './services/sqs-client.service';
import { ProcessorRegistryService } from './services/processor-registry.service';
import { SqsPollerService } from './services/sqs-poller.service';

// Queue Services (for queuing jobs)
import { EmailQueueService } from './services/email-queue.service';
import { WhatsAppQueueService } from './services/whatsapp-queue.service';
import { SmsQueueService } from './services/sms-queue.service';
import { InvoiceQueueService } from './services/invoice-queue.service';

// Processors (for processing jobs)
import { EmailProcessor } from './processors/email.processor';
import { BulkEmailProcessor } from './processors/bulk-email.processor';
import { WhatsAppProcessor } from './processors/whatsapp.processor';
import { BulkWhatsAppProcessor } from './processors/bulk-whatsapp.processor';
import { SmsProcessor } from './processors/sms.processor';
import { InvoiceProcessor } from './processors/invoice.processor';
import { JoinLinkGenerationProcessor } from './processors/join-link-generation.processor';
import { SessionCommunicationTriggerProcessor } from './processors/session-communication-trigger.processor';

// Import CommunicationModule for processors to use CommunicationService
import { CommunicationModule } from 'src/communication/communication.module';
import { InvoiceModule } from 'src/invoice/invoice.module';
import { RegistrationApprovalModule } from 'src/registration-approval/registration-approval.module';
// JoinLinkGenerationProcessor delegates to JoinLinkGenerationService.
import { JoinLinkGenerationModule } from 'src/join-link-generation/join-link-generation.module';
// SessionCommunicationTriggerProcessor delegates to SessionCommunicationService.
import { SessionCommunicationModule } from 'src/session-communication/session-communication.module';

// Import shared services for processors
import { Msg91Service } from 'src/common/services/msg91.service';
import { AwsS3Service } from 'src/common/services/awsS3.service';
import { BrowserManagerService } from 'src/common/services/browser-manager.service';

// Configuration
import { validateQueueConfiguration } from './config/sqs.config';
import { QUEUE_CONSTANTS } from './constants/queue.constants';

@Module({
  imports: [
    ConfigModule, // For accessing environment variables
    CommunicationModule, // Processors need CommunicationService
    forwardRef(() => InvoiceModule), // InvoiceProcessor needs InvoiceService (circular dependency resolved)
    forwardRef(() => RegistrationApprovalModule), // InvoiceProcessor needs RegistrationApprovalService (circular dependency resolved)
    forwardRef(() => JoinLinkGenerationModule), // processor delegates the generation run
    forwardRef(() => SessionCommunicationModule), // trigger processor delegates the send
  ],
  providers: [
    // Core infrastructure
    SqsClientService,
    ProcessorRegistryService,
    SqsPollerService,

    // Shared logger (app-wide logging format)
    AppLoggerService,

    // Queue services (exported for use in other modules)
    EmailQueueService,
    WhatsAppQueueService,
    SmsQueueService,
    InvoiceQueueService,

    // Processors (internal to queue module)
    EmailProcessor,
    BulkEmailProcessor,
    WhatsAppProcessor,
    BulkWhatsAppProcessor,
    SmsProcessor,
    InvoiceProcessor,
    JoinLinkGenerationProcessor,
    SessionCommunicationTriggerProcessor,

    // Shared services needed by processors
    Msg91Service, // For SMS processor
    AwsS3Service, // For Email processor (S3 attachments)
    BrowserManagerService, // For InvoiceProcessor (browser cleanup)
  ],
  exports: [
    // Export queue services so other modules can queue jobs
    EmailQueueService,
    WhatsAppQueueService,
    SmsQueueService,
    InvoiceQueueService,
    
    // Export core services for advanced usage if needed
    SqsClientService,
    ProcessorRegistryService,
  ],
})
export class QueueModule implements OnModuleInit {
  constructor(
    private readonly logger: AppLoggerService,
    private readonly processorRegistry: ProcessorRegistryService,
    private readonly emailProcessor: EmailProcessor,
    private readonly bulkEmailProcessor: BulkEmailProcessor,
    private readonly whatsappProcessor: WhatsAppProcessor,
    private readonly bulkWhatsappProcessor: BulkWhatsAppProcessor,
    private readonly smsProcessor: SmsProcessor,
    private readonly invoiceProcessor: InvoiceProcessor,
    private readonly joinLinkGenerationProcessor: JoinLinkGenerationProcessor,
    private readonly sessionCommunicationTriggerProcessor: SessionCommunicationTriggerProcessor,
    // Add other processors here as they're created
  ) {}

  /**
   * Initialize the module - register all processors
   */
  async onModuleInit() {
    this.logger.log('Initializing Queue Module...');

    // Validate configuration
    try {
      validateQueueConfiguration();
    } catch (error) {
      this.logger.error('Queue configuration validation failed', '', {
        error: error instanceof Error ? error.message : String(error),
        stack: error instanceof Error ? error.stack : undefined,
      });
      // Don't throw - allow app to start even if queues aren't configured
    }

    // Register processors with the registry
    this.registerProcessors();

    this.logger.log(
      'Queue Module initialized successfully. ' +
      'SQS Poller will start polling queues every ' +
      `${QUEUE_CONSTANTS.POLL_INTERVAL_SECONDS} seconds.`
    );
  }

  /**
   * Register all processors with the ProcessorRegistry
   * Processors are registered by message subType (email, whatsapp, sms, invoice)
   * NOT by queue type (communication, heavy-processing)
   */
  private registerProcessors(): void {
    // Register communication processors
    this.processorRegistry.registerProcessor(
      QUEUE_CONSTANTS.COMMUNICATION_TYPES.EMAIL,
      this.emailProcessor
    );

    this.processorRegistry.registerProcessor(
      QUEUE_CONSTANTS.COMMUNICATION_TYPES.BULK_EMAIL,
      this.bulkEmailProcessor
    );

    this.processorRegistry.registerProcessor(
      QUEUE_CONSTANTS.COMMUNICATION_TYPES.WHATSAPP,
      this.whatsappProcessor
    );

    this.processorRegistry.registerProcessor(
      QUEUE_CONSTANTS.COMMUNICATION_TYPES.BULK_WHATSAPP,
      this.bulkWhatsappProcessor
    );

    this.processorRegistry.registerProcessor(
      QUEUE_CONSTANTS.COMMUNICATION_TYPES.SMS,
      this.smsProcessor
    );
    
    // Register heavy processing processors
    this.processorRegistry.registerProcessor(
      QUEUE_CONSTANTS.HEAVY_PROCESSING_TYPES.INVOICE,
      this.invoiceProcessor
    );

    // Register event processors
    this.processorRegistry.registerProcessor(
      QUEUE_CONSTANTS.EVENT_TYPES.JOIN_LINK_GENERATION,
      this.joinLinkGenerationProcessor
    );

    this.processorRegistry.registerProcessor(
      QUEUE_CONSTANTS.EVENT_TYPES.SESSION_COMMUNICATION_TRIGGER,
      this.sessionCommunicationTriggerProcessor
    );
    // this.processorRegistry.registerProcessor(
    //   QUEUE_CONSTANTS.HEAVY_PROCESSING_TYPES.PAYMENT_RECEIPT,
    //   this.paymentReceiptProcessor
    // );

    const registeredTypes = this.processorRegistry.getRegisteredQueueTypes();
    this.logger.log(`Registered ${registeredTypes.length} processor(s): ${registeredTypes.join(', ')}`);
  }
}
