import ComposableArchitecture
import FirebaseAppDistribution
import Foundation
import os
import UIKit

@DependencyClient
public struct FirebaseAppDistributionClient {
    public struct Release: Equatable {
        public var displayVersion: String
        public var buildVersion: String
        public var releaseNotes: String?

        public init(displayVersion: String, buildVersion: String, releaseNotes: String?) {
            self.displayVersion = displayVersion
            self.buildVersion = buildVersion
            self.releaseNotes = releaseNotes
        }
    }

    public enum UpdateStatus: Equatable {
        case none
        case available(Release)
    }

    public var isAvailable: @Sendable () -> Bool = { false }
    public var ensureTesterIsSignedIn: @MainActor @Sendable () async -> Void = {}
    public var checkForUpdate: @MainActor @Sendable () async throws -> UpdateStatus = { .none }
    public var openLatestRelease: @MainActor @Sendable () async -> Void = {}
}

extension FirebaseAppDistributionClient: DependencyKey {
    public static let liveValue: Self = {
        let logger = Logger(subsystem: "ai.suno.app", category: "FirebaseAppDistribution")
        let appDistribution = AppDistribution.appDistribution()

        return Self(
            isAvailable: {
                #if DEBUG
                return false
                #else
                return Bundle.main.bundleIdentifier?.contains("staff") ?? false
                #endif
            },
            ensureTesterIsSignedIn: { @MainActor in
                guard appDistribution.isTesterSignedIn == false else { return }
                await withCheckedContinuation { continuation in
                    DispatchQueue.main.async {
                        appDistribution.signInTester { error in
                            if let error {
                                logger.log("Tester sign-in error: \(error.localizedDescription)")
                            }
                            continuation.resume()
                        }
                    }
                }
            },
            checkForUpdate: { @MainActor in
                try await withCheckedThrowingContinuation { continuation in
                    DispatchQueue.main.async {
                        appDistribution.checkForUpdate { release, error in
                            if let error {
                                continuation.resume(throwing: error)
                                return
                            }

                            guard let release else {
                                continuation.resume(returning: .none)
                                return
                            }

                            let mapped = Release(
                                displayVersion: release.displayVersion,
                                buildVersion: release.buildVersion,
                                releaseNotes: release.releaseNotes
                            )
                            continuation.resume(returning: .available(mapped))
                        }
                    }
                }
            },
            openLatestRelease: {
                await MainActor.run {
                    appDistribution.checkForUpdate { release, error in
                        if let error {
                            logger.log("Unable to check for App Distribution release: \(error.localizedDescription)")
                            return
                        }

                        guard let release = release else {
                            logger.log("No new App Distribution release available to open")
                            return
                        }

                        UIApplication.shared.open(release.downloadURL)
                    }
                }
            }
        )
    }()
}

extension FirebaseAppDistributionClient: TestDependencyKey {
    public static let testValue = Self(
        isAvailable: { false },
        ensureTesterIsSignedIn: {},
        checkForUpdate: { .none },
        openLatestRelease: {}
    )
}

public extension FirebaseAppDistributionClient {
    static let previewValue = Self.testValue
}

public extension DependencyValues {
    var firebaseAppDistributionClient: FirebaseAppDistributionClient {
        get { self[FirebaseAppDistributionClient.self] }
        set { self[FirebaseAppDistributionClient.self] = newValue }
    }
}
