import Foundation
import React

// Conditionally import DeclaredAgeRange only on iOS 26+
#if canImport(DeclaredAgeRange)
import DeclaredAgeRange
#endif

@objc(AgeDeclarationModule)
class AgeDeclarationModule: NSObject {

    // MARK: - Properties

    private var ageThresholds: [Int] = []

    // MARK: - Module Setup

    @objc
    static func requiresMainQueueSetup() -> Bool {
        return true
    }

    // MARK: - Public Methods

    /// Sets the age range thresholds for the application
    /// - Parameters:
    ///   - thresholds: Array of age thresholds (must be 1-18, ascending order, 2-year separation)
    ///   - resolver: Promise resolver
    ///   - rejecter: Promise rejecter
    @objc
    func setAgeThresholds(
        _ thresholds: [Int],
        resolver: @escaping RCTPromiseResolveBlock,
        rejecter: @escaping RCTPromiseRejectBlock
    ) {
        // Validate thresholds
        guard !thresholds.isEmpty else {
            rejecter("INVALID_THRESHOLDS", "At least one threshold is required", nil)
            return
        }

        // Validate range (1-18)
        guard thresholds.allSatisfy({ $0 >= 1 && $0 <= 18 }) else {
            rejecter("INVALID_THRESHOLDS", "Thresholds must be between 1 and 18", nil)
            return
        }

        // Validate ascending order
        guard thresholds == thresholds.sorted() else {
            rejecter("INVALID_THRESHOLDS", "Thresholds must be in ascending order", nil)
            return
        }

        // Validate 2-year separation
        for i in 0..<(thresholds.count - 1) {
            if thresholds[i + 1] - thresholds[i] < 2 {
                rejecter("INVALID_THRESHOLDS", "Thresholds must have at least 2-year separation", nil)
                return
            }
        }

        // Validate max 3 thresholds (API limitation)
        guard thresholds.count <= 3 else {
            rejecter("INVALID_THRESHOLDS", "Maximum 3 thresholds allowed", nil)
            return
        }

        self.ageThresholds = thresholds
        resolver(["success": true])
    }

    /// Requests age range information from the system
    /// - Parameters:
    ///   - resolver: Promise resolver
    ///   - rejecter: Promise rejecter
    @objc
    func requestAgeRange(
        _ resolver: @escaping RCTPromiseResolveBlock,
        rejecter: @escaping RCTPromiseRejectBlock
    ) {
        // Validate thresholds are set
        guard !ageThresholds.isEmpty else {
            rejecter("THRESHOLDS_NOT_SET", "Age thresholds must be set before requesting age range", nil)
            return
        }

        // Check iOS version and framework availability
        if #available(iOS 26.0, *) {
            #if canImport(DeclaredAgeRange)
            DispatchQueue.main.async { [weak self] in
                guard let self = self else { return }
                self.requestDeclaredAgeRange(resolver: resolver, rejecter: rejecter)
            }
            #else
            // Framework not available at compile time
            let result: [String: Any] = [
                "status": "not_available_yet",
                "message": "DeclaredAgeRange framework not available in current SDK",
                "thresholds": ageThresholds
            ]
            resolver(result)
            #endif
        } else {
            // For iOS versions before 26.0, return not available
            let result: [String: Any] = [
                "status": "not_available_yet",
                "message": "Apple's Declared Age Range API requires iOS 26.0 or later",
                "thresholds": ageThresholds
            ]
            resolver(result)
        }
    }

    /// Checks if age range API is supported on this device
    /// - Parameters:
    ///   - resolver: Promise resolver
    ///   - rejecter: Promise rejecter
    @objc
    func isSupported(
        _ resolver: RCTPromiseResolveBlock,
        rejecter: RCTPromiseRejectBlock
    ) {
        #if canImport(DeclaredAgeRange)
        if #available(iOS 26.0, *) {
            resolver(true)
        } else {
            resolver(false)
        }
        #else
        // Framework not available at compile time, so not supported
        resolver(false)
        #endif
    }

    // MARK: - Private Methods

    #if canImport(DeclaredAgeRange)
    @available(iOS 26.0, *)
    private func requestDeclaredAgeRange(
        resolver: @escaping RCTPromiseResolveBlock,
        rejecter: @escaping RCTPromiseRejectBlock
    ) {
        // Find the top view controller to present the age range prompt
        guard let viewController = topViewController() else {
            rejecter("NO_VIEW_CONTROLLER", "Could not find a view controller to present the age range prompt", nil)
            return
        }

        // Convert thresholds (API supports up to 3 thresholds)
        let firstThreshold = ageThresholds[0]
        let secondThreshold = ageThresholds.count > 1 ? ageThresholds[1] : nil
        let thirdThreshold = ageThresholds.count > 2 ? ageThresholds[2] : nil

        // Request age range using async/await
        Task {
            do {
                let response = try await AgeRangeService.shared.requestAgeRange(
                    ageGates: firstThreshold,
                    secondThreshold,
                    thirdThreshold,
                    in: viewController
                )

                // Handle response
                let result = self.processAgeRangeResponse(response)

                DispatchQueue.main.async {
                    resolver(result)
                }
            } catch {
                DispatchQueue.main.async {
                    rejecter("API_ERROR", "Failed to request age range: \(error.localizedDescription)", error)
                }
            }
        }
    }

    @available(iOS 26.0, *)
    private func processAgeRangeResponse(_ response: AgeRangeResponse) -> [String: Any] {
        switch response {
        case .sharing(let declaration):
            // User shared their age range
            var result: [String: Any] = [
                "status": "verified",
                "message": "User age range retrieved successfully",
                "thresholds": ageThresholds
            ]

            // Add age range declaration if available
            if let ageRange = declaration.ageRangeDeclaration {
                result["ageRange"] = String(describing: ageRange)
            }

            // Add lower and upper bounds if available
            if let lowerBound = declaration.lowerBound {
                result["lowerBound"] = lowerBound
            }

            if let upperBound = declaration.upperBound {
                result["upperBound"] = upperBound
            }

            // Add parental controls info
            do {
                let parentalControls = try declaration.activeParentalControls
                result["parentalControls"] = parentalControls.rawValue
            } catch {
                // Parental controls info not available
                result["parentalControls"] = nil
            }

            return result

        case .declinedSharing:
            // User declined to share age range
            return [
                "status": "not_verified",
                "message": "User declined to share age range",
                "thresholds": ageThresholds
            ]

        @unknown default:
            // Unknown response type
            return [
                "status": "unknown",
                "message": "Unknown age range response",
                "thresholds": ageThresholds
            ]
        }
    }
    #endif

    /// Finds the top-most view controller to present the age range prompt
    private func topViewController() -> UIViewController? {
        guard let windowScene = UIApplication.shared.connectedScenes
            .compactMap({ $0 as? UIWindowScene })
            .first(where: { $0.activationState == .foregroundActive }),
              let rootViewController = windowScene.windows
                .first(where: { $0.isKeyWindow })?.rootViewController else {
            return nil
        }

        var topViewController = rootViewController
        while let presentedViewController = topViewController.presentedViewController {
            topViewController = presentedViewController
        }

        return topViewController
    }
}
