//
//  RootView.swift
//  suixinkan
//
//  Created by Codex on 2026/6/18.
//

import SwiftUI

/// App 根视图，负责创建全局依赖并根据登录状态切换登录页和主界面。
struct RootView: View {
    @Environment(\.scenePhase) private var scenePhase
    @StateObject private var appSession = AppSession()
    @StateObject private var accountContext = AccountContext()
    @StateObject private var permissionContext = PermissionContext()
    @StateObject private var scenicSpotContext = ScenicSpotContext()
    @StateObject private var appRouter = AppRouter()
    @StateObject private var toastCenter = ToastCenter()
    @State private var globalLoading = GlobalLoadingCenter()
    @State private var snapshotStore: AccountSnapshotStore
    @State private var apiClient: APIClient
    @State private var authAPI: AuthAPI
    @State private var profileAPI: ProfileAPI
    @State private var uploadAPI: UploadAPI
    @State private var ossUploadService: OSSUploadService
    @State private var accountContextAPI: AccountContextAPI
    @State private var ordersAPI: OrdersAPI
    @State private var statisticsAPI: StatisticsAPI
    @State private var paymentAPI: PaymentAPI
    @State private var walletAPI: WalletAPI
    @State private var pushAPI: PushAPI
    @State private var scenicPermissionAPI: ScenicPermissionAPI
    @State private var scenicSettlementAPI: ScenicSettlementAPI
    @State private var messageCenterAPI: MessageCenterAPI
    @State private var scenicQueueAPI: ScenicQueueAPI
    @StateObject private var scenicQueueRuntime = ScenicQueueRuntime()
    @State private var liveAPI: LiveAPI
    @State private var operatingAreaAPI: OperatingAreaAPI
    @State private var pilotCertificationAPI: PilotCertificationAPI
    @State private var taskAPI: TaskAPI
    @State private var projectAPI: ProjectAPI
    @State private var scheduleAPI: ScheduleAPI
    @State private var inviteAPI: InviteAPI
    @State private var assetsAPI: AssetsAPI
    @State private var punchPointAPI: PunchPointAPI
    @State private var locationReportAPI: LocationReportAPI
    @State private var cooperationOrderAPI: CooperationOrderAPI
    @State private var authSessionCoordinator: AuthSessionCoordinator
    @State private var sessionBootstrapper: SessionBootstrapper

    /// 初始化网络客户端和业务 API，确保它们共享同一个 token provider。
    init() {
        let apiClient = APIClient()
        let tokenStore = SessionTokenStore()
        let snapshotStore = AccountSnapshotStore()
        _snapshotStore = State(initialValue: snapshotStore)
        _apiClient = State(initialValue: apiClient)
        _authAPI = State(initialValue: AuthAPI(client: apiClient))
        _profileAPI = State(initialValue: ProfileAPI(client: apiClient))
        let uploadAPI = UploadAPI(client: apiClient)
        _uploadAPI = State(initialValue: uploadAPI)
        _ossUploadService = State(initialValue: OSSUploadService(configService: uploadAPI))
        _accountContextAPI = State(initialValue: AccountContextAPI(client: apiClient))
        _ordersAPI = State(initialValue: OrdersAPI(client: apiClient))
        _statisticsAPI = State(initialValue: StatisticsAPI(client: apiClient))
        _paymentAPI = State(initialValue: PaymentAPI(client: apiClient))
        _walletAPI = State(initialValue: WalletAPI(client: apiClient))
        _pushAPI = State(initialValue: PushAPI(client: apiClient))
        _scenicPermissionAPI = State(initialValue: ScenicPermissionAPI(client: apiClient))
        _scenicSettlementAPI = State(initialValue: ScenicSettlementAPI(client: apiClient))
        _messageCenterAPI = State(initialValue: MessageCenterAPI(client: apiClient))
        _scenicQueueAPI = State(initialValue: ScenicQueueAPI(client: apiClient))
        _liveAPI = State(initialValue: LiveAPI(client: apiClient))
        _operatingAreaAPI = State(initialValue: OperatingAreaAPI(client: apiClient))
        _pilotCertificationAPI = State(initialValue: PilotCertificationAPI(client: apiClient))
        _taskAPI = State(initialValue: TaskAPI(client: apiClient))
        _projectAPI = State(initialValue: ProjectAPI(client: apiClient))
        _scheduleAPI = State(initialValue: ScheduleAPI(client: apiClient))
        _inviteAPI = State(initialValue: InviteAPI(client: apiClient))
        _assetsAPI = State(initialValue: AssetsAPI(client: apiClient))
        _punchPointAPI = State(initialValue: PunchPointAPI(client: apiClient))
        _locationReportAPI = State(initialValue: LocationReportAPI(client: apiClient))
        _cooperationOrderAPI = State(initialValue: CooperationOrderAPI(client: apiClient))
        _authSessionCoordinator = State(
            initialValue: AuthSessionCoordinator(
                tokenStore: tokenStore,
                snapshotStore: snapshotStore,
                preferencesStore: AppPreferencesStore()
            )
        )
        _sessionBootstrapper = State(
            initialValue: SessionBootstrapper(
                tokenStore: tokenStore,
                snapshotStore: snapshotStore
            )
        )
    }

