//
//  Analytics.swift
//  Reflect
//
//  Singleton analytics manager wrapping PostHog SDK.
//  All analytics events flow through this single manager.
//

import Foundation
import PostHog
import UIKit

// MARK: - Analytics Manager

@MainActor
final class AnalyticsManager {

    // MARK: - Singleton

    static let shared = AnalyticsManager()

    // MARK: - Configuration

    private static let apiKey = "phc_3GsB3oqNft8Ykg2bJfE9MaJktzLAwr2EPMXQgwEFzAs"
    private static let host = "https://analytics.88oakapps.com"
    private static let optOutKey = "analyticsOptedOut"
    private static let sessionReplayKey = "analytics_session_replay_enabled"
    private static let iso8601Formatter = ISO8601DateFormatter()

    // MARK: - State

    var isOptedOut: Bool {
        UserDefaults.standard.bool(forKey: Self.optOutKey)
    }

    var sessionReplayEnabled: Bool {
        get {
            if UserDefaults.standard.object(forKey: Self.sessionReplayKey) == nil {
                return true
            }
            return UserDefaults.standard.bool(forKey: Self.sessionReplayKey)
        }
        set {
            UserDefaults.standard.set(newValue, forKey: Self.sessionReplayKey)
            if newValue {
                PostHogSDK.shared.startSessionRecording()
            } else {
                PostHogSDK.shared.stopSessionRecording()
            }
        }
    }

    private var isConfigured = false

    // MARK: - Initialization

    private init() {}

    // MARK: - Setup

    func configure() {
        guard !isConfigured else { return }

        let config = PostHogConfig(apiKey: Self.apiKey, host: Self.host)

        // Person profiles — .always creates anonymous person profiles for every user,
        // enabling accurate unique user counts without requiring identify() calls
        config.personProfiles = .always

        // Auto-capture — disabled for SwiftUI (PostHog docs recommend manual tracking)
        // captureElementInteractions: UIKit-only, generates noisy $autocapture events
        // captureScreenViews: produces meaningless SwiftUI internal names, duplicates manual trackScreen()
        config.captureElementInteractions = false
        config.captureApplicationLifecycleEvents = true
        config.captureScreenViews = false

        // Session replay
        config.sessionReplay = sessionReplayEnabled
        config.sessionReplayConfig.maskAllTextInputs = true
        config.sessionReplayConfig.maskAllImages = false
        config.sessionReplayConfig.captureNetworkTelemetry = true
        config.sessionReplayConfig.screenshotMode = true // Required for SwiftUI

        // Respect user opt-out preference
        if isOptedOut {
            config.optOut = true
        }

        #if DEBUG
        config.optOut = true // Prevent debug/test data from polluting production analytics
        #endif

        PostHogSDK.shared.setup(config)
        isConfigured = true

        // Register super properties
        updateSuperProperties()
    }

    // MARK: - Super Properties (attached to every event)

