import { ToolingError } from '../../../../../../types'
import { withRetry, DEFAULT_RETRY_POLICY } from '../../../../../../../../../platform/resilience'
import type { ExecutionContext } from '../../../../../../../base/types'
import type { MillionVerifierVerifyEmailResult } from '../../../../../types/millionverifier'

interface MillionVerifierCredentials {
  apiKey: string
}

export interface VerifyEmailParams {
  email: string
}

const MV_API_BASE = 'https://api.millionverifier.com/api/v3/'

/**
 * Verify an email address via MillionVerifier
 *
 * Calls the MillionVerifier single-verification endpoint. The API always returns
 * HTTP 200 -- errors are signalled by result === 'error' and a non-empty error field.
 *
 * Credits are deducted for ok/invalid/disposable results; catch_all and unknown are free.
 *
 * @param credentials - MillionVerifier API key
 * @param params - Email address to verify
 * @param context - Execution context for logging
 * @returns Normalized verification result in camelCase
 */
export async function verifyEmail(
  credentials: MillionVerifierCredentials,
  params: VerifyEmailParams,
  context?: ExecutionContext
): Promise<MillionVerifierVerifyEmailResult> {
  const { apiKey } = credentials
  const { email } = params

  if (!email) {
    throw new ToolingError('validation_error', 'Missing required parameter: email', {
      integration: 'millionverifier',
      method: 'verifyEmail'
    })
  }

  if (context?.logger) {
    context.logger.info(
      `[MillionVerifierAdapter] verifyEmail: email=${email} organizationId=${context.organizationId} executionId=${context.executionId}`
    )
  }

  const url = new URL(MV_API_BASE)
  url.searchParams.set('api', apiKey)
  url.searchParams.set('email', email)

  const response = await withRetry(async () => {
    const res = await fetch(url.toString(), {
      method: 'GET',
      signal: AbortSignal.timeout(60_000)
    })

    if (!res.ok) {
      throw new ToolingError('api_error', `MillionVerifier API returned HTTP ${res.status}`, {
        integration: 'millionverifier',
        method: 'verifyEmail',
        organizationId: context?.organizationId
      })
    }

    return res.json() as Promise<Record<string, unknown>>
  }, DEFAULT_RETRY_POLICY)

  const data = response as Record<string, unknown>

  // The API signals errors via result === 'error' with a non-empty error field
  if (data.result === 'error' && data.error) {
    throw new ToolingError('api_error', `MillionVerifier error: ${data.error as string}`, {
      integration: 'millionverifier',
      method: 'verifyEmail',
      organizationId: context?.organizationId
    })
  }

  if (context?.logger) {
    context.logger.info(
      `[MillionVerifierAdapter] verifyEmail complete: email=${email} result=${data.result ?? ''} quality=${data.quality ?? ''} organizationId=${context.organizationId}`
    )
  }

  return {
    email: (data.email as string) ?? email,
    quality: (data.quality as MillionVerifierVerifyEmailResult['quality']) ?? '',
    result: (data.result as MillionVerifierVerifyEmailResult['result']) ?? 'unknown',
    resultCode: (data.resultcode as MillionVerifierVerifyEmailResult['resultCode']) ?? 3,
    subresult: (data.subresult as string) ?? '',
    free: (data.free as boolean) ?? false,
    role: (data.role as boolean) ?? false,
    didYouMean: (data.didyoumean as string) ?? '',
    credits: (data.credits as number) ?? 0,
    executionTime: (data.executiontime as number) ?? 0,
    error: (data.error as string) ?? '',
    liveMode: (data.livemode as boolean) ?? false
  }
}
