import { it, expect, vi, beforeEach } from 'vitest'
import { SendEmailCommand } from '@aws-sdk/client-sesv2'

const sendMock = vi.fn()

vi.mock('@aws-sdk/client-sesv2', async (importOriginal) => {
  const actual = await importOriginal<typeof import('@aws-sdk/client-sesv2')>()
  return {
    ...actual,
    SESv2Client: vi.fn().mockImplementation(() => ({
      send: sendMock,
    })),
  }
})

import { makeSesAdapter } from './ses.js'
import { MailProviderError } from './index.js'

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

it('maps MailMessage to SendEmailCommand input', async () => {
  sendMock.mockResolvedValue({ MessageId: 'ses-1' })

  const adapter = makeSesAdapter({
    region: 'eu-west-1',
    client: { send: sendMock } as never,
  })

  await adapter.send({
    from: 'from@example.com',
    to: ['to@example.com'],
    cc: 'cc@example.com',
    replyTo: 'reply@example.com',
    subject: 'Subject',
    html: '<p>Hi</p>',
    text: 'Hi',
    tags: { campaign: 'welcome' },
  })

  expect(sendMock).toHaveBeenCalledOnce()
  const command = sendMock.mock.calls[0]![0] as SendEmailCommand
  expect(command.input).toMatchObject({
    FromEmailAddress: 'from@example.com',
    Destination: {
      ToAddresses: ['to@example.com'],
      CcAddresses: ['cc@example.com'],
    },
    ReplyToAddresses: ['reply@example.com'],
    Content: {
      Simple: {
        Subject: { Data: 'Subject', Charset: 'UTF-8' },
        Body: {
          Html: { Data: '<p>Hi</p>', Charset: 'UTF-8' },
          Text: { Data: 'Hi', Charset: 'UTF-8' },
        },
      },
    },
    EmailTags: [{ Name: 'campaign', Value: 'welcome' }],
  })
})

it('maps provider errors to MailProviderError', async () => {
  const err = Object.assign(new Error('throttled'), {
    $metadata: { httpStatusCode: 429 },
  })
  sendMock.mockRejectedValue(err)

  const adapter = makeSesAdapter({
    region: 'eu-west-1',
    client: { send: sendMock } as never,
  })

  await expect(
    adapter.send({
      from: 'from@example.com',
      to: 'to@example.com',
      subject: 'Subject',
      text: 'Hi',
    }),
  ).rejects.toBeInstanceOf(MailProviderError)
})

it('returns MailResult with MessageId on success', async () => {
  sendMock.mockResolvedValue({ MessageId: 'ses-ok' })

  const adapter = makeSesAdapter({
    region: 'eu-west-1',
    client: { send: sendMock } as never,
  })

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

  expect(result).toEqual({ id: 'ses-ok', provider: 'ses' })
})