    func updateSuperProperties() {
        let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "unknown"
        let build = Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "unknown"
        let device = UIDevice.current.model
        let osVersion = UIDevice.current.systemVersion

        let defaults = GroupUserDefaults.groupDefaults
        var props: [String: Any] = [
            "app_version": version,
            "build_number": build,
            "device_model": device,
            "os_version": osVersion,
            "is_pro": IAPManager.shared.isSubscribed,
            "animations_enabled": !UIAccessibility.isReduceMotionEnabled,
            "selected_sports": [String](),
            "theme": "n/a",
            "icon_pack": "n/a",
            "voting_layout": "n/a",
            "day_view_style": "n/a",
            "mood_shape": "n/a",
            "personality_pack": "n/a",
            "privacy_lock_enabled": false,
            "healthkit_enabled": false,
            "days_filter_count": 0,
            "days_filter_all": false,
        ]

        // Theme
        if let themeRaw = defaults.string(forKey: UserDefaultsStore.Keys.theme.rawValue) {
            props["theme"] = themeRaw
        }

        // Icon pack
        if let iconPackRaw = defaults.object(forKey: UserDefaultsStore.Keys.moodImages.rawValue) as? Int,
           let iconPack = MoodImages(rawValue: iconPackRaw) {
            props["icon_pack"] = String(describing: iconPack)
        }

        // Voting layout
        if let layoutRaw = defaults.object(forKey: UserDefaultsStore.Keys.votingLayoutStyle.rawValue) as? Int,
           let layout = VotingLayoutStyle(rawValue: layoutRaw) {
            props["voting_layout"] = layout.displayName
        }

        // Day view style
        if let styleRaw = defaults.object(forKey: UserDefaultsStore.Keys.dayViewStyle.rawValue) as? Int,
           let style = DayViewStyle(rawValue: styleRaw) {
            props["day_view_style"] = style.displayName
        }

        // Shape
        if let shapeRaw = defaults.object(forKey: UserDefaultsStore.Keys.shape.rawValue) as? Int,
           let shape = BGShape(rawValue: shapeRaw) {
            props["mood_shape"] = String(describing: shape)
        }

        // Personality pack
        if let packRaw = defaults.object(forKey: UserDefaultsStore.Keys.personalityPack.rawValue) as? Int,
           let pack = PersonalityPack(rawValue: packRaw) {
            props["personality_pack"] = pack.title()
        }

        // Privacy lock
        props["privacy_lock_enabled"] = defaults.bool(forKey: UserDefaultsStore.Keys.privacyLockEnabled.rawValue)

        // HealthKit
        props["healthkit_enabled"] = defaults.bool(forKey: UserDefaultsStore.Keys.healthKitEnabled.rawValue)

        // Days filter
        let daysFilter = UserDefaultsStore.getDaysFilter()
        props["days_filter_count"] = daysFilter.count
        props["days_filter_all"] = daysFilter.count == 7

        PostHogSDK.shared.register(props)
    }

    func registerSuperProperties() {
        updateSuperProperties()
    }

    // MARK: - Event Tracking

    func track(_ event: Event) {
        guard isConfigured else { return }
        let (name, properties) = event.payload
        #if DEBUG
        print("[Analytics] \(name)", properties ?? [:])
        #endif
        PostHogSDK.shared.capture(name, properties: properties)
    }

    // MARK: - Screen Tracking (manual supplement to auto-capture)

    func trackScreen(_ screen: Screen, properties: [String: Any]? = nil) {
        guard isConfigured else { return }
        var props: [String: Any] = ["screen_name": screen.rawValue]
        if let properties { props.merge(properties) { _, new in new } }

        #if DEBUG
        print("[Analytics] screen_viewed: \(screen.rawValue)")
        #endif
        PostHogSDK.shared.capture("screen_viewed", properties: props)
    }

    // MARK: - Subscription Funnel

    func trackPaywallViewed(source: String) {
        guard isConfigured else { return }
        PostHogSDK.shared.capture("paywall_viewed", properties: [
            "source": source
        ])
    }

    func trackPurchaseStarted(productId: String, source: String) {
        guard isConfigured else { return }
        PostHogSDK.shared.capture("purchase_started", properties: [
            "product_id": productId,
            "source": source
        ])
    }

    func trackPurchaseCompleted(productId: String, source: String) {
        guard isConfigured else { return }
        PostHogSDK.shared.capture("purchase_completed", properties: [
            "product_id": productId,
            "source": source
        ])
    }

    func trackPurchaseFailed(productId: String?, source: String, error: String) {
        guard isConfigured else { return }
        var props: [String: Any] = [
            "source": source,
            "error": error
        ]
        if let productId {
            props["product_id"] = productId
        }
        PostHogSDK.shared.capture("purchase_failed", properties: props)
    }

    func trackPurchaseRestored(source: String) {
        guard isConfigured else { return }
        PostHogSDK.shared.capture("purchase_restored", properties: [
            "source": source
        ])
    }

    // MARK: - Opt In / Opt Out

    func optIn() {
        UserDefaults.standard.set(false, forKey: Self.optOutKey)
        if isConfigured {
            PostHogSDK.shared.optIn()
            PostHogSDK.shared.capture("analytics_toggled", properties: ["enabled": true])
        }
    }

