import assert from 'node:assert/strict';
import test from 'node:test';
import { executeNotificationDispatch } from './delivery-engine';
import type { NotificationProvider } from '../types';

function createProvider(options: {
  validateError?: string;
  sendError?: string;
}): NotificationProvider {
  return {
    channel: 'email',
    key: 'smtp',
    async validate() {
      if (options.validateError) {
        throw new Error(options.validateError);
      }
    },
    async healthCheck() {
      return { ok: true };
    },
    async send() {
      if (options.sendError) {
        throw new Error(options.sendError);
      }

      return {
        providerMessageId: 'msg-1',
        acceptedRecipients: ['to@example.com'],
        rejectedRecipients: [],
      };
    },
  };
}

function createMessage() {
  return {
    dispatchId: 'dispatch-1',
    subject: 'Test',
    bodyText: 'Plain',
    bodyHtml: null,
    to: [{ email: 'to@example.com', name: null }],
    cc: [],
    bcc: [],
    replyTo: null,
    attachments: [],
    attachmentBuffers: [],
  };
}

test('executeNotificationDispatch marks success when provider sends', async () => {
  const result = await executeNotificationDispatch({
    provider: createProvider({}),
    message: createMessage(),
    retryCount: 0,
    maxRetryCount: 3,
  });

  assert.equal(result.status, 'sent');
  assert.equal(result.retryCount, 1);
  assert.equal(result.errorMessage, null);
  assert.equal(result.providerResult?.providerMessageId, 'msg-1');
  assert.ok(result.sentAt instanceof Date);
});

test('executeNotificationDispatch schedules retry before max retry count', async () => {
  const result = await executeNotificationDispatch({
    provider: createProvider({ sendError: 'SMTP offline' }),
    message: createMessage(),
    retryCount: 0,
    maxRetryCount: 3,
  });

  assert.equal(result.status, 'retry');
  assert.equal(result.retryCount, 1);
  assert.equal(result.errorMessage, 'SMTP offline');
  assert.equal(result.sentAt, null);
});

test('executeNotificationDispatch fails permanently at retry limit', async () => {
  const result = await executeNotificationDispatch({
    provider: createProvider({ validateError: 'SMTP host is not configured.' }),
    message: createMessage(),
    retryCount: 2,
    maxRetryCount: 3,
  });

  assert.equal(result.status, 'failed');
  assert.equal(result.retryCount, 3);
  assert.equal(result.errorMessage, 'SMTP host is not configured.');
});
