import { ToolingError } from '../../../../../../types'
import type { ExecutionContext } from '../../../../../../../base/types'
import { withRetry, createHttpError, DEFAULT_RETRY_POLICY } from '../../../../../../../../../platform/resilience'
import type { SignatureApiCredentials, GetEnvelopeParams, GetEnvelopeResult } from '../utils/types'

const DEFAULT_API_URL = 'https://api.signatureapi.com/v1'

/**
 * SignatureAPI raw response format (snake_case)
 */
interface SignatureApiGetEnvelopeResponse {
  id: string
  title: string
  status: 'processing' | 'pending' | 'completed' | 'declined' | 'voided'
  created_at: string
  completed_at?: string
  metadata: Record<string, string>
  recipients: Array<{
    key: string
    name: string
    email: string
    status: 'pending' | 'signed' | 'declined'
    signed_at?: string
  }>
}

/**
 * Get envelope details from SignatureAPI
 *
 * @param credentials - SignatureAPI credentials (apiKey, optional apiUrl)
 * @param params - Envelope ID to retrieve
 * @param context - Execution context for logging
 * @returns Envelope details including status and recipients
 * @throws ToolingError if retrieval fails
 *
 * @example
 * const result = await getEnvelope(
 *   { apiKey: 'key_test_xxx' },
 *   { envelopeId: 'env_xxx' },
 *   context
 * )
 * // result.status: 'processing', 'pending', 'completed', 'declined', 'voided'
 */
export async function getEnvelope(
  credentials: SignatureApiCredentials,
  params: GetEnvelopeParams,
  context?: ExecutionContext
): Promise<GetEnvelopeResult> {
  const { apiKey, apiUrl = DEFAULT_API_URL } = credentials
  const { envelopeId } = params

  // Validate required parameters
  if (!apiKey) {
    throw new ToolingError('credentials_invalid', 'SignatureAPI credentials must include apiKey', {
      integration: 'signature-api',
      method: 'getEnvelope'
    })
  }

  if (!envelopeId) {
    throw new ToolingError('validation_error', 'Envelope ID is required', {
      integration: 'signature-api',
      method: 'getEnvelope'
    })
  }

  // Build URL
  const url = `${apiUrl}/envelopes/${encodeURIComponent(envelopeId)}`

  try {
    // Execute with retry logic
    const response = await withRetry(async () => {
      const res = await fetch(url, {
        method: 'GET',
        headers: {
          'X-API-Key': apiKey
        }
      })

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

      return res
    }, DEFAULT_RETRY_POLICY)

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

    // Log success
    if (context?.logger) {
      context.logger.info(
        `[SignatureApiAdapter] Envelope retrieved: organizationId=${context.organizationId} executionId=${context.executionId} envelopeId=${result.id} status=${result.status}`
      )
    }

    // Return standardized result (snake_case -> camelCase)
    return {
      id: result.id,
      title: result.title,
      status: result.status,
      createdAt: result.created_at,
      completedAt: result.completed_at,
      metadata: result.metadata || {},
      recipients: result.recipients.map((recipient) => ({
        key: recipient.key,
        name: recipient.name,
        email: recipient.email,
        status: recipient.status,
        signedAt: recipient.signed_at
      }))
    }
  } catch (error) {
    // Re-throw ToolingError as-is
    if (error instanceof ToolingError) {
      throw error
    }

    // Wrap unknown errors
    throw new ToolingError('api_error', `Failed to get envelope from SignatureAPI: ${(error as Error).message}`, {
      integration: 'signature-api',
      method: 'getEnvelope',
      organizationId: context?.organizationId,
      envelopeId,
      originalError: error
    })
  }
}