    func optOut() {
        if isConfigured {
            PostHogSDK.shared.capture("analytics_toggled", properties: ["enabled": false])
        }
        UserDefaults.standard.set(true, forKey: Self.optOutKey)
        if isConfigured {
            PostHogSDK.shared.optOut()
        }
    }

    // MARK: - Person Properties (subscription segmentation)

    func updateSubscriptionStatus(_ status: String, type: String) {
        guard isConfigured else { return }
        PostHogSDK.shared.capture("$set", properties: [
            "$set": [
                "subscription_status": status,
                "subscription_type": type
            ]
        ])
    }

    func trackSubscriptionStatusObserved(
        status: String,
        type: String,
        source: String,
        isSubscribed: Bool,
        hasFullAccess: Bool,
        productId: String?,
        willAutoRenew: Bool?,
        isInGracePeriod: Bool?,
        trialDaysRemaining: Int?,
        expirationDate: Date?
    ) {
        guard isConfigured else { return }

        var props: [String: Any] = [
            "status": status,
            "type": type,
            "source": source,
            "is_subscribed": isSubscribed,
            "has_full_access": hasFullAccess
        ]

        if let productId {
            props["product_id"] = productId
        }
        if let willAutoRenew {
            props["will_auto_renew"] = willAutoRenew
        }
        if let isInGracePeriod {
            props["is_in_grace_period"] = isInGracePeriod
        }
        if let trialDaysRemaining {
            props["trial_days_remaining"] = trialDaysRemaining
        }
        if let expirationDate {
            props["expiration_date"] = Self.iso8601Formatter.string(from: expirationDate)
        }

        PostHogSDK.shared.capture("subscription_status_changed", properties: props)
        updateSubscriptionStatus(status, type: type)
    }

    // MARK: - Lifecycle

    func flush() {
        guard isConfigured else { return }
        PostHogSDK.shared.flush()
    }

    func reset() {
        guard isConfigured else { return }
        PostHogSDK.shared.reset()
    }
}

// MARK: - Screen Names

extension AnalyticsManager {
    enum Screen: String {
        case day = "day"
        case month = "month"
        case monthDetail = "month_detail"
        case year = "year"
        case insights = "insights"
        case settings = "settings"
        case customize = "customize"
        case onboarding = "onboarding"
        case onboardingSubscription = "onboarding_subscription"
        case paywall = "paywall"
        case entryDetail = "entry_detail"
        case noteEditor = "note_editor"
        case lockScreen = "lock_screen"
        case sharing = "sharing"
        case themePicker = "theme_picker"
        case iconPackPicker = "icon_pack_picker"
        case votingLayoutPicker = "voting_layout_picker"
        case dayStylePicker = "day_style_picker"
        case shapePicker = "shape_picker"
        case personalityPackPicker = "personality_pack_picker"
        case appThemePicker = "app_theme_picker"
        case dayFilterPicker = "day_filter_picker"
        case iconPicker = "icon_picker"
        case widgetCreator = "widget_creator"
        case widgetPicker = "widget_picker"
        case privacy = "privacy"
        case eula = "eula"
        case specialThanks = "special_thanks"
        case reminderTimePicker = "reminder_time_picker"
        case exportView = "export_view"
    }
}

// MARK: - Event Definitions

extension AnalyticsManager {
    enum Event {
        // MARK: Mood
        case moodLogged(mood: Int, entryType: String)
        case moodUpdated(mood: Int)
        case noteUpdated(characterCount: Int)
        case photoAdded
        case photoDeleted
        case missingEntriesFilled(count: Int)
        case entryDeleted(mood: Int)
        case allDataCleared
        case duplicatesRemoved(count: Int)

        // MARK: Customization
        case themeChanged(themeId: String)
        case themeApplied(themeName: String)
        case iconPackChanged(packId: Int)
        case votingLayoutChanged(layout: String)
        case dayViewStyleChanged(style: String)
        case moodShapeChanged(shapeId: Int)
        case personalityPackChanged(packTitle: String)
        case appIconChanged(iconTitle: String)
        case celebrationAnimationChanged(animation: String)