    var body: some View {
        rootContent
            .globalToastOverlay()
            .globalLoadingOverlay(loadingCenter: globalLoading)
            .environmentObject(appSession)
            .environmentObject(accountContext)
            .environmentObject(permissionContext)
            .environmentObject(scenicSpotContext)
            .environmentObject(appRouter)
            .environmentObject(toastCenter)
            .environment(\.globalLoading, globalLoading)
            .environment(\.accountSnapshotStore, snapshotStore)
            .environment(\.apiClient, apiClient)
            .environment(\.authAPI, authAPI)
            .environment(\.profileAPI, profileAPI)
            .environment(\.uploadAPI, uploadAPI)
            .environment(\.ossUploadService, ossUploadService)
            .environment(\.accountContextAPI, accountContextAPI)
            .environment(\.ordersAPI, ordersAPI)
            .environment(\.statisticsAPI, statisticsAPI)
            .environment(\.paymentAPI, paymentAPI)
            .environment(\.walletAPI, walletAPI)
            .environment(\.pushAPI, pushAPI)
            .environment(\.scenicPermissionAPI, scenicPermissionAPI)
            .environment(\.scenicSettlementAPI, scenicSettlementAPI)
            .environment(\.messageCenterAPI, messageCenterAPI)
            .environment(\.scenicQueueAPI, scenicQueueAPI)
            .environmentObject(scenicQueueRuntime)
            .environment(\.liveAPI, liveAPI)
            .environment(\.operatingAreaAPI, operatingAreaAPI)
            .environment(\.pilotCertificationAPI, pilotCertificationAPI)
            .environment(\.taskAPI, taskAPI)
            .environment(\.projectAPI, projectAPI)
            .environment(\.scheduleAPI, scheduleAPI)
            .environment(\.inviteAPI, inviteAPI)
            .environment(\.assetsAPI, assetsAPI)
            .environment(\.punchPointAPI, punchPointAPI)
            .environment(\.locationReportAPI, locationReportAPI)
            .environment(\.cooperationOrderAPI, cooperationOrderAPI)
            .environment(\.authSessionCoordinator, authSessionCoordinator)
            .task {
                apiClient.bindAuthTokenProvider { appSession.token }
                PushNotificationManager.shared.configure(api: pushAPI, session: appSession, router: appRouter)
                await globalLoading.withLoading {
                    await sessionBootstrapper.restore(
                        appSession: appSession,
                        accountContext: accountContext,
                        permissionContext: permissionContext,
                        profileAPI: profileAPI,
                        accountContextAPI: accountContextAPI,
                        toastCenter: toastCenter
                    )
                }
                if appSession.isLoggedIn, !AppUITestLaunchState.isRunningUITests {
                    PushNotificationManager.shared.requestAuthorizationAndRegister()
                }
            }
            .task(id: scenicSpotTaskID) {
                guard appSession.isLoggedIn else {
                    scenicSpotContext.reset()
                    return
                }
                await scenicSpotContext.reload(
                    scenicId: accountContext.currentScenic?.id,
                    api: accountContextAPI
                )
            }
            .onChange(of: scenePhase) { newPhase in
                guard !AppUITestLaunchState.isRunningUITests else { return }
                if appSession.isLoggedIn {
                    scenicQueueRuntime.update(
                        api: scenicQueueAPI,
                        userId: accountContext.profile?.userId,
                        scenicId: accountContext.currentScenic?.id,
                        scenePhase: newPhase
                    )
                } else {
                    scenicQueueRuntime.stop()
                }
            }
            .onChange(of: accountContext.currentScenic?.id) { _ in
                guard !AppUITestLaunchState.isRunningUITests else { return }
                if appSession.isLoggedIn {
                    scenicQueueRuntime.update(
                        api: scenicQueueAPI,
                        userId: accountContext.profile?.userId,
                        scenicId: accountContext.currentScenic?.id,
                        scenePhase: scenePhase
                    )
                }
            }
            .onChange(of: appSession.phase) { phase in
                switch phase {
                case .loggedIn:
                    if !AppUITestLaunchState.isRunningUITests {
                        PushNotificationManager.shared.requestAuthorizationAndRegister()
                    }
                case .loggedOut:
                    accountContext.reset()
                    permissionContext.reset()
                    scenicSpotContext.reset()
                    appRouter.reset()
                    toastCenter.dismiss()
                case .restoring:
                    break
                }
            }
    }

    @ViewBuilder
    private var rootContent: some View {
        switch appSession.phase {
        case .loggedOut:
            LoginView()
        case .restoring:
            Color(.systemBackground)
                .frame(maxWidth: .infinity, maxHeight: .infinity)
        case .loggedIn:
            MainTabsView()
                .task {
                    #if DEBUG
                    await AppUITestRouteDriver.applyIfNeeded(appRouter: appRouter)
                    #endif
                }
        }
    }

    /// 景点加载任务的稳定标识，确保登录状态和当前景区变化都会触发任务。
    private var scenicSpotTaskID: String {
        let phaseText: String
        switch appSession.phase {
        case .loggedOut:
            phaseText = "loggedOut"
        case .restoring:
            phaseText = "restoring"
        case .loggedIn:
            phaseText = "loggedIn"
        }
        return "\(phaseText)-\(accountContext.currentScenic?.id ?? 0)"
    }
}

#Preview {
    RootView()
}
