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

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

/**
 * Void/cancel a pending envelope
 *
 * @param credentials - SignatureAPI credentials (apiKey, optional apiUrl)
 * @param params - Void parameters (envelopeId, optional reason)
 * @param context - Execution context for logging
 * @returns Envelope ID and voided status
 * @throws ToolingError if voiding fails
 */
export async function voidEnvelope(
  credentials: SignatureApiCredentials,
  params: VoidEnvelopeParams,
  context?: ExecutionContext
): Promise<VoidEnvelopeResult> {
  const { apiKey, apiUrl = DEFAULT_API_URL } = credentials
  const { envelopeId, reason } = params

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

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

  try {
    const response = await withRetry(async () => {
      const res = await fetch(`${apiUrl}/envelopes/${envelopeId}/void`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-API-Key': apiKey
        },
        body: JSON.stringify({ reason: reason || 'Voided by system' })
      })

      if (!res.ok) {
        throw await createHttpError(res, {
          integration: 'signature-api',
          method: 'voidEnvelope',
          organizationId: context?.organizationId
        })
      }

      return res
    }, DEFAULT_RETRY_POLICY)

    const result = await response.json()

    // Log success
    if (context?.logger) {
      context.logger.info(
        `[SignatureApiAdapter] Envelope voided: organizationId=${context.organizationId} envelopeId=${envelopeId}`
      )
    }

    return {
      id: result.id,
      status: 'voided'
    }
  } catch (error) {
    // Re-throw ToolingError as-is
    if (error instanceof ToolingError) {
      throw error
    }

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