{"version":3,"file":"analytics.mjs","sources":["../../../src/lib/utils/analytics.ts"],"sourcesContent":["/**\n * @file Analytics Utilities\n * @description Telemetry and analytics wrapper with privacy controls,\n * consent management, and multiple provider support\n */\n\nimport { logger } from './logging';\nimport { globalEventBus } from './eventEmitter';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Analytics event types\n */\nexport type AnalyticsEventType =\n  | 'page_view'\n  | 'click'\n  | 'form_submit'\n  | 'error'\n  | 'performance'\n  | 'feature_usage'\n  | 'search'\n  | 'conversion'\n  | 'custom';\n\n/**\n * Analytics event\n */\nexport interface AnalyticsEvent {\n  type: AnalyticsEventType;\n  name: string;\n  properties?: Record<string, unknown>;\n  timestamp?: number;\n  userId?: string;\n  sessionId?: string;\n}\n\n/**\n * User properties for identification\n */\nexport interface UserProperties {\n  id?: string;\n  email?: string;\n  name?: string;\n  role?: string;\n  organization?: string;\n  plan?: string;\n  createdAt?: string;\n  [key: string]: unknown;\n}\n\n/**\n * Analytics provider interface\n */\nexport interface AnalyticsProvider {\n  name: string;\n  initialize(config: Record<string, unknown>): Promise<void>;\n  identify(userId: string, properties?: UserProperties): void;\n  track(event: AnalyticsEvent): void;\n  page(name: string, properties?: Record<string, unknown>): void;\n  reset(): void;\n  setUserProperties(properties: UserProperties): void;\n}\n\n/**\n * Consent categories\n */\nexport interface ConsentCategories {\n  necessary: boolean;\n  analytics: boolean;\n  marketing: boolean;\n  preferences: boolean;\n}\n\n/**\n * Analytics configuration\n */\nexport interface AnalyticsConfig {\n  /** Enable analytics */\n  enabled?: boolean;\n  /** Enable debug mode */\n  debug?: boolean;\n  /** Default consent settings */\n  defaultConsent?: Partial<ConsentCategories>;\n  /** PHI fields to exclude */\n  phiFields?: string[];\n  /** PII fields to hash */\n  piiFields?: string[];\n  /** Sample rate (0-1) */\n  sampleRate?: number;\n  /** Session timeout in ms */\n  sessionTimeout?: number;\n  /** Queue events when offline */\n  offlineQueue?: boolean;\n  /** Max queue size */\n  maxQueueSize?: number;\n}\n\n/**\n * Analytics context\n */\nexport interface AnalyticsContext {\n  page?: {\n    path: string;\n    title: string;\n    referrer: string;\n  };\n  device?: {\n    type: string;\n    os: string;\n    browser: string;\n    screen: string;\n  };\n  location?: {\n    timezone: string;\n    language: string;\n  };\n  campaign?: {\n    source?: string;\n    medium?: string;\n    campaign?: string;\n    term?: string;\n    content?: string;\n  };\n}\n\n// ============================================================================\n// Analytics Manager\n// ============================================================================\n\n/**\n * Analytics manager with privacy controls and multi-provider support\n */\nexport class AnalyticsManager {\n  private config: Required<AnalyticsConfig>;\n  private providers = new Map<string, AnalyticsProvider>();\n  private consent: ConsentCategories;\n  private userId: string | null = null;\n  private sessionId: string;\n  private sessionStart: number;\n  private eventQueue: AnalyticsEvent[] = [];\n  private context: AnalyticsContext = {};\n\n  constructor(config: AnalyticsConfig = {}) {\n    this.config = {\n      enabled: config.enabled ?? true,\n      debug: config.debug ?? false,\n      defaultConsent: config.defaultConsent ?? {},\n      phiFields: config.phiFields ?? [\n        'ssn',\n        'medicalRecordNumber',\n        'healthCondition',\n        'diagnosis',\n        'treatment',\n        'prescription',\n      ],\n      piiFields: config.piiFields ?? ['email', 'phone', 'address', 'name'],\n      sampleRate: config.sampleRate ?? 1,\n      sessionTimeout: config.sessionTimeout ?? 30 * 60 * 1000, // 30 minutes\n      offlineQueue: config.offlineQueue ?? true,\n      maxQueueSize: config.maxQueueSize ?? 100,\n    };\n\n    this.consent = {\n      necessary: true,\n      analytics: config.defaultConsent?.analytics ?? false,\n      marketing: config.defaultConsent?.marketing ?? false,\n      preferences: config.defaultConsent?.preferences ?? true,\n    };\n\n    this.sessionId = this.generateSessionId();\n    this.sessionStart = Date.now();\n\n    this.setupContext();\n    this.setupSessionTracking();\n  }\n\n  /**\n   * Register analytics provider\n   */\n  async registerProvider(\n    provider: AnalyticsProvider,\n    config: Record<string, unknown> = {}\n  ): Promise<void> {\n    try {\n      await provider.initialize(config);\n      this.providers.set(provider.name, provider);\n      logger.debug('[Analytics] Provider registered', { name: provider.name });\n    } catch (error) {\n      logger.error('[Analytics] Failed to register provider', {\n        name: provider.name,\n        error,\n      });\n    }\n  }\n\n  /**\n   * Remove provider\n   */\n  removeProvider(name: string): void {\n    this.providers.delete(name);\n  }\n\n  /**\n   * Set consent\n   */\n  setConsent(consent: Partial<ConsentCategories>): void {\n    this.consent = { ...this.consent, ...consent };\n\n    // Flush queue if analytics consent granted\n    if (consent.analytics === true && this.eventQueue.length > 0) {\n      this.flushQueue();\n    }\n\n    globalEventBus.emitSync('analytics:consentChanged', { consent: this.consent });\n    logger.debug('[Analytics] Consent updated', { consent: this.consent });\n  }\n\n  /**\n   * Get consent\n   */\n  getConsent(): ConsentCategories {\n    return { ...this.consent };\n  }\n\n  /**\n   * Identify user\n   */\n  identify(userId: string, properties?: UserProperties): void {\n    this.userId = userId;\n\n    if (!this.canTrack()) return;\n\n    const sanitizedProps = properties\n      ? (this.sanitizeProperties(properties as Record<string, unknown>) as UserProperties)\n      : undefined;\n\n    for (const provider of this.providers.values()) {\n      try {\n        provider.identify(userId, sanitizedProps);\n      } catch (error) {\n        logger.error('[Analytics] Identify failed', { provider: provider.name, error });\n      }\n    }\n\n    if (this.config.debug) {\n      logger.debug('[Analytics] User identified', { userId });\n    }\n  }\n\n  /**\n   * Track event\n   */\n  track(\n    name: string,\n    properties?: Record<string, unknown>,\n    type: AnalyticsEventType = 'custom'\n  ): void {\n    const event: AnalyticsEvent = {\n      type,\n      name,\n      properties: properties ? this.sanitizeProperties(properties) : undefined,\n      timestamp: Date.now(),\n      userId: this.userId ?? undefined,\n      sessionId: this.sessionId,\n    };\n\n    if (!this.canTrack()) {\n      // Queue event if offline queuing enabled\n      if (this.config.offlineQueue) {\n        this.queueEvent(event);\n      }\n      return;\n    }\n\n    this.sendEvent(event);\n  }\n\n  /**\n   * Track page view\n   */\n  page(name?: string, properties?: Record<string, unknown>): void {\n    const pageName = name ?? (typeof window !== 'undefined' ? window.location.pathname : '/');\n\n    // Update context\n    if (typeof window !== 'undefined') {\n      this.context.page = {\n        path: window.location.pathname,\n        title: document.title,\n        referrer: document.referrer,\n      };\n    }\n\n    if (!this.canTrack()) return;\n\n    const sanitizedProps = properties\n      ? this.sanitizeProperties(properties)\n      : undefined;\n\n    for (const provider of this.providers.values()) {\n      try {\n        provider.page(pageName, sanitizedProps);\n      } catch (error) {\n        logger.error('[Analytics] Page view failed', { provider: provider.name, error });\n      }\n    }\n\n    if (this.config.debug) {\n      logger.debug('[Analytics] Page view tracked', { name: pageName });\n    }\n  }\n\n  /**\n   * Track error\n   */\n  trackError(error: Error, context?: Record<string, unknown>): void {\n    this.track(\n      'error',\n      {\n        message: error.message,\n        name: error.name,\n        stack: error.stack?.substring(0, 500),\n        ...context,\n      },\n      'error'\n    );\n  }\n\n  /**\n   * Track performance metric\n   */\n  trackPerformance(metric: string, value: number, context?: Record<string, unknown>): void {\n    this.track(\n      metric,\n      {\n        value,\n        ...context,\n      },\n      'performance'\n    );\n  }\n\n  /**\n   * Track feature usage\n   */\n  trackFeature(feature: string, action: string, context?: Record<string, unknown>): void {\n    this.track(\n      `${feature}:${action}`,\n      context,\n      'feature_usage'\n    );\n  }\n\n  /**\n   * Track conversion\n   */\n  trackConversion(name: string, value?: number, context?: Record<string, unknown>): void {\n    this.track(\n      name,\n      {\n        value,\n        ...context,\n      },\n      'conversion'\n    );\n  }\n\n  /**\n   * Set user properties\n   */\n  setUserProperties(properties: UserProperties): void {\n    if (!this.canTrack()) return;\n\n    const sanitizedProps = this.sanitizeProperties(\n      properties as Record<string, unknown>\n    ) as UserProperties;\n\n    for (const provider of this.providers.values()) {\n      try {\n        provider.setUserProperties(sanitizedProps);\n      } catch (error) {\n        logger.error('[Analytics] Set user properties failed', {\n          provider: provider.name,\n          error,\n        });\n      }\n    }\n  }\n\n  /**\n   * Reset analytics (on logout)\n   */\n  reset(): void {\n    this.userId = null;\n    this.sessionId = this.generateSessionId();\n    this.sessionStart = Date.now();\n    this.eventQueue = [];\n\n    for (const provider of this.providers.values()) {\n      try {\n        provider.reset();\n      } catch (error) {\n        logger.error('[Analytics] Reset failed', { provider: provider.name, error });\n      }\n    }\n\n    logger.debug('[Analytics] Reset complete');\n  }\n\n  /**\n   * Get analytics context\n   */\n  getContext(): AnalyticsContext {\n    return { ...this.context };\n  }\n\n  /**\n   * Get session info\n   */\n  getSessionInfo(): { sessionId: string; duration: number } {\n    return {\n      sessionId: this.sessionId,\n      duration: Date.now() - this.sessionStart,\n    };\n  }\n\n  /**\n   * Generate session ID\n   */\n  private generateSessionId(): string {\n    return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n  }\n\n  /**\n   * Setup context information\n   */\n  private setupContext(): void {\n    if (typeof window === 'undefined') return;\n\n    this.context = {\n      page: {\n        path: window.location.pathname,\n        title: document.title,\n        referrer: document.referrer,\n      },\n      device: {\n        type: this.getDeviceType(),\n        os: this.getOS(),\n        browser: this.getBrowser(),\n        screen: `${window.screen.width}x${window.screen.height}`,\n      },\n      location: {\n        timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n        language: navigator.language,\n      },\n      campaign: this.getUTMParams(),\n    };\n  }\n\n  /**\n   * Get device type\n   */\n  private getDeviceType(): string {\n    const ua = navigator.userAgent;\n    if (/tablet/i.test(ua)) return 'tablet';\n    if (/mobile/i.test(ua)) return 'mobile';\n    return 'desktop';\n  }\n\n  /**\n   * Get OS\n   */\n  private getOS(): string {\n    const ua = navigator.userAgent;\n    if (/windows/i.test(ua)) return 'Windows';\n    if (/mac/i.test(ua)) return 'macOS';\n    if (/linux/i.test(ua)) return 'Linux';\n    if (/android/i.test(ua)) return 'Android';\n    if (/ios|iphone|ipad/i.test(ua)) return 'iOS';\n    return 'Unknown';\n  }\n\n  /**\n   * Get browser\n   */\n  private getBrowser(): string {\n    const ua = navigator.userAgent;\n    if (/chrome/i.test(ua)) return 'Chrome';\n    if (/firefox/i.test(ua)) return 'Firefox';\n    if (/safari/i.test(ua)) return 'Safari';\n    if (/edge/i.test(ua)) return 'Edge';\n    return 'Unknown';\n  }\n\n  /**\n   * Get UTM parameters\n   */\n  private getUTMParams(): AnalyticsContext['campaign'] {\n    if (typeof window === 'undefined') return {};\n\n    const params = new URLSearchParams(window.location.search);\n    return {\n      source: params.get('utm_source') ?? undefined,\n      medium: params.get('utm_medium') ?? undefined,\n      campaign: params.get('utm_campaign') ?? undefined,\n      term: params.get('utm_term') ?? undefined,\n      content: params.get('utm_content') ?? undefined,\n    };\n  }\n\n  /**\n   * Setup session tracking\n   */\n  private setupSessionTracking(): void {\n    if (typeof window === 'undefined') return;\n\n    // Reset session on activity after timeout\n    let lastActivity = Date.now();\n\n    const resetSessionIfNeeded = (): void => {\n      const now = Date.now();\n      if (now - lastActivity > this.config.sessionTimeout) {\n        this.sessionId = this.generateSessionId();\n        this.sessionStart = now;\n      }\n      lastActivity = now;\n    };\n\n    window.addEventListener('click', resetSessionIfNeeded, { passive: true });\n    window.addEventListener('keydown', resetSessionIfNeeded, { passive: true });\n    window.addEventListener('scroll', resetSessionIfNeeded, { passive: true });\n  }\n\n  /**\n   * Check if tracking is allowed\n   */\n  private canTrack(): boolean {\n    if (!this.config.enabled) return false;\n    if (!this.consent.analytics) return false;\n\n    // Sample rate check\n    if (this.config.sampleRate < 1) {\n      if (Math.random() > this.config.sampleRate) return false;\n    }\n\n    return true;\n  }\n\n  /**\n   * Sanitize event properties\n   */\n  private sanitizeProperties(\n    properties: Record<string, unknown>\n  ): Record<string, unknown> {\n    const sanitized: Record<string, unknown> = {};\n\n    for (const [key, value] of Object.entries(properties)) {\n      // Remove PHI fields entirely\n      if (this.config.phiFields.includes(key.toLowerCase())) {\n        continue;\n      }\n\n      // Hash PII fields\n      if (this.config.piiFields.includes(key.toLowerCase())) {\n        sanitized[key] = this.hashValue(String(value));\n        continue;\n      }\n\n      sanitized[key] = value;\n    }\n\n    return sanitized;\n  }\n\n  /**\n   * Simple hash function for PII\n   */\n  private hashValue(value: string): string {\n    let hash = 0;\n    for (let i = 0; i < value.length; i++) {\n      const char = value.charCodeAt(i);\n      hash = (hash << 5) - hash + char;\n      hash = hash & hash;\n    }\n    return `hashed_${Math.abs(hash).toString(16)}`;\n  }\n\n  /**\n   * Send event to providers\n   */\n  private sendEvent(event: AnalyticsEvent): void {\n    for (const provider of this.providers.values()) {\n      try {\n        provider.track(event);\n      } catch (error) {\n        logger.error('[Analytics] Track failed', { provider: provider.name, error });\n      }\n    }\n\n    if (this.config.debug) {\n      logger.debug('[Analytics] Event tracked', { event });\n    }\n  }\n\n  /**\n   * Queue event for later\n   */\n  private queueEvent(event: AnalyticsEvent): void {\n    if (this.eventQueue.length >= this.config.maxQueueSize) {\n      this.eventQueue.shift(); // Remove oldest\n    }\n    this.eventQueue.push(event);\n  }\n\n  /**\n   * Flush event queue\n   */\n  private flushQueue(): void {\n    const events = [...this.eventQueue];\n    this.eventQueue = [];\n\n    for (const event of events) {\n      this.sendEvent(event);\n    }\n\n    if (events.length > 0) {\n      logger.debug('[Analytics] Queue flushed', { count: events.length });\n    }\n  }\n}\n\n// ============================================================================\n// Console Analytics Provider (for development)\n// ============================================================================\n\n/**\n * Console analytics provider for development\n */\nclass ConsoleAnalyticsProvider implements AnalyticsProvider {\n  name = 'console';\n\n  async initialize(): Promise<void> {\n    await Promise.resolve(); // Satisfy require-await lint rule\n    logger.info('[ConsoleAnalytics] Initialized');\n  }\n\n  identify(userId: string, properties?: UserProperties): void {\n    console.group('🔵 Analytics: Identify');\n    console.info('User ID:', userId);\n    if (properties) console.info('Properties:', properties);\n    console.groupEnd();\n  }\n\n  track(event: AnalyticsEvent): void {\n    console.group(`📊 Analytics: ${event.type}`);\n    console.info('Event:', event.name);\n    if (event.properties) console.info('Properties:', event.properties);\n    console.info('Timestamp:', new Date(event.timestamp ?? Date.now()).toISOString());\n    console.groupEnd();\n  }\n\n  page(name: string, properties?: Record<string, unknown>): void {\n    console.group('📄 Analytics: Page View');\n    console.info('Page:', name);\n    if (properties) console.info('Properties:', properties);\n    console.groupEnd();\n  }\n\n  reset(): void {\n    logger.info('[ConsoleAnalytics] Reset');\n  }\n\n  setUserProperties(properties: UserProperties): void {\n    console.info('👤 Analytics: User Properties', properties);\n  }\n}\n\nexport default ConsoleAnalyticsProvider;\n\n// ============================================================================\n// Default Instance\n// ============================================================================\n\n/**\n * Global analytics manager instance\n */\nexport const analytics = new AnalyticsManager({\n  debug: import.meta.env.DEV,\n});\n\n// Register console provider in development\nif (import.meta.env.DEV) {\n  void analytics.registerProvider(new ConsoleAnalyticsProvider());\n}\n\n// ============================================================================\n// Convenience Functions\n// ============================================================================\n\n/**\n * Track event\n */\nexport function trackEvent(\n  name: string,\n  properties?: Record<string, unknown>,\n  type?: AnalyticsEventType\n): void {\n  analytics.track(name, properties, type);\n}\n\n/**\n * Track page view\n */\nexport function trackPageView(name?: string, properties?: Record<string, unknown>): void {\n  analytics.page(name, properties);\n}\n\n/**\n * Identify user\n */\nexport function identifyUser(userId: string, properties?: UserProperties): void {\n  analytics.identify(userId, properties);\n}\n\n/**\n * Track error\n */\nexport function trackError(error: Error, context?: Record<string, unknown>): void {\n  analytics.trackError(error, context);\n}\n\n/**\n * Track performance metric\n */\nexport function trackPerformance(\n  metric: string,\n  value: number,\n  context?: Record<string, unknown>\n): void {\n  analytics.trackPerformance(metric, value, context);\n}\n\n/**\n * Track feature usage\n */\nexport function trackFeature(\n  feature: string,\n  action: string,\n  context?: Record<string, unknown>\n): void {\n  analytics.trackFeature(feature, action, context);\n}\n\n/**\n * Set analytics consent\n */\nexport function setAnalyticsConsent(consent: Partial<ConsentCategories>): void {\n  analytics.setConsent(consent);\n}\n\n/**\n * Reset analytics\n */\nexport function resetAnalytics(): void {\n  analytics.reset();\n}\n"],"names":["AnalyticsManager","config","provider","logger","error","name","consent","globalEventBus","userId","properties","sanitizedProps","type","event","pageName","context","metric","value","feature","action","ua","params","lastActivity","resetSessionIfNeeded","now","sanitized","key","hash","char","events","ConsoleAnalyticsProvider","analytics","trackEvent","trackPageView","identifyUser","trackError","trackPerformance","trackFeature","setAnalyticsConsent","resetAnalytics"],"mappings":"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"}