//
//  ReflectApp.swift
//  Shared
//
//  Created by Trey Tartt on 1/5/22.
//

import SwiftUI
import SwiftData
import BackgroundTasks
import WidgetKit

@main
struct ReflectApp: App {
    @Environment(\.scenePhase) private var scenePhase
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

    let dataController = DataController.shared
    @StateObject var iapManager = IAPManager.shared
    @StateObject var authManager = BiometricAuthManager()
    @StateObject var healthKitManager = HealthKitManager.shared
    @AppStorage(UserDefaultsStore.Keys.firstLaunchDate.rawValue, store: GroupUserDefaults.groupDefaults) private var firstLaunchDate = Date()
    @State private var showSubscriptionFromWidget = false
    @State private var showStorageFallbackAlert = SharedModelContainer.isUsingInMemoryFallback

    init() {
        // Configure UI test mode before anything else
        if UITestMode.isUITesting {
            UITestMode.configureIfNeeded()
        }

        AnalyticsManager.shared.configure()

        BGTaskScheduler.shared.cancelAllTaskRequests()
        BGTaskScheduler.shared.register(forTaskWithIdentifier: BGTask.updateDBMissingID, using: nil) { (task) in
            guard let processingTask = task as? BGProcessingTask else { return }
            BGTask.runFillInMissingDatesTask(task: processingTask)
        }
        UNUserNotificationCenter.current().setBadgeCount(0)

        // Reset tips session on app launch
        ReflectTipsManager.shared.resetSession()

        // Initialize Live Activity scheduler
        LiveActivityScheduler.shared.scheduleBasedOnCurrentTime()

        // Initialize Watch Connectivity for cross-device widget updates
        _ = WatchConnectivityManager.shared
    }

    var body: some Scene {
        WindowGroup {
            ZStack {
                MainTabView(dayView: DayView(viewModel: DayViewViewModel(addMonthStartWeekdayPadding: false)),
                            monthView: MonthView(viewModel: DayViewViewModel(addMonthStartWeekdayPadding: true)),
                            yearView: YearView(viewModel: YearViewModel()),
                            insightsView: InsightsView())
                .modelContainer(dataController.container)
                .environmentObject(iapManager)
                .environmentObject(authManager)
                .environmentObject(healthKitManager)
                .sheet(isPresented: $showSubscriptionFromWidget) {
                    ReflectSubscriptionStoreView(source: "widget_deeplink")
                        .environmentObject(iapManager)
                }
                .onOpenURL { url in
                    handleDeepLink(url)
                }
                .alert("Data Storage Unavailable",
                       isPresented: $showStorageFallbackAlert) {
                    Button("OK", role: .cancel) { }
                } message: {
                    Text("Your mood data cannot be saved permanently. Please restart the app. If the problem persists, reinstall the app.")
                }
                .onAppear {
                    if SharedModelContainer.isUsingInMemoryFallback {
                        AnalyticsManager.shared.track(.storageFallbackActivated)
                    }
                    if let url = AppDelegate.pendingDeepLinkURL {
                        AppDelegate.pendingDeepLinkURL = nil
                        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
                            handleDeepLink(url)
                        }
                    }
                }

                // Lock screen overlay
                if authManager.isLockEnabled && !authManager.isUnlocked {
                    LockScreenView(authManager: authManager)
                        .transition(.opacity)
                }
            }
        }.onChange(of: scenePhase) { _, newPhase in
            if newPhase == .background {
                BGTask.scheduleBackgroundProcessing()
                WidgetCenter.shared.reloadAllTimelines()
                // Flush pending analytics events
                AnalyticsManager.shared.flush()
                // Lock the app when going to background
                authManager.lock()
            }

            if newPhase == .active {
                UNUserNotificationCenter.current().setBadgeCount(0)

                // Authenticate if locked - this must happen immediately on main thread
                if authManager.isLockEnabled && !authManager.isUnlocked {
                    Task {
                        await authManager.authenticate()
                    }
                }

                // Defer all non-critical foreground work to avoid blocking UI
                Task(priority: .utility) {
                    // Refresh from disk to pick up widget/watch changes
                    DataController.shared.refreshFromDisk()

                    // Fill in any missing dates (moved from AppDelegate)
                    DataController.shared.fillInMissingDates()

                    // Clean up any duplicate entries (after backfill so backfill dupes are caught)
                    DataController.shared.removeDuplicates()

                    // Reschedule notifications for new title
                    LocalNotification.rescheduleNotifiations()

                    // Update super properties on foreground
                    AnalyticsManager.shared.updateSuperProperties()
                }

                // Defer Live Activity scheduling (heavy DB operations)
                Task(priority: .utility) {
                    await LiveActivityScheduler.shared.scheduleBasedOnCurrentTime()
                }

                // Catch up on side effects from widget/watch votes
                Task(priority: .utility) {
                    await MoodLogger.shared.processPendingSideEffects()
                }

                // Check subscription status (network call) - throttled
                Task(priority: .background) {
                    await iapManager.checkSubscriptionStatus()
                    await iapManager.trackSubscriptionAnalytics(source: "app_foreground")
                }
            }
        }
    }

    private func handleDeepLink(_ url: URL) {
        if url.scheme == "reflect" && url.host == "subscribe" {
            showSubscriptionFromWidget = true
        }
    }
}
