import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import Database from 'better-sqlite3';
import { runMigrations } from '../../db/migrations.js';
import { EmailQueueWorker } from '../email-queue-worker.js';
function createMockSes() {
    return {
        isConfigured: () => true,
        sendEmail: vi.fn().mockResolvedValue({ messageId: 'ses-msg-001' }),
        getSendQuota: vi.fn().mockResolvedValue({ maxSendRate: 14, max24HourSend: 50000, sentLast24Hours: 0 }),
    };
}
describe('EmailQueueWorker', () => {
    let db;
    let ses;
    beforeEach(() => {
        db = new Database(':memory:');
        runMigrations(db);
        ses = createMockSes();
    });
    afterEach(() => { db.close(); });
    function seedQueue(campaignStatus = 'sending') {
        db.prepare("INSERT INTO leads (id, email) VALUES ('l1', 'user@test.com')").run();
        db.prepare("INSERT INTO email_campaigns (id, name, subject, body_html, from_email, status, total_recipients) VALUES ('c1', 'Test', 'Hi', '<p>Hi</p>', 'a@b.com', ?, 1)").run(campaignStatus);
        db.prepare("INSERT INTO email_queue (id, campaign_id, lead_id, to_email, status) VALUES ('q1', 'c1', 'l1', 'user@test.com', 'pending')").run();
    }
    it('should process pending emails', async () => {
        seedQueue();
        const worker = new EmailQueueWorker({ db, ses, rateLimit: 14, jwtSecret: 'a'.repeat(32), serverUrl: 'http://localhost:3001' });
        await worker.tick();
        const row = db.prepare("SELECT status, ses_message_id FROM email_queue WHERE id = 'q1'").get();
        expect(row.status).toBe('sent');
        expect(row.ses_message_id).toBe('ses-msg-001');
    });
    it('should skip paused campaigns', async () => {
        seedQueue('paused');
        const worker = new EmailQueueWorker({ db, ses, rateLimit: 14, jwtSecret: 'a'.repeat(32), serverUrl: 'http://localhost:3001' });
        await worker.tick();
        const row = db.prepare("SELECT status FROM email_queue WHERE id = 'q1'").get();
        expect(row.status).toBe('pending');
    });
    it('should increment attempts on failure', async () => {
        seedQueue();
        ses.sendEmail.mockRejectedValueOnce(new Error('SES throttle'));
        const worker = new EmailQueueWorker({ db, ses, rateLimit: 14, jwtSecret: 'a'.repeat(32), serverUrl: 'http://localhost:3001' });
        await worker.tick();
        const row = db.prepare("SELECT status, attempts, error FROM email_queue WHERE id = 'q1'").get();
        expect(row.status).toBe('pending');
        expect(row.attempts).toBe(1);
        expect(row.error).toContain('SES throttle');
    });
    it('should mark as failed after 3 attempts', async () => {
        seedQueue();
        db.prepare("UPDATE email_queue SET attempts = 2 WHERE id = 'q1'").run();
        ses.sendEmail.mockRejectedValueOnce(new Error('Permanent fail'));
        const worker = new EmailQueueWorker({ db, ses, rateLimit: 14, jwtSecret: 'a'.repeat(32), serverUrl: 'http://localhost:3001' });
        await worker.tick();
        const row = db.prepare("SELECT status, attempts FROM email_queue WHERE id = 'q1'").get();
        expect(row.status).toBe('failed');
        expect(row.attempts).toBe(3);
    });
    it('should update campaign counters', async () => {
        seedQueue();
        const worker = new EmailQueueWorker({ db, ses, rateLimit: 14, jwtSecret: 'a'.repeat(32), serverUrl: 'http://localhost:3001' });
        await worker.tick();
        const campaign = db.prepare("SELECT sent_count FROM email_campaigns WHERE id = 'c1'").get();
        expect(campaign.sent_count).toBe(1);
    });
    it('should recover stale sending items on startup', () => {
        seedQueue();
        db.prepare("UPDATE email_queue SET status = 'sending', attempts = 1 WHERE id = 'q1'").run();
        const worker = new EmailQueueWorker({ db, ses, rateLimit: 14, jwtSecret: 'a'.repeat(32), serverUrl: 'http://localhost:3001' });
        worker.recover();
        const row = db.prepare("SELECT status FROM email_queue WHERE id = 'q1'").get();
        expect(row.status).toBe('pending');
    });
    it('should mark stale sending as failed when max attempts reached', () => {
        seedQueue();
        db.prepare("UPDATE email_queue SET status = 'sending', attempts = 3 WHERE id = 'q1'").run();
        const worker = new EmailQueueWorker({ db, ses, rateLimit: 14, jwtSecret: 'a'.repeat(32), serverUrl: 'http://localhost:3001' });
        worker.recover();
        const row = db.prepare("SELECT status FROM email_queue WHERE id = 'q1'").get();
        expect(row.status).toBe('failed');
    });
    it('should detect campaign completion', async () => {
        seedQueue();
        const worker = new EmailQueueWorker({ db, ses, rateLimit: 14, jwtSecret: 'a'.repeat(32), serverUrl: 'http://localhost:3001' });
        await worker.tick();
        const campaign = db.prepare("SELECT status, completed_at FROM email_campaigns WHERE id = 'c1'").get();
        expect(campaign.status).toBe('sent');
        expect(campaign.completed_at).toBeTruthy();
    });
});
//# sourceMappingURL=email-queue-worker.test.js.map