import { Processor, WorkerHost, OnWorkerEvent } from '@nestjs/bullmq';
import { Logger } from '@nestjs/common';
import { Job } from 'bullmq';
import { InjectRepository } from '@mikro-orm/nestjs';
import { EntityRepository, EntityManager } from '@mikro-orm/postgresql';
import { Notification } from '../entities/notification.entity';
import { PushNotificationQueueJob } from '../interfaces/jobs-queue.interface';
import { NotificationQueueNameEnum } from '../constants/queue';
import { PushNotificationService } from '../services/push-notification.service';

@Processor(NotificationQueueNameEnum.PUSH)
export class PushProcessor extends WorkerHost {
  private readonly logger = new Logger(PushProcessor.name);

  constructor(
    @InjectRepository(Notification)
    private readonly notificationRepository: EntityRepository<Notification>,
    private readonly em: EntityManager,
    private readonly pushNotificationService: PushNotificationService,
  ) {
    super();
  }

  async process(job: Job<PushNotificationQueueJob>) {
    const { title, content, action, pushToken, pushTokens } = job.data;

    this.logger.log(`Processing push notification job: ${job.id} - Title: ${title},`);

    try {
      // Get push token from job data
      const pushToken = job.data.pushToken;
      const pushTokens = job.data.pushTokens;

      if (!pushToken && (!pushTokens || pushTokens.length === 0)) {
        this.logger.warn(`Push token(s) not provided for notification `);
        throw new Error('Push token or pushTokens array is required for push notifications');
      }

      // Send push notification
      // Convert NotificationTitle enum to a readable string for the notification title
      const notificationTitle = String(title)
        .replace(/\./g, ' ')
        .replace(/\b\w/g, l => l.toUpperCase());

      let pushResult;
      if (pushTokens && pushTokens.length > 0) {
        // Send to multiple tokens
        pushResult = await this.pushNotificationService.sendToMultipleTokens({
          title: notificationTitle,
          body: content,
          tokens: pushTokens,
          data: {
            action,
          },
        });
      } else if (pushToken) {
        // Send to single token
        pushResult = await this.pushNotificationService.sendToToken({
          title: notificationTitle,
          body: content,
          token: pushToken,
          data: {
            action,
          },
        });
      } else {
        throw new Error('Push token or pushTokens array is required');
      }

      if (!pushResult.success) {
        throw new Error(pushResult.error || 'Failed to send push notification');
      }

      this.logger.log(`Push notification   sent successfully`);

      return {
        success: true,

        providerResponse: { messageId: pushResult.messageId },
      };
    } catch (error) {
      this.logger.error(`Error processing push notification job ${job.id}:`, error);
      throw error;
    }
  }

  @OnWorkerEvent('completed')
  onCompleted(job: Job) {
    this.logger.log(`Notification job ${job.id} completed`);
  }

  @OnWorkerEvent('failed')
  onFailed(job: Job, error: Error) {
    this.logger.error(`Notification job ${job.id} failed:`, error);
  }
}
