import AdamantiumClient
import AttributionAndDeeplinkingClient
import BrazeClient
import ClerkClient
import Combine
import Dependencies
import FirebaseClient
import Foundation
import OSLog
import PaywallClient
import ShareAssetClient
import StatsigClient
import SwiftUI

extension AppStartUpClient: DependencyKey {
    public static let liveValue: Self = AppStartUpClientFactory.liveKey()
}

public extension DependencyValues {
    var appStartUpClient: AppStartUpClient {
        get { self[AppStartUpClient.self] }
        set { self[AppStartUpClient.self] = newValue }
    }
}

// MARK: - AppStartUpClient

public struct AppStartUpClient {
    private let logger: Logger
    private let orchestratorFactory: () -> AppStartUpOrchestratorProtocol
    @Dependency(\.firebaseClient) private var firebaseClient

    init(
        logger: Logger,
        orchestratorFactory: @escaping () -> AppStartUpOrchestratorProtocol
    ) {
        self.logger = logger
        self.orchestratorFactory = orchestratorFactory
    }

    public func startup() async throws {
        try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<Void, Error>) in
            // Explicitly detach this process, in case this instance is deallocated for some reason (it should not be)
            Task.detached {
                let orchestrator = self.orchestratorFactory()
                var hasResumed = false

                await orchestrator.start { event in
                    switch event {
                    case .phaseStarted, .sdkInitialized:
                        break

                    case .criticalFailure(let failures):
                        guard !hasResumed else { return }
                        hasResumed = true
                        let error = AppStartUpError.criticalSdkInitFailures(failures)
                        continuation.resume(throwing: error)

                    case .canShowUI:
                        guard !hasResumed else { return }
                        hasResumed = true
                        // Resume here to let UI proceed - orchestrator continues in background
                        continuation.resume(returning: ())

                    case .completed(let metrics):
                        // This still runs in background after UI proceeds
                        // Don't resume again - already resumed on canShowUI
                        self.logger.debug("🎉 Startup completed in \(String(format: "%.1f", metrics.totalDuration * 1000))ms")
                    }
                }
            }
        }
    }
}
