import SwiftUI
import ComposeApp

/// Shared authentication state manager
@MainActor
class AuthenticationManager: ObservableObject {
    static let shared = AuthenticationManager()

    @Published var isAuthenticated: Bool = false
    @Published var isVerified: Bool = false
    @Published var isCheckingAuth: Bool = true

    private init() {
        // NOTE: Do NOT call checkAuthenticationStatus() here.
        // AuthenticationManager.shared may be initialized before DataManager.initialize()
        // completes in iOSApp.init(), causing a race condition. Instead, RootView
        // triggers the auth check via .task {} after the view appears.
    }

    func checkAuthenticationStatus() {
        if UITestRuntime.isEnabled {
            isAuthenticated = DataManager.shared.isAuthenticated()
            isVerified = isAuthenticated
            isCheckingAuth = false
            return
        }

        isCheckingAuth = true

        // Check if token exists via DataManager (single source of truth)
        guard DataManager.shared.isAuthenticated() else {
            isAuthenticated = false
            isVerified = false
            isCheckingAuth = false
            return
        }

        isAuthenticated = true

        // Fetch current user to validate token and check verification status
        Task { @MainActor in
            do {
                // Lookups are already initialized by iOSApp.init() at startup
                // and refreshed by scenePhase .active handler — no need to call again here

                let result = try await APILayer.shared.getCurrentUser(forceRefresh: true)

                if let success = result as? ApiResultSuccess<User> {
                    self.isVerified = success.data?.verified ?? false

                    // Register device for push notifications for authenticated users
                    PushNotificationManager.shared.registerDeviceAfterLogin()

                    // Verify subscription entitlements with backend for verified users
                    if self.isVerified {
                        await StoreKitManager.shared.verifyEntitlementsOnLaunch()
                    }
                } else if result is ApiResultError {
                    // Token is invalid, clear all data via DataManager
                    DataManager.shared.clear()
                    self.isAuthenticated = false
                    self.isVerified = false
                }
            } catch {
                #if DEBUG
                print("Failed to check auth status: \(error)")
                #endif
                // Distinguish network errors from auth errors
                let nsError = error as NSError
                if nsError.domain == NSURLErrorDomain {
                    // Network error — keep authenticated state, user may be offline
                    #if DEBUG
                    print("Network error during auth check, keeping auth state")
                    #endif
                } else {
                    // Auth error — token is invalid
                    DataManager.shared.clear()
                    self.isAuthenticated = false
                    self.isVerified = false
                }
            }

            self.isCheckingAuth = false
        }
    }

    func login(verified: Bool) {
        isAuthenticated = true
        isVerified = verified

        guard !UITestRuntime.isEnabled else { return }

        // Register device for push notifications now that user is authenticated
        PushNotificationManager.shared.registerDeviceAfterLogin()
    }

    func markVerified() {
        isVerified = true

        guard !UITestRuntime.isEnabled else { return }

        // Lookups are already initialized at app start or during login/register
        // Just verify subscription entitlements after user becomes verified
        Task {
            await StoreKitManager.shared.verifyEntitlementsOnLaunch()
            print("✅ Subscription entitlements verified after email verification")
        }
    }

    func logout() {
        // Call APILayer logout which clears DataManager
        Task {
            _ = try? await APILayer.shared.logout()
        }

        // Clear widget data (tasks and auth token)
        WidgetDataManager.shared.clearCache()
        WidgetDataManager.shared.clearAuthToken()

        // Clear authenticated image cache
        AuthenticatedImage.clearCache()

        // Update authentication state
        isAuthenticated = false
        isVerified = false

        // Note: We don't reset onboarding state on logout
        // so returning users go to login screen, not onboarding

        #if DEBUG
        print("AuthenticationManager: Logged out - all state reset")
        #endif
    }

    /// Reset onboarding state (for testing or re-onboarding)
    func resetOnboarding() {
        OnboardingState.shared.reset()
    }
}

/// Root view that handles authentication flow: loading -> onboarding -> login -> verify email -> main app
struct RootView: View {
    @EnvironmentObject private var themeManager: ThemeManager
    @StateObject private var authManager = AuthenticationManager.shared
    @StateObject private var onboardingState = OnboardingState.shared
    @State private var refreshID = UUID()
    @Binding var deepLinkResetToken: String?

    var body: some View {
        ZStack(alignment: .topLeading) {
            Group {
                if authManager.isCheckingAuth {
                    // Show loading while checking auth status
                    loadingView
                        .accessibilityIdentifier(AccessibilityIdentifiers.Common.loadingIndicator)
                } else if !onboardingState.hasCompletedOnboarding {
                    // Show onboarding for first-time users (includes auth + verification steps)
                    // This takes precedence because we need to finish the onboarding flow
                    ZStack(alignment: .topLeading) {
                        OnboardingCoordinator(onComplete: {
                            // Onboarding complete - mark verified and refresh the view
                            authManager.markVerified()
                            // Force refresh all data so tasks created during onboarding appear
                            Task {
                                _ = try? await APILayer.shared.getMyResidences(forceRefresh: true)
                                _ = try? await APILayer.shared.getTasks(forceRefresh: true)
                            }
                            refreshID = UUID()
                        })
                        Color.clear
                            .frame(width: 1, height: 1)
                            .accessibilityIdentifier("ui.root.onboarding")
                    }
                } else if !authManager.isAuthenticated {
                    // Show login screen for returning users
                    ZStack(alignment: .topLeading) {
                        LoginView(resetToken: $deepLinkResetToken)
                        Color.clear
                            .frame(width: 1, height: 1)
                            .accessibilityIdentifier("ui.root.login")
                    }
                } else if !authManager.isVerified {
                    // Show email verification screen (for returning users who haven't verified)
                    VerifyEmailView(
                        onVerifySuccess: {
                            authManager.markVerified()
                        },
                        onLogout: {
                            authManager.logout()
                        }
                    )
                } else {
                    // Show main app
                    ZStack(alignment: .topLeading) {
                        MainTabView(refreshID: refreshID)
                        Color.clear
                            .frame(width: 1, height: 1)
                            .accessibilityIdentifier("ui.root.mainTabs")
                    }
                }
            }
            Color.clear
                .frame(width: 1, height: 1)
                .accessibilityIdentifier("ui.app.ready")
        }
        .task {
            // Trigger auth check here, after iOSApp.init() has completed
            // DataManager.initialize(). This avoids the race condition where
            // checkAuthenticationStatus() runs before DataManager is ready.
            if authManager.isCheckingAuth {
                authManager.checkAuthenticationStatus()
            }
        }
    }

    private var loadingView: some View {
        ZStack {
            Color.appBackgroundPrimary
                .ignoresSafeArea()

            VStack(spacing: 16) {
                ProgressView()
                    .scaleEffect(1.5)
                    .tint(Color.appPrimary)

                Text("Loading...")
                    .font(.subheadline)
                    .foregroundColor(Color.appTextSecondary)
            }
        }
    }
}
