import { it, expect, vi, beforeEach } from 'vitest'

const sendMock = vi.fn()

vi.mock('resend', () => ({
  Resend: vi.fn(function MockResend() {
    return { emails: { send: sendMock } }
  }),
}))

import { makeResendAdapter } from './resend.js'
import { MailProviderError } from './index.js'

beforeEach(() => {
  sendMock.mockReset()
})

it('maps MailMessage fields including replyTo → reply_to', async () => {
  sendMock.mockResolvedValue({ data: { id: 're_123' }, error: null })

  const adapter = makeResendAdapter({ apiKey: 'test-key' })
  await adapter.send({
    from: 'from@example.com',
    to: 'to@example.com',
    replyTo: 'reply@example.com',
    subject: 'Subject',
    html: '<p>Hi</p>',
    text: 'Hi',
    headers: { 'X-Custom': '1' },
  })

  expect(sendMock.mock.calls[0]![0]).toMatchObject({
    from: 'from@example.com',
    to: ['to@example.com'],
    subject: 'Subject',
    html: '<p>Hi</p>',
    text: 'Hi',
    headers: { 'X-Custom': '1' },
    replyTo: 'reply@example.com',
  })
})

it('maps provider 4xx to MailProviderError with provider context', async () => {
  sendMock.mockResolvedValue({
    data: null,
    error: { message: 'invalid from', statusCode: 422 },
  })

  const adapter = makeResendAdapter({ apiKey: 'test-key' })
  await expect(
    adapter.send({
      from: 'from@example.com',
      to: 'to@example.com',
      subject: 'Subject',
      text: 'Hi',
    }),
  ).rejects.toMatchObject({
    name: 'MailProviderError',
    provider: 'resend',
    message: 'invalid from',
  } satisfies Partial<MailProviderError>)
})

it('forwards idempotencyKey as the send 2nd-arg options when present', async () => {
  sendMock.mockResolvedValue({ data: { id: 're_idem' }, error: null })

  const adapter = makeResendAdapter({ apiKey: 'test-key' })
  await adapter.send({
    from: 'from@example.com',
    to: 'to@example.com',
    subject: 'Subject',
    text: 'Hi',
    idempotencyKey: 'key-123',
  })

  expect(sendMock.mock.calls[0]![1]).toEqual({ idempotencyKey: 'key-123' })
})

it('omits the send 2nd-arg options when idempotencyKey is absent', async () => {
  sendMock.mockResolvedValue({ data: { id: 're_noidem' }, error: null })

  const adapter = makeResendAdapter({ apiKey: 'test-key' })
  await adapter.send({
    from: 'from@example.com',
    to: 'to@example.com',
    subject: 'Subject',
    text: 'Hi',
  })

  expect(sendMock.mock.calls[0]![1]).toBeUndefined()
})

it('returns MailResult on success', async () => {
  sendMock.mockResolvedValue({ data: { id: 're_ok' }, error: null })

  const adapter = makeResendAdapter({ apiKey: 'test-key' })
  const result = await adapter.send({
    from: 'from@example.com',
    to: 'to@example.com',
    subject: 'Subject',
    text: 'Hi',
  })

  expect(result).toEqual({ id: 're_ok', provider: 'resend' })
})