        // MARK: Widget
        case widgetViewed
        case widgetCreateTapped
        case widgetCreated
        case widgetUsed
        case widgetDeleted
        case widgetShuffled
        case widgetRandomized
        case widgetEyeUpdated(style: String)
        case widgetMouthUpdated(style: String)
        case widgetBackgroundUpdated(style: String)
        case widgetColorUpdated(part: String)

        // MARK: Notifications
        case notificationEnabled
        case notificationDisabled
        case reminderTimeUpdated
        case reminderTimeTapped

        // MARK: Onboarding
        case onboardingCompleted(dayId: String?)
        case onboardingSubscribeTapped
        case onboardingSkipped

        // MARK: Subscription
        case paywallSubscribeTapped(source: String)

        // MARK: Settings
        case settingsClosed
        case deleteToggleChanged(enabled: Bool)
        case hapticFeedbackToggled(enabled: Bool)
        case exportTapped
        case dataExported(format: String, count: Int)
        case importTapped
        case importSucceeded
        case importFailed(error: String?)
        case onboardingReshown

        // MARK: Privacy & Security
        case privacyLockEnabled
        case privacyLockDisabled
        case privacyLockEnableFailed
        case appLocked
        case biometricUnlockSuccess
        case biometricUnlockFailed(error: String)

        // MARK: HealthKit
        case healthKitAuthorized
        case healthKitAuthFailed(error: String)
        case healthKitEnableFailed
        case healthKitDisabled
        case healthKitNotAuthorized
        case healthKitSyncCompleted(total: Int, success: Int, failed: Int)

        // MARK: Navigation
        case tabSwitched(tab: String)
        case viewHeaderChanged(header: String)

        // MARK: Sharing
        case shareTemplateViewed(template: String)

        // MARK: Error
        case storageFallbackActivated

        // MARK: Legal
        case eulaViewed
        case privacyPolicyViewed
        case specialThanksViewed

