import { MailProviderError, type MailMessage, type MailResult } from '@platform-modules/mail'
import type { ChannelAdapter, ChannelResult, NotifyEvent, RenderedMessage } from './index.js'

export type EmailRecipient = {
  to: string
  from: string
  replyTo?: string
  /** Used when rendered.subject is absent. */
  subjectFallback?: string
  idempotencyKey?: string
}

export type EmailChannelOpts = {
  mapMessage?: (
    rendered: RenderedMessage,
    recipient: EmailRecipient,
    event?: NotifyEvent,
  ) => MailMessage
}

function defaultMapMessage(
  rendered: RenderedMessage,
  recipient: EmailRecipient,
): MailMessage {
  return {
    from: recipient.from,
    to: recipient.to,
    replyTo: recipient.replyTo,
    subject: rendered.subject ?? recipient.subjectFallback ?? 'notification',
    text: rendered.body,
    html: rendered.html,
    idempotencyKey: recipient.idempotencyKey,
  }
}

export type MailSend = (msg: MailMessage) => Promise<MailResult>

/** Thin bridge — delegates send to `@platform-modules/mail`, does not re-implement. */
export function createEmailChannel(
  mail: { send: MailSend },
  opts?: EmailChannelOpts,
): ChannelAdapter {
  const mapMessage = opts?.mapMessage ?? ((r, recip) => defaultMapMessage(r, recip))

  return {
    channel: 'email',
    async send(rendered, recipient): Promise<ChannelResult> {
      const msg = mapMessage(rendered, recipient as EmailRecipient)

      try {
        const result = await mail.send(msg)
        return { ok: true, id: result.id }
      } catch (err) {
        if (err instanceof MailProviderError) {
          return {
            ok: false,
            error: {
              message: err.message,
              retryable: err.retryable,
              code: err.name,
            },
          }
        }
        return {
          ok: false,
          error: {
            message: err instanceof Error ? err.message : String(err),
            retryable: true,
          },
        }
      }
    },
  }
}
