import { ToolingError } from '../../../../../../types'
import type { ExecutionContext } from '../../../../../../../base/types'
import { withRetry, createHttpError, DEFAULT_RETRY_POLICY } from '../../../../../../../../../platform/resilience'
import type { ResendCredentials, SendEmailParams, SendEmailResult, ResendSendEmailResponse } from '../utils/types'

/**
 * Send an email using Resend API
 *
 * @param credentials - Resend API credentials (apiKey)
 * @param params - Email parameters (from, to, subject, html/text, etc.)
 * @param context - Execution context for logging
 * @returns Email ID and success status
 * @throws ToolingError if email sending fails
 *
 * @example
 * // Send a simple email
 * const result = await sendEmail(
 *   { apiKey: 're_xxx' },
 *   {
 *     from: 'Alex <alexl@elevasis.io>',
 *     to: 'john@example.com',
 *     subject: 'Discovery Call Reminder',
 *     html: '<p>Your call is tomorrow...</p>',
 *     headers: {
 *       'List-Unsubscribe': '<https://elevasis.io/api/unsubscribe?email=...>',
 *       'List-Unsubscribe-Post': 'List-Unsubscribe=One-Click'
 *     }
 *   },
 *   context
 * )
 */
export async function sendEmail(
  credentials: ResendCredentials,
  params: SendEmailParams,
  context?: ExecutionContext
): Promise<SendEmailResult> {
  const { apiKey } = credentials
  const { from, to, subject, html, text, replyTo, cc, bcc, headers, tags, idempotencyKey } = params

  // Validate required parameters
  if (!apiKey) {
    throw new ToolingError('credentials_invalid', 'Resend API credentials must include apiKey', {
      integration: 'resend',
      method: 'sendEmail'
    })
  }

  if (!from || !to || !subject) {
    throw new ToolingError('validation_error', 'From, to, and subject are required', {
      integration: 'resend',
      method: 'sendEmail',
      params: { from, to, subject }
    })
  }

  if (!html && !text) {
    throw new ToolingError('validation_error', 'Either html or text content is required', {
      integration: 'resend',
      method: 'sendEmail'
    })
  }

  // Build URL
  const url = 'https://api.resend.com/emails'

  // Build request body
  const requestBody: Record<string, unknown> = {
    from,
    to: Array.isArray(to) ? to : [to],
    subject
  }

  if (html) requestBody.html = html
  if (text) requestBody.text = text
  if (replyTo) requestBody.reply_to = replyTo
  if (cc) requestBody.cc = Array.isArray(cc) ? cc : [cc]
  if (bcc) requestBody.bcc = Array.isArray(bcc) ? bcc : [bcc]
  if (headers) requestBody.headers = headers
  if (tags) requestBody.tags = tags

  try {
    // Build request headers; include Idempotency-Key when provided so platform_internal
    // retries dedupe server-side instead of double-sending.
    const requestHeaders: Record<string, string> = {
      Authorization: `Bearer ${apiKey}`,
      'Content-Type': 'application/json'
    }
    if (idempotencyKey) {
      requestHeaders['Idempotency-Key'] = idempotencyKey
    }

    // Execute with retry logic
    const response = await withRetry(async () => {
      const res = await fetch(url, {
        method: 'POST',
        headers: requestHeaders,
        body: JSON.stringify(requestBody)
      })

      // Handle HTTP errors
      if (!res.ok) {
        throw await createHttpError(res, {
          integration: 'resend',
          method: 'sendEmail',
          organizationId: context?.organizationId
        })
      }

      return res
    }, DEFAULT_RETRY_POLICY)

    // Parse response
    const result = (await response.json()) as ResendSendEmailResponse

    // Log success
    if (context?.logger) {
      context.logger.info(
        `[ResendAdapter] Email sent: organizationId=${context.organizationId} executionId=${context.executionId} emailId=${result.id} to=${Array.isArray(to) ? to.join(',') : to}`
      )
    }

    // Return standardized result
    return {
      id: result.id,
      success: true
    }
  } catch (error) {
    // Re-throw ToolingError as-is
    if (error instanceof ToolingError) {
      throw error
    }

    // Wrap unknown errors
    throw new ToolingError('api_error', `Failed to send email via Resend: ${(error as Error).message}`, {
      integration: 'resend',
      method: 'sendEmail',
      organizationId: context?.organizationId,
      originalError: error
    })
  }
}
