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

interface InstantlyCredentials {
  apiKey: string
}

export interface GetCampaignAnalyticsParams {
  campaign_id: string
  start_date?: string
  end_date?: string
}

export interface GetCampaignAnalyticsResult {
  campaign_id: string
  sent: number
  opened: number
  unique_opened: number
  replied: number
  unique_replied: number
  bounced: number
  unsubscribed: number
  [key: string]: unknown
}

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

/**
 * Get analytics for an Instantly campaign
 *
 * Retrieves aggregated analytics data for a specific campaign including
 * sends, opens, replies, bounces, and unsubscribes. Despite being a read
 * operation, this endpoint uses POST per the Instantly API design.
 *
 * @param credentials - Instantly API key
 * @param params - Campaign ID and optional date range
 * @param context - Execution context for logging
 * @returns Campaign analytics including all engagement metrics
 */
export async function getCampaignAnalytics(
  credentials: InstantlyCredentials,
  params: GetCampaignAnalyticsParams,
  context?: ExecutionContext
): Promise<GetCampaignAnalyticsResult> {
  const { apiKey } = credentials
  const { campaign_id, start_date, end_date } = params

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

  const queryParams = new URLSearchParams()
  queryParams.set('id', campaign_id)
  if (start_date) queryParams.set('start_date', start_date)
  if (end_date) queryParams.set('end_date', end_date)

  const analyticsUrl = `${INSTANTLY_API_BASE}/campaigns/analytics?${queryParams.toString()}`

  if (context?.logger) {
    context.logger.info(
      `[InstantlyAdapter] Fetching campaign analytics: campaign_id=${campaign_id} executionId=${context.executionId}`
    )
  }

  const response = await withRetry(async () => {
    const res = await fetch(analyticsUrl, {
      headers: {
        Authorization: `Bearer ${apiKey}`
      }
    })

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

    return res.json()
  }, DEFAULT_RETRY_POLICY)

  // API returns an array of per-campaign objects with v2 field names
  const rawData = response.data ?? response
  const entries: Array<Record<string, unknown>> = Array.isArray(rawData) ? rawData : [rawData]

  // Find the matching campaign entry (API may return multiple if filter wasn't applied)
  const match = entries.find((e) => e.campaign_id === campaign_id) ?? entries[0]

  const totals = {
    campaign_id,
    sent: Number(match?.emails_sent_count ?? match?.sent ?? 0),
    opened: Number(match?.open_count ?? match?.opened ?? 0),
    unique_opened: Number(match?.open_count_unique ?? match?.unique_opened ?? 0),
    replied: Number(match?.reply_count ?? match?.replies ?? match?.replied ?? 0),
    unique_replied: Number(match?.reply_count_unique ?? match?.unique_replies ?? match?.unique_replied ?? 0),
    bounced: Number(match?.bounced_count ?? match?.bounced ?? 0),
    unsubscribed: Number(match?.unsubscribed_count ?? match?.unsubscribed ?? 0)
  }

  if (context?.logger) {
    context.logger.info(
      `[InstantlyAdapter] Campaign analytics fetched: campaign_id=${campaign_id} sent=${totals.sent} opened=${totals.opened} replied=${totals.replied} executionId=${context.executionId}`
    )
  }

  return totals
}
