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

interface InstantlyCredentials {
  apiKey: string
}

/**
 * Lead data for adding to an Instantly campaign
 */
export interface AddToCampaignLead {
  email: string
  first_name?: string
  last_name?: string
  company_name?: string
}

export interface AddToCampaignParams {
  campaign_id: string
  leads: AddToCampaignLead[]
}

export interface AddToCampaignResult {
  success: boolean
  added_count: number
  errors?: string[]
}

const INSTANTLY_API_BASE = 'https://api.instantly.ai/api/v2'

/**
 * Add leads to an Instantly campaign
 *
 * Adds one or more leads to an existing campaign. When leads are added,
 * they begin receiving the campaign sequence immediately (Day 0).
 *
 * @param credentials - Instantly API key
 * @param params - Campaign ID and array of leads to add
 * @param context - Execution context for logging
 * @returns Result with success status and count of added leads
 */
export async function addToCampaign(
  credentials: InstantlyCredentials,
  params: AddToCampaignParams,
  context?: ExecutionContext
): Promise<AddToCampaignResult> {
  const { apiKey } = credentials
  const { campaign_id, leads } = params

  // Validation
  if (!campaign_id) {
    throw new ToolingError('validation_error', 'Missing required parameter: campaign_id', {
      integration: 'instantly',
      method: 'addToCampaign'
    })
  }

  if (!leads || leads.length === 0) {
    throw new ToolingError('validation_error', 'Must provide at least one lead', {
      integration: 'instantly',
      method: 'addToCampaign'
    })
  }

  // Validate each lead has an email
  for (const lead of leads) {
    if (!lead.email) {
      throw new ToolingError('validation_error', 'Each lead must have an email address', {
        integration: 'instantly',
        method: 'addToCampaign'
      })
    }
  }

  const addLeadsUrl = `${INSTANTLY_API_BASE}/leads`

  // Transform leads to Instantly API format
  const requestBody = {
    campaign_id,
    leads: leads.map((lead) => ({
      email: lead.email,
      first_name: lead.first_name,
      last_name: lead.last_name,
      company_name: lead.company_name
    }))
  }

  if (context?.logger) {
    context.logger.info(
      `[InstantlyAdapter] Adding leads to campaign: campaign_id=${campaign_id} lead_count=${leads.length} executionId=${context.executionId}`
    )
  }

  const errors: string[] = []
  let addedCount = 0

  try {
    const response = await withRetry(async () => {
      const res = await fetch(addLeadsUrl, {
        method: 'POST',
        headers: {
          Authorization: `Bearer ${apiKey}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(requestBody)
      })

      if (!res.ok) {
        throw await createHttpError(res, {
          integration: 'instantly',
          method: 'addToCampaign',
          organizationId: context?.organizationId
        })
      }

      return res.json()
    }, DEFAULT_RETRY_POLICY)

    // Parse response - Instantly API returns different structures
    // Common response: { status: 'success', leads_uploaded: N }
    // Or: { uploaded: N, ... }
    if (response.status === 'success' || response.uploaded || response.leads_uploaded) {
      addedCount = response.leads_uploaded || response.uploaded || leads.length
    } else if (response.data) {
      // Wrapped response format
      addedCount = response.data.leads_uploaded || response.data.uploaded || leads.length
    } else {
      // Assume success if no error was thrown
      addedCount = leads.length
    }

    if (context?.logger) {
      context.logger.info(
        `[InstantlyAdapter] Leads added successfully: campaign_id=${campaign_id} added_count=${addedCount} executionId=${context.executionId}`
      )
    }
  } catch (error) {
    const errorMessage = error instanceof Error ? error.message : String(error)
    errors.push(errorMessage)

    if (context?.logger) {
      context.logger.error(
        `[InstantlyAdapter] Failed to add leads: campaign_id=${campaign_id} error=${errorMessage} executionId=${context.executionId}`
      )
    }
  }

  return {
    success: errors.length === 0,
    added_count: addedCount,
    errors: errors.length > 0 ? errors : undefined
  }
}
