package com.craigvg.lichun_android.managers import android.content.Context import android.os.Bundle import android.util.Log import com.craigvg.lichun_android.BuildConfig import com.google.firebase.analytics.FirebaseAnalytics import com.google.firebase.crashlytics.FirebaseCrashlytics import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject import javax.inject.Singleton /** * Analytics manager for tracking app events * * Firebase initialization is gated behind BuildConfig.FIREBASE_ENABLED. * Set FIREBASE_ENABLED to true in build.gradle.kts and add google-services.json * to enable Firebase Analytics and Crashlytics. * * Ported from iOS AnalyticsManager.swift */ @Singleton class AnalyticsManager @Inject constructor( @ApplicationContext private val context: Context ) { @Volatile private var isInitialized = false private var userId: String? = null private var firebaseAnalytics: FirebaseAnalytics? = null private var crashlytics: FirebaseCrashlytics? = null companion object { private const val TAG = "AnalyticsManager" // Event names const val EVENT_SCREEN_VIEW = "screen_view" const val EVENT_BUTTON_TAP = "button_tap" const val EVENT_ACTIVITY_START = "activity_start" const val EVENT_ACTIVITY_COMPLETE = "activity_complete" const val EVENT_RELATIONSHIP_CHANGE = "relationship_change" const val EVENT_PURCHASE_START = "purchase_start" const val EVENT_PURCHASE_COMPLETE = "purchase_complete" const val EVENT_ACHIEVEMENT_UNLOCK = "achievement_unlock" const val EVENT_QUEST_COMPLETE = "quest_complete" const val EVENT_DAILY_REWARD_CLAIM = "daily_reward_claim" const val EVENT_GAME_SPEED_CHANGE = "game_speed_change" const val EVENT_MESSAGE_SENT = "message_sent" const val EVENT_SWIPE_ACTION = "swipe_action" const val EVENT_EVENT_CLAIM = "event_claim" // Parameter names const val PARAM_SCREEN_NAME = "screen_name" const val PARAM_BUTTON_NAME = "button_name" const val PARAM_ACTIVITY_ID = "activity_id" const val PARAM_ACTIVITY_NAME = "activity_name" const val PARAM_RELATIONSHIP_ID = "relationship_id" const val PARAM_RELATIONSHIP_TYPE = "relationship_type" const val PARAM_PRODUCT_ID = "product_id" const val PARAM_PRODUCT_NAME = "product_name" const val PARAM_PRICE = "price" const val PARAM_ACHIEVEMENT_ID = "achievement_id" const val PARAM_ACHIEVEMENT_NAME = "achievement_name" const val PARAM_QUEST_ID = "quest_id" const val PARAM_DAY_NUMBER = "day_number" const val PARAM_GAME_SPEED = "game_speed" const val PARAM_CHARACTER_ID = "character_id" const val PARAM_SWIPE_DIRECTION = "swipe_direction" const val PARAM_EVENT_ID = "event_id" const val PARAM_EVENT_TYPE = "event_type" } /** * Initialize analytics * When FIREBASE_ENABLED is true, initializes FirebaseAnalytics and Crashlytics */ fun initialize() { if (isInitialized) return synchronized(this) { if (isInitialized) return if (BuildConfig.FIREBASE_ENABLED) { try { firebaseAnalytics = FirebaseAnalytics.getInstance(context) crashlytics = FirebaseCrashlytics.getInstance() isInitialized = true Log.d(TAG, "Firebase Analytics initialized successfully") } catch (e: Exception) { Log.w(TAG, "Firebase not configured - analytics disabled: ${e.message}") isInitialized = true } } else { isInitialized = true Log.d(TAG, "AnalyticsManager initialized (stub - Firebase not enabled)") } } } /** * Log a custom event */ fun logEvent(eventName: String, params: Map? = null) { if (!isInitialized) { initialize() } firebaseAnalytics?.let { analytics -> val bundle = Bundle().apply { params?.forEach { (key, value) -> when (value) { is String -> putString(key, value) is Int -> putInt(key, value) is Long -> putLong(key, value) is Double -> putDouble(key, value) is Float -> putFloat(key, value) is Boolean -> putBoolean(key, value) else -> putString(key, value.toString()) } } } analytics.logEvent(eventName, bundle) } Log.d(TAG, "Event: $eventName | Params: $params") } /** * Log screen view */ fun logScreenView(screenName: String) { logEvent(EVENT_SCREEN_VIEW, mapOf(PARAM_SCREEN_NAME to screenName)) } /** * Log button tap */ fun logButtonTap(buttonName: String, screenName: String? = null) { val params = mutableMapOf(PARAM_BUTTON_NAME to buttonName) screenName?.let { params[PARAM_SCREEN_NAME] = it } logEvent(EVENT_BUTTON_TAP, params) } /** * Log activity start */ fun logActivityStart(activityId: String, activityName: String) { logEvent(EVENT_ACTIVITY_START, mapOf( PARAM_ACTIVITY_ID to activityId, PARAM_ACTIVITY_NAME to activityName )) } /** * Log activity completion */ fun logActivityComplete(activityId: String, activityName: String) { logEvent(EVENT_ACTIVITY_COMPLETE, mapOf( PARAM_ACTIVITY_ID to activityId, PARAM_ACTIVITY_NAME to activityName )) } /** * Log relationship change */ fun logRelationshipChange(relationshipId: String, type: String) { logEvent(EVENT_RELATIONSHIP_CHANGE, mapOf( PARAM_RELATIONSHIP_ID to relationshipId, PARAM_RELATIONSHIP_TYPE to type )) } /** * Log purchase start */ fun logPurchaseStart(productId: String, productName: String, price: Double) { logEvent(EVENT_PURCHASE_START, mapOf( PARAM_PRODUCT_ID to productId, PARAM_PRODUCT_NAME to productName, PARAM_PRICE to price )) } /** * Log purchase completion */ fun logPurchaseComplete(productId: String, productName: String, price: Double) { logEvent(EVENT_PURCHASE_COMPLETE, mapOf( PARAM_PRODUCT_ID to productId, PARAM_PRODUCT_NAME to productName, PARAM_PRICE to price )) } /** * Log achievement unlock */ fun logAchievementUnlock(achievementId: String, achievementName: String) { logEvent(EVENT_ACHIEVEMENT_UNLOCK, mapOf( PARAM_ACHIEVEMENT_ID to achievementId, PARAM_ACHIEVEMENT_NAME to achievementName )) } /** * Log quest completion */ fun logQuestComplete(questId: String) { logEvent(EVENT_QUEST_COMPLETE, mapOf(PARAM_QUEST_ID to questId)) } /** * Log daily reward claim */ fun logDailyRewardClaim(dayNumber: Int) { logEvent(EVENT_DAILY_REWARD_CLAIM, mapOf(PARAM_DAY_NUMBER to dayNumber)) } /** * Log game speed change */ fun logGameSpeedChange(speed: Int) { logEvent(EVENT_GAME_SPEED_CHANGE, mapOf(PARAM_GAME_SPEED to speed)) } /** * Log message sent */ fun logMessageSent(characterId: String) { logEvent(EVENT_MESSAGE_SENT, mapOf(PARAM_CHARACTER_ID to characterId)) } /** * Log swipe action (dating) */ fun logSwipeAction(characterId: String, direction: String) { logEvent(EVENT_SWIPE_ACTION, mapOf( PARAM_CHARACTER_ID to characterId, PARAM_SWIPE_DIRECTION to direction )) } /** * Log event claim */ fun logEventClaim(eventId: String, eventType: String) { logEvent(EVENT_EVENT_CLAIM, mapOf( PARAM_EVENT_ID to eventId, PARAM_EVENT_TYPE to eventType )) } // MARK: - User & Error Tracking /** * Set user ID for analytics and crash reports */ fun setUserId(userId: String) { this.userId = userId firebaseAnalytics?.setUserId(userId) crashlytics?.setUserId(userId) Log.d(TAG, "User ID set: $userId") } /** * Set custom key for crash reports */ fun setCustomKey(key: String, value: String) { crashlytics?.setCustomKey(key, value) Log.d(TAG, "Custom key set: $key = $value") } /** * Log a non-fatal error */ fun logError(exception: Throwable) { crashlytics?.recordException(exception) Log.e(TAG, "Error logged: ${exception.message}", exception) } /** * Log a custom message for debugging */ fun logMessage(message: String) { crashlytics?.log(message) Log.d(TAG, "Message: $message") } }