import { Injectable, Logger } from '@nestjs/common';
import { InjectQueue } from '@nestjs/bullmq';
import { Queue } from 'bullmq';
import { NotificationQueueNameEnum } from '../constants/queue';
import {
  InAppNotificationQueueJob,
  PushNotificationQueueJob,
  SmsNotificationQueueJob,
} from '../interfaces/jobs-queue.interface';

@Injectable()
export class NotificationQueueService {
  private readonly logger = new Logger(NotificationQueueService.name);

  constructor(
    @InjectQueue(NotificationQueueNameEnum.SMS) private readonly smsQueue: Queue,
    @InjectQueue(NotificationQueueNameEnum.PUSH) private readonly pushQueue: Queue,
    @InjectQueue(NotificationQueueNameEnum.IN_APP) private readonly inAppQueue: Queue,
  ) {}

  async addSmsNotification(job: SmsNotificationQueueJob): Promise<void> {
    try {
      const jobId = `${job.templateId}-${this.generateRandomInt()}-${Date.now()}`;

      await this.smsQueue.add('sms-notification', job, {
        jobId,
        attempts: 3,
        backoff: {
          type: 'exponential',
          delay: 2000,
        },
        removeOnComplete: {
          age: 24 * 3600, // Keep completed jobs for 24 hours
          count: 1000,
        },
        removeOnFail: {
          age: 7 * 24 * 3600, // Keep failed jobs for 7 days
        },
      });

      this.logger.log(`SMS notification job added to queue: ${jobId}`);
    } catch (error) {
      this.logger.error(`Failed to add SMS notification to queue:`, error);
      throw error;
    }
  }

  async addPushNotification(job: PushNotificationQueueJob): Promise<void> {
    try {
      const jobId = `${job.title}-${this.generateRandomInt()}-${Date.now()}`;

      await this.pushQueue.add('push-notification', job, {
        jobId,
        attempts: 3,
        backoff: {
          type: 'exponential',
          delay: 2000,
        },
        removeOnComplete: {
          age: 24 * 3600, // Keep completed jobs for 24 hours
          count: 1000,
        },
        removeOnFail: {
          age: 7 * 24 * 3600, // Keep failed jobs for 7 days
        },
      });

      this.logger.log(`Push notification job added to queue: ${jobId}`);
    } catch (error) {
      this.logger.error(`Failed to add push notification to queue:`, error);
      throw error;
    }
  }

  async addBulkSmsNotifications(jobs: SmsNotificationQueueJob[]): Promise<void> {
    try {
      const queueJobs = jobs.map(job => ({
        name: 'sms-notification',
        data: job,
        opts: {
          jobId: `${job.templateId}-${this.generateRandomInt()}`,
          attempts: 3,
          backoff: {
            type: 'exponential',
            delay: 2000,
          },
        },
      }));

      await this.smsQueue.addBulk(queueJobs);
      this.logger.log(`Added ${jobs.length} SMS notification jobs to queue`);
    } catch (error) {
      this.logger.error(`Failed to add bulk notifications to queue:`, error);
      throw error;
    }
  }

  async addBulkPushNotifications(jobs: PushNotificationQueueJob[]): Promise<void> {
    try {
      const queueJobs = jobs.map(job => ({
        name: 'push-notification',
        data: job,
        opts: {
          jobId: `${job.title}-${this.generateRandomInt()}-${Date.now()}`,
          attempts: 3,
          backoff: {
            type: 'exponential',
            delay: 2000,
          },
        },
      }));

      await this.pushQueue.addBulk(queueJobs);
      this.logger.log(`Added ${jobs.length} Push notification jobs to queue`);
    } catch (error) {
      this.logger.error(`Failed to add bulk notifications to queue:`, error);
      throw error;
    }
  }
  async addBulkInAppNotifications(jobs: InAppNotificationQueueJob[]): Promise<void> {
    try {
      const queueJobs = jobs.map(job => ({
        name: 'in-app-notification',
        data: job,
        opts: {
          jobId: `${job.subject}-${job.notificationId}-${Date.now()}`,
          attempts: 3,
          backoff: {
            type: 'exponential',
            delay: 2000,
          },
        },
      }));

      await this.inAppQueue.addBulk(queueJobs);
      this.logger.log(`Added ${jobs.length} InApp notification jobs to queue`);
    } catch (error) {
      this.logger.error(`Failed to add bulk notifications to queue:`, error);
      throw error;
    }
  }
  private generateRandomInt(): string {
    return Math.random().toString(36).substring(2, 15);
  }
}
