"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.emailQueueService = void 0;
const bullmq_1 = require("bullmq");
const client_1 = require("@prisma/client");
const env_1 = require("../config/env");
const database_1 = require("../config/database");
const logger_1 = require("../utils/logger");
const email_service_1 = require("./email.service");
const metrics_1 = require("../utils/metrics");
const listmonk_event_sync_service_1 = require("./listmonk-event-sync.service");
class EmailQueueService {
    queue;
    worker = null;
    constructor() {
        this.queue = new bullmq_1.Queue('campaign-emails', {
            connection: { url: env_1.env.REDIS_URL },
            defaultJobOptions: {
                attempts: 3,
                backoff: { type: 'exponential', delay: 2000 },
                removeOnComplete: { age: 24 * 60 * 60, count: 1000 },
                removeOnFail: { age: 7 * 24 * 60 * 60 },
            },
        });
    }
    startWorker() {
        this.worker = new bullmq_1.Worker('campaign-emails', async (job) => {
            const { campaignEmailId, ...emailData } = job.data;
            const endTimer = metrics_1.emailSendDuration.startTimer();
            logger_1.logger.info(`Processing email job ${job.id} for campaign-email ${campaignEmailId}`);
            // Look up campaign ID for metrics
            const emailRecord = await database_1.prisma.campaignEmail.findUnique({
                where: { id: campaignEmailId },
                select: { campaignId: true },
            });
            const campaignId = emailRecord?.campaignId || 'unknown';
            const result = await email_service_1.emailService.sendCampaignEmail(emailData);
            endTimer();
            const status = result.success
                ? client_1.CampaignEmailStatus.SENT
                : client_1.CampaignEmailStatus.FAILED;
            await database_1.prisma.campaignEmail.update({
                where: { id: campaignEmailId },
                data: { status },
            });
            if (result.success) {
                (0, metrics_1.recordEmailSent)(campaignId);
                // Listmonk event sync
                listmonk_event_sync_service_1.listmonkEventSyncService.onCampaignEmailSent({
                    email: emailData.userEmail,
                    name: emailData.userName,
                    campaignSlug: emailData.campaignTitle,
                    postalCode: emailData.postalCode,
                }).catch(() => { });
            }
            else {
                (0, metrics_1.recordEmailFailed)(campaignId, 'send_failure');
                throw new Error(`Failed to send email to ${emailData.recipientEmail}`);
            }
            return { messageId: result.messageId, testMode: result.testMode };
        }, {
            connection: { url: env_1.env.REDIS_URL },
            concurrency: 3,
        });
        this.worker.on('completed', (job) => {
            logger_1.logger.info(`Email job ${job.id} completed`);
        });
        this.worker.on('failed', (job, err) => {
            logger_1.logger.error(`Email job ${job?.id} failed: ${err.message}`);
        });
        logger_1.logger.info('Email queue worker started');
    }
    async addCampaignEmail(data) {
        const job = await this.queue.add('campaign', data);
        return job.id;
    }
    async getStats() {
        const [waiting, active, completed, failed, paused] = await Promise.all([
            this.queue.getWaitingCount(),
            this.queue.getActiveCount(),
            this.queue.getCompletedCount(),
            this.queue.getFailedCount(),
            this.queue.isPaused(),
        ]);
        (0, metrics_1.setEmailQueueSize)(waiting + active);
        return { waiting, active, completed, failed, paused };
    }
    async pause() {
        await this.queue.pause();
        logger_1.logger.info('Email queue paused');
    }
    async resume() {
        await this.queue.resume();
        logger_1.logger.info('Email queue resumed');
    }
    async clean(grace = 24 * 60 * 60 * 1000) {
        const cleaned = await this.queue.clean(grace, 1000, 'completed');
        logger_1.logger.info(`Cleaned ${cleaned.length} completed jobs`);
        return cleaned.length;
    }
    async close() {
        if (this.worker) {
            await this.worker.close();
        }
        await this.queue.close();
        logger_1.logger.info('Email queue closed');
    }
}
exports.emailQueueService = new EmailQueueService();
//# sourceMappingURL=email-queue.service.js.map