import { getApiJwt } from './appwrite'

/**
 * Analytics & Tracking Utility
 * Handles UTM parameter tracking and event analytics
 */

export interface TrackingParams {
  utm_source?: string
  utm_medium?: string
  utm_campaign?: string
  utm_term?: string
  utm_content?: string
  gclid?: string // Google Ads Click ID
  fbclid?: string // Facebook Click ID
  ref?: string // General referrer
}

export interface ConversionEvent {
  type: 'page_view' | 'signup' | 'trial_start' | 'purchase' | 'email_connected' | 'onboarding_step' | 'provider_connected' | 'demo_used' | 'suggested_rules_generated' | 'rule_created' | 'rules_applied' | 'limit_reached' | 'upgrade_clicked' | 'referral_shared' | 'sort_completed' | 'account_deleted'
  userId?: string
  metadata?: Record<string, unknown>
  sessionId?: string
}

const STORAGE_KEY = 'emailsorter_utm_params'
const USER_ID_KEY = 'emailsorter_user_id'
const SESSION_ID_KEY = 'emailsorter_session_id'

/**
 * Parse UTM parameters from URL
 */
export function parseUTMParams(): TrackingParams {
  const params = new URLSearchParams(window.location.search)
  const utmParams: TrackingParams = {}

  const utmKeys: Array<keyof TrackingParams> = [
    'utm_source',
    'utm_medium',
    'utm_campaign',
    'utm_term',
    'utm_content',
    'gclid',
    'fbclid',
    'ref',
  ]

  utmKeys.forEach((key) => {
    const value = params.get(key)
    if (value) {
      utmParams[key] = value
    }
  })

  // If no UTM params but referrer exists, capture it
  if (!utmParams.utm_source && document.referrer) {
    try {
      const referrerUrl = new URL(document.referrer)
      if (referrerUrl.hostname !== window.location.hostname) {
        utmParams.ref = referrerUrl.hostname
      }
    } catch {
      // Invalid referrer URL, ignore
    }
  }

  return utmParams
}

/**
 * Store UTM parameters in localStorage (persists across sessions)
 */
export function storeUTMParams(params: TrackingParams): void {
  if (Object.keys(params).length === 0) return

  const existing = getStoredUTMParams()
  const merged = { ...existing, ...params }

  try {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(merged))
    
    // Set expiration (30 days)
    localStorage.setItem(`${STORAGE_KEY}_expiry`, String(Date.now() + 30 * 24 * 60 * 60 * 1000))
  } catch (error) {
    console.warn('Failed to store UTM parameters:', error)
  }
}

/**
 * Get stored UTM parameters from localStorage
 */
export function getStoredUTMParams(): TrackingParams {
  try {
    // Check expiry
    const expiry = localStorage.getItem(`${STORAGE_KEY}_expiry`)
    if (expiry && Date.now() > parseInt(expiry, 10)) {
      localStorage.removeItem(STORAGE_KEY)
      localStorage.removeItem(`${STORAGE_KEY}_expiry`)
      return {}
    }

    const stored = localStorage.getItem(STORAGE_KEY)
    return stored ? JSON.parse(stored) : {}
  } catch (error) {
    console.warn('Failed to get stored UTM parameters:', error)
    return {}
  }
}

/**
 * Clear stored UTM parameters
 */
export function clearUTMParams(): void {
  try {
    localStorage.removeItem(STORAGE_KEY)
    localStorage.removeItem(`${STORAGE_KEY}_expiry`)
  } catch (error) {
    console.warn('Failed to clear UTM parameters:', error)
  }
}

/**
 * Capture and store UTM parameters from current URL
 * Call this on page load or navigation
 */
export function captureUTMParams(): TrackingParams {
  const params = parseUTMParams()
  if (Object.keys(params).length > 0) {
    storeUTMParams(params)
  }
  return params
}

/**
 * Get all tracking parameters (from URL + stored)
 */
export function getAllTrackingParams(): TrackingParams {
  const urlParams = parseUTMParams()
  const storedParams = getStoredUTMParams()
  
  // URL params take precedence
  return { ...storedParams, ...urlParams }
}

/**
 * Track conversion event
 * Send tracking data to server or analytics service
 */
