import {
  SESv2Client,
  SendEmailCommand,
  type SendEmailCommandInput,
} from '@aws-sdk/client-sesv2'
import {
  MailProviderError,
  type MailAdapter,
  type MailMessage,
  type MailResult,
} from './index.js'

export type SesAdapterConfig = {
  region: string
  credentials?: {
    accessKeyId: string
    secretAccessKey: string
    sessionToken?: string
  }
  client?: SESv2Client
}

function toList(value: string | string[] | undefined): string[] | undefined {
  if (value === undefined) return undefined
  return Array.isArray(value) ? value : [value]
}

function toCommandInput(msg: MailMessage): SendEmailCommandInput {
  const body: NonNullable<SendEmailCommandInput['Content']>['Simple'] = {
    Subject: { Data: msg.subject, Charset: 'UTF-8' },
    Body: {},
  }

  if (msg.html) {
    body.Body!.Html = { Data: msg.html, Charset: 'UTF-8' }
  }
  if (msg.text) {
    body.Body!.Text = { Data: msg.text, Charset: 'UTF-8' }
  }

  return {
    FromEmailAddress: msg.from,
    Destination: {
      ToAddresses: toList(msg.to),
      CcAddresses: toList(msg.cc),
      BccAddresses: toList(msg.bcc),
    },
    ReplyToAddresses: msg.replyTo ? [msg.replyTo] : undefined,
    Content: { Simple: body },
    EmailTags: msg.tags
      ? Object.entries(msg.tags).map(([Name, Value]) => ({ Name, Value }))
      : undefined,
  }
}

export function makeSesAdapter({
  region,
  credentials,
  client,
}: SesAdapterConfig): MailAdapter {
  const ses =
    client ??
    new SESv2Client({
      region,
      credentials,
    })

  return {
    async send(msg: MailMessage): Promise<MailResult> {
      try {
        // msg.idempotencyKey is intentionally NOT forwarded — SESv2 SendEmail has
        // no idempotency/client-token in the API model (verified 2026-06-14). The
        // dropped field is deliberate, never silent; cross-provider exactly-once is
        // a jobs' IdempotencyStore concern at dispatch, not the provider call.
        const response = await ses.send(new SendEmailCommand(toCommandInput(msg)))

        if (!response.MessageId) {
          throw new MailProviderError('ses returned no message id', 'ses', false, response)
        }

        return { id: response.MessageId, provider: 'ses' }
      } catch (err) {
        if (err instanceof MailProviderError) throw err

        const statusCode =
          typeof err === 'object' &&
          err !== null &&
          '$metadata' in err &&
          typeof err.$metadata === 'object' &&
          err.$metadata !== null &&
          'httpStatusCode' in err.$metadata &&
          typeof err.$metadata.httpStatusCode === 'number'
            ? err.$metadata.httpStatusCode
            : undefined

        throw new MailProviderError(
          err instanceof Error ? err.message : 'ses send failed',
          'ses',
          statusCode !== undefined && statusCode >= 500,
          err,
        )
      }
    },
  }
}