        var payload: (name: String, properties: [String: Any]?) {
            switch self {
            // Mood
            case .moodLogged(let mood, let entryType):
                return ("mood_logged", ["mood_value": mood, "entry_type": entryType])
            case .moodUpdated(let mood):
                return ("mood_updated", ["mood_value": mood])
            case .noteUpdated(let count):
                return ("note_updated", ["character_count": count])
            case .photoAdded:
                return ("photo_added", nil)
            case .photoDeleted:
                return ("photo_deleted", nil)
            case .missingEntriesFilled(let count):
                return ("missing_entries_filled", ["count": count])
            case .entryDeleted(let mood):
                return ("entry_deleted", ["mood": mood])
            case .allDataCleared:
                return ("all_data_cleared", nil)
            case .duplicatesRemoved(let count):
                return ("duplicates_removed", ["count": count])

            // Customization
            case .themeChanged(let id):
                return ("theme_changed", ["theme_id": id])
            case .themeApplied(let name):
                return ("theme_applied", ["theme_name": name])
            case .iconPackChanged(let id):
                return ("icon_pack_changed", ["pack_id": id])
            case .votingLayoutChanged(let layout):
                return ("voting_layout_changed", ["layout": layout])
            case .dayViewStyleChanged(let style):
                return ("day_view_style_changed", ["style": style])
            case .moodShapeChanged(let id):
                return ("mood_shape_changed", ["shape_id": id])
            case .personalityPackChanged(let title):
                return ("personality_pack_changed", ["pack_title": title])
            case .appIconChanged(let title):
                return ("app_icon_changed", ["icon_title": title])
            case .celebrationAnimationChanged(let animation):
                return ("celebration_animation_changed", ["animation": animation])

            // Widget
            case .widgetViewed:
                return ("widget_viewed", nil)
            case .widgetCreateTapped:
                return ("widget_create_tapped", nil)
            case .widgetCreated:
                return ("widget_created", nil)
            case .widgetUsed:
                return ("widget_used", nil)
            case .widgetDeleted:
                return ("widget_deleted", nil)
            case .widgetShuffled:
                return ("widget_shuffled", nil)
            case .widgetRandomized:
                return ("widget_randomized", nil)
            case .widgetEyeUpdated(let style):
                return ("widget_eye_updated", ["style": style])
            case .widgetMouthUpdated(let style):
                return ("widget_mouth_updated", ["style": style])
            case .widgetBackgroundUpdated(let style):
                return ("widget_background_updated", ["style": style])
            case .widgetColorUpdated(let part):
                return ("widget_color_updated", ["part": part])

            // Notifications
            case .notificationEnabled:
                return ("notification_enabled", nil)
            case .notificationDisabled:
                return ("notification_disabled", nil)
            case .reminderTimeUpdated:
                return ("reminder_time_updated", nil)
            case .reminderTimeTapped:
                return ("reminder_time_tapped", nil)

            // Onboarding
            case .onboardingCompleted(let dayId):
                var props: [String: Any] = [:]
                if let dayId { props["day_id"] = dayId }
                return ("onboarding_completed", props.isEmpty ? nil : props)
            case .onboardingSubscribeTapped:
                return ("onboarding_subscribe_tapped", nil)
            case .onboardingSkipped:
                return ("onboarding_skipped", nil)

            // Subscription
            case .paywallSubscribeTapped(let source):
                return ("paywall_subscribe_tapped", ["source": source])

            // Settings
            case .settingsClosed:
                return ("settings_closed", nil)
            case .deleteToggleChanged(let enabled):
                return ("delete_toggle_changed", ["enabled": enabled])
            case .hapticFeedbackToggled(let enabled):
                return ("haptic_feedback_toggled", ["enabled": enabled])
            case .exportTapped:
                return ("export_tapped", nil)
            case .dataExported(let format, let count):
                return ("data_exported", ["format": format, "count": count])
            case .importTapped:
                return ("import_tapped", nil)
            case .importSucceeded:
                return ("import_succeeded", nil)
            case .importFailed(let error):
                return ("import_failed", error != nil ? ["error": error!] : nil)
            case .onboardingReshown:
                return ("onboarding_reshown", nil)

            // Privacy & Security
            case .privacyLockEnabled:
                return ("privacy_lock_enabled", nil)
            case .privacyLockDisabled:
                return ("privacy_lock_disabled", nil)
            case .privacyLockEnableFailed:
                return ("privacy_lock_enable_failed", nil)
            case .appLocked:
                return ("app_locked", nil)
            case .biometricUnlockSuccess:
                return ("biometric_unlock_success", nil)
            case .biometricUnlockFailed(let error):
                return ("biometric_unlock_failed", ["error": error])

            // HealthKit
            case .healthKitAuthorized:
                return ("healthkit_authorized", nil)
            case .healthKitAuthFailed(let error):
                return ("healthkit_auth_failed", ["error": error])
            case .healthKitEnableFailed:
                return ("healthkit_enable_failed", nil)
            case .healthKitDisabled:
                return ("healthkit_disabled", nil)
            case .healthKitNotAuthorized:
                return ("healthkit_not_authorized", nil)
            case .healthKitSyncCompleted(let total, let success, let failed):
                return ("healthkit_sync_completed", ["total": total, "success": success, "failed": failed])

            // Navigation
            case .tabSwitched(let tab):
                return ("tab_switched", ["tab": tab])
            case .viewHeaderChanged(let header):
                return ("view_header_changed", ["header": header])

            // Sharing
            case .shareTemplateViewed(let template):
                return ("share_template_viewed", ["template": template])

            // Error
            case .storageFallbackActivated:
                return ("storage_fallback_activated", nil)

            // Legal
            case .eulaViewed:
                return ("eula_viewed", nil)
            case .privacyPolicyViewed:
                return ("privacy_policy_viewed", nil)
            case .specialThanksViewed:
                return ("special_thanks_viewed", nil)
            }
        }
    }
}

// MARK: - SwiftUI Screen Tracking Modifier

import SwiftUI

struct ScreenTrackingModifier: ViewModifier {
    let screen: AnalyticsManager.Screen
    let properties: [String: Any]?

    func body(content: Content) -> some View {
        content.onAppear {
            AnalyticsManager.shared.trackScreen(screen, properties: properties)
        }
    }
}

extension View {
    func trackScreen(_ screen: AnalyticsManager.Screen, properties: [String: Any]? = nil) -> some View {
        modifier(ScreenTrackingModifier(screen: screen, properties: properties))
    }
}
