/**
 * Completion-email coverage for the WhatsApp Nurturing module.
 *
 * WhatsApp is the one module that does NOT pass the auto-fill mapping to
 * completeJob() directly — routes/aiContext.ts wraps it as
 * `{ autoFillData, result }`. These tests pin that the wrapped shape still
 * produces exactly one email on success and none on failure, and that the
 * campaign name reaches the subject line.
 */

const sendSystemEmailMock = jest.fn().mockResolvedValue({ success: true });
const findOneMock = jest.fn();

jest.mock('../../email/transactionalMailer', () => ({
  sendSystemEmail: (...args: any[]) => sendSystemEmailMock(...args),
}));

jest.mock('../../../models', () => ({
  getModels: () => ({ User: { findOne: (...args: any[]) => findOneMock(...args) } }),
}));

jest.mock('../../notificationService', () => ({
  notificationService: { notifyUser: jest.fn().mockResolvedValue(undefined) },
}));

jest.mock('../../../utils/requestContext', () => ({
  getRequestContext: () => ({ userId: 'user-1', organizationId: 'company-1' }),
}));

import { createJob, completeJob, failJob } from '../aiJobManager';

const flush = () => new Promise((resolve) => setImmediate(resolve));

/** The exact payload routes/aiContext.ts builds for generate-messages. */
function whatsappJobPayload(campaignName: string) {
  return {
    autoFillData: {
      name: campaignName,
      messages: [{ id: 'm1', day: 1, copy: 'hi', goal: 'g', cta: 'c' }],
      sequencePlan: [{ day: 1, theme: 'Welcome' }],
    },
    result: {
      success: true,
      messages: [{ id: 'm1', day: 1, copy: 'hi', goal: 'g', cta: 'c' }],
      provider: 'claude',
    },
  };
}

describe('WhatsApp Nurturing — AI generation completion email', () => {
  beforeEach(() => {
    sendSystemEmailMock.mockClear();
    findOneMock.mockReset();
    findOneMock.mockReturnValue({
      lean: () => Promise.resolve({
        panelSettings: { aiGenerationNotifications: { enabled: true, recipients: ['ops@bizzfly.com'] } },
      }),
    });
  });

  it('sends exactly one email when generate-messages completes', async () => {
    const job = createJob('whatsapp-nurturing', 'company-1', 'whatsapp-nurturing');

    completeJob(job.jobId, whatsappJobPayload('Q3 Lead Nurture'), 'generated');
    await flush();

    expect(sendSystemEmailMock).toHaveBeenCalledTimes(1);
    const arg = sendSystemEmailMock.mock.calls[0][0];
    expect(arg.to).toBe('ops@bizzfly.com');
    expect(arg.html).toContain('AI generation completed successfully');
    expect(arg.html).toContain('WhatsApp Nurturing');
  });

  it('names the module and campaign in the subject', async () => {
    const job = createJob('whatsapp-nurturing', 'company-1', 'whatsapp-nurturing');

    completeJob(job.jobId, whatsappJobPayload('Q3 Lead Nurture'), 'generated');
    await flush();

    expect(sendSystemEmailMock.mock.calls[0][0].subject).toBe('AI Generation Completed: Q3 Lead Nurture');
  });

  it('sends one email for the sequence-plan job shape too', async () => {
    const job = createJob('whatsapp-nurturing', 'company-1', 'whatsapp-nurturing');

    completeJob(job.jobId, { autoFillData: { name: 'Plan Only' }, plan: [{ day: 1 }] }, 'generated');
    await flush();

    expect(sendSystemEmailMock).toHaveBeenCalledTimes(1);
    expect(sendSystemEmailMock.mock.calls[0][0].subject).toBe('AI Generation Completed: Plan Only');
  });

  it('does not email twice if completion is signalled twice', async () => {
    const job = createJob('whatsapp-nurturing', 'company-1', 'whatsapp-nurturing');

    completeJob(job.jobId, whatsappJobPayload('Once'), 'generated');
    completeJob(job.jobId, whatsappJobPayload('Once'), 'generated');
    await flush();

    expect(sendSystemEmailMock).toHaveBeenCalledTimes(1);
  });

  it('does not email when the pipeline fails', async () => {
    const job = createJob('whatsapp-nurturing', 'company-1', 'whatsapp-nurturing');

    failJob(job.jobId, 'Pipeline failed');
    await flush();

    expect(sendSystemEmailMock).not.toHaveBeenCalled();
  });

  it('does not let a mailer failure escape into the generation flow', async () => {
    sendSystemEmailMock.mockRejectedValueOnce(new Error('SMTP down'));
    const job = createJob('whatsapp-nurturing', 'company-1', 'whatsapp-nurturing');

    expect(() => completeJob(job.jobId, whatsappJobPayload('Boom'), 'generated')).not.toThrow();
    await flush();

    expect(sendSystemEmailMock).toHaveBeenCalledTimes(1);
  });
});