export async function trackEvent(
  event: ConversionEvent,
  trackingParams?: TrackingParams
): Promise<void> {
  const params = trackingParams || getAllTrackingParams()
  const userId = localStorage.getItem(USER_ID_KEY)

  const payload = {
    ...event,
    userId: event.userId || userId || undefined,
    sessionId: event.sessionId || getSessionId(),
    tracking: params,
    timestamp: new Date().toISOString(),
    page: window.location.pathname,
    referrer: document.referrer || undefined,
  }

  try {
    const jwt = await getApiJwt()
    if (!jwt) return

    await fetch('/api/analytics/track', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${jwt}`,
      },
      body: JSON.stringify(payload),
    }).catch(() => {})

    // Also log to console in development
    if (import.meta.env.DEV) {
      console.log('📊 Analytics Event:', event.type, payload)
    }
  } catch (error) {
    console.warn('Failed to track event:', error)
  }
}

/**
 * Track page view
 */
export function trackPageView(path?: string): void {
  trackEvent({
    type: 'page_view',
    metadata: {
      path: path || window.location.pathname,
      title: document.title,
    },
  })
}

/**
 * Track signup event
 */
export function trackSignup(userId: string, email: string): void {
  const trackingParams = getAllTrackingParams()
  
  trackEvent({
    type: 'signup',
    userId,
    metadata: {
      email: email,
      source: trackingParams.utm_source,
      medium: trackingParams.utm_medium,
      campaign: trackingParams.utm_campaign,
    },
  })

  // Store user ID for future events
  try {
    localStorage.setItem(USER_ID_KEY, userId)
  } catch (error) {
    console.warn('Failed to store user ID:', error)
  }
}

/**
 * Track trial start
 */
export function trackTrialStart(userId: string): void {
  trackEvent({
    type: 'trial_start',
    userId,
    metadata: {
      timestamp: new Date().toISOString(),
    },
  })
}

/**
 * Track purchase/subscription
 */
export function trackPurchase(userId: string, plan: string, amount: number): void {
  const trackingParams = getAllTrackingParams()

  trackEvent({
    type: 'purchase',
    userId,
    metadata: {
      plan,
      amount,
      currency: 'EUR',
      source: trackingParams.utm_source,
      medium: trackingParams.utm_medium,
      campaign: trackingParams.utm_campaign,
    },
  })
}

/**
 * Track email account connection
 */
export function trackEmailConnected(userId: string, provider: string): void {
  trackEvent({
    type: 'email_connected',
    userId,
    metadata: {
      provider,
      timestamp: new Date().toISOString(),
    },
  })
}

/**
 * Set user ID (for authenticated users)
 */
export function setUserId(userId: string): void {
  try {
    localStorage.setItem(USER_ID_KEY, userId)
  } catch (error) {
    console.warn('Failed to store user ID:', error)
  }
}

/**
 * Get stored user ID
 */
export function getUserId(): string | null {
  try {
    return localStorage.getItem(USER_ID_KEY)
  } catch {
    return null
  }
}

/**
 * Initialize analytics
 * Call this once on app startup
 */
export function initAnalytics(): void {
  // Capture UTM parameters from URL
  captureUTMParams()

  // Track initial page view
  trackPageView()

  // Track page views on navigation (will be handled by React Router)
}

/**
 * Get tracking parameters as query string (for API calls)
 */
export function getTrackingQueryString(): string {
  const params = getAllTrackingParams()
  const entries = Object.entries(params).filter(([, value]) => value)
  return entries.length > 0 
    ? '&' + new URLSearchParams(entries as string[][]).toString()
    : ''
}

/**
 * Get or create session ID
 */
function getSessionId(): string {
  try {
    let sessionId = sessionStorage.getItem(SESSION_ID_KEY)
    if (!sessionId) {
      sessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
      sessionStorage.setItem(SESSION_ID_KEY, sessionId)
    }
    return sessionId
  } catch {
    // Fallback if sessionStorage is not available
    return `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
  }
}

/**
 * Track onboarding step
 */
export function trackOnboardingStep(userId: string, step: string): void {
  trackEvent({
    type: 'onboarding_step',
    userId,
    metadata: {
      step,
      timestamp: new Date().toISOString(),
    },
  })
}

/**
 * Track provider connection
 */
export function trackProviderConnected(userId: string, provider: string): void {
  trackEvent({
    type: 'provider_connected',
    userId,
    metadata: {
      provider,
      timestamp: new Date().toISOString(),
    },
  })
}

/**
 * Track demo account usage
 */
export function trackDemoUsed(userId: string): void {
  trackEvent({
    type: 'demo_used',
    userId,
    metadata: {
      timestamp: new Date().toISOString(),
    },
  })
}

/**
 * Track sort completion
 */
export function trackSortCompleted(userId: string, sortedCount: number, isFirstRun: boolean): void {
  trackEvent({
    type: 'sort_completed',
    userId,
    metadata: {
      sortedCount,
      isFirstRun,
      timestamp: new Date().toISOString(),
    },
  })
}

/**
 * Track limit reached
 */
export function trackLimitReached(userId: string, limit: number, used: number): void {
  trackEvent({
    type: 'limit_reached',
    userId,
    metadata: {
      limit,
      used,
      timestamp: new Date().toISOString(),
    },
  })
}

/**
 * Track rules applied
 */
export function trackRulesApplied(userId: string, rulesCount: number): void {
  trackEvent({
    type: 'rules_applied',
    userId,
    metadata: {
      rulesCount,
      timestamp: new Date().toISOString(),
    },
  })
}

/**
 * Track upgrade clicked
 */
export function trackUpgradeClicked(userId: string, source: string): void {
  trackEvent({
    type: 'upgrade_clicked',
    userId,
    metadata: {
      source,
      timestamp: new Date().toISOString(),
    },
  })
}

/**
 * Track referral shared
 */
export function trackReferralShared(userId: string, referralCode: string): void {
  trackEvent({
    type: 'referral_shared',
    userId,
    metadata: {
      referralCode,
      timestamp: new Date().toISOString(),
    },
  })
}
