import Foundation
import FirebaseRemoteConfig

enum KMRemoteConfigFetchStatus: Int {
    case success
    case failure
}

let KMFirebaseRemateConfigRequestIsSuccessful = "KMFirebaseRemateConfigRequestIsSuccessful"
let KMFirebaseRemateConfigFinishNoti = "KMFirebaseRemateConfigFinishNoti"

typealias KMRemoteConfigFetchCompletion = (_ status: KMRemoteConfigFetchStatus, _ error: Error?) -> Void

@objcMembers class KMKdanRemoteConfig: NSObject {
    private let kIsDisplayAdsKey = "isDisplayAds"
    private let kIsDisplayAdsEvaluateAfterKey = "isDisplayAdsEvaluateAfter"
    private let kDisplayAdsUrlConfigKey = "displayAdsUrl"
    private let kDisplayHouseAdsUrlConfigKey = "displayHouseAdsUrl"
    private let kRefreshAdsRateDayKey = "refreshAdsRate"
    private let kRefreshAdsRateDayEvaluateAfterKey = "refreshAdsRateEvaluateAfter"
    private let kRefreshAdsDateDayKey = "refreshAdsDate"
    private let kRefreshAdsDateDayEvaluateAfterKey = "refreshAdsDateEvaluateAfter"
    private let kCloseIntervalDateDayKey = "closeIntervalDate"
    private let kCloseIntervalDateDayEvaluateAfterKey = "closeIntervalDateEvaluateAfter"
    private let kAppEvaluateBeforeAdsCountKey = "appEvaluateBeforeAdsCount"
    private let kAppEvaluateAfterAdsCountKey = "appEvaluateAfterAdsCount"

    static let remoteConfig = KMKdanRemoteConfig()
    
    private var remoteConfigDatas: [String: Any] = [:]
    private var userInfo: [String: Any] = [:]

    private lazy var firebaseConfig: RemoteConfig = {
        let config = RemoteConfig.remoteConfig()
        let settings = RemoteConfigSettings()
        settings.minimumFetchInterval = 0
        config.configSettings = settings
        
        #if VERSION_FREE
            config.setDefaults(fromPlist: "RemoteConfigDefaults")
        #else
            config.setDefaults(fromPlist: "ProRemoteConfigDefaults")
        #endif
        
        return config
    }()

    override init() {
        super.init()
        let mainBundleString = Bundle.main.bundleIdentifier ?? ""
        var dataPath: String?

        #if VERSION_DMG
            dataPath = Bundle.main.path(forResource: "DMGRemoteConfigDefaults", ofType: "plist")
        #else
            #if VERSION_FREE
                dataPath = Bundle.main.path(forResource: "RemoteConfigDefaults", ofType: "plist")
            #else
                dataPath = Bundle.main.path(forResource: "ProRemoteConfigDefaults", ofType: "plist")
            #endif
        #endif

        if let path = dataPath, let dict = NSDictionary(contentsOfFile: path) as? [String: Any] {
            self.userInfo = dict
        }
    }

    func fetch(completionHandler: @escaping KMRemoteConfigFetchCompletion) {
        let mainBundleString = Bundle.main.bundleIdentifier ?? ""
        let configuration = URLSessionConfiguration.default
        configuration.requestCachePolicy = .reloadIgnoringLocalCacheData
        configuration.urlCache = URLCache.shared
        
        let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? ""
        let params = "app_code=\(mainBundleString)&app_version=\(appVersion)&key=DisplayAds"
        
        var urlString = "http://store.pdfreaderpro.com:3018/api/get_config"
        
        #if DEBUG
        urlString = "http://test-store.kdan.cn:3018/api/get_config"
        #endif
        
        if let url = URL(string: "\(urlString)?\(params)") {
            var request = URLRequest(url: url)
            request.httpMethod = "GET"
            request.setValue("application/json", forHTTPHeaderField: "Content-Type")
            
            let session = URLSession(configuration: configuration)
            let task = session.dataTask(with: request) { data, response, error in
                if let error = error {
                    completionHandler(.failure, error)
                } else if let data = data {
                    do {
                        if let datas = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
                           let displayAds = datas["data"] as? [String: Any] {
    #if VERSION_DMG
                            if let dmg = displayAds["DisplayAds"] as? String {
                                if let jsonData = dmg.data(using: .utf8),
                                   let dic = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any],
                                   let remoteConfigDatas = dic["dmg"] {
                                    self.remoteConfigDatas = remoteConfigDatas as! [String : Any]
                                }
                            }
    #else
                            if let store = displayAds["DisplayAds"] as? String {
                                if let jsonData = store.data(using: .utf8),
                                   let dic = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any],
                                   let remoteConfigDatas = dic["store"] {
                                    self.remoteConfigDatas = remoteConfigDatas as! [String : Any]
                                }
                            }
    #endif
                        }
                        completionHandler(.success, nil)
                    } catch {
                        completionHandler(.failure, error)
                    }
                }
                
                NotificationCenter.default.post(name: Notification.Name(KMFirebaseRemateConfigRequestIsSuccessful), object: self, userInfo: nil)
            }
            task.resume()
        }
    }
    
    func fetchWithRemoteConfigCompletionHandler(completionHandler: @escaping RemoteConfigFetchCompletion) {
        let expirationDuration: TimeInterval = 0
        
        // If your app is using developer mode, expirationDuration is set to 0, so each fetch will
        // retrieve values from the Remote Config service.
        // TimeInterval is set to expirationDuration here, indicating the next fetch request will use
        // data fetched from the Remote Config service, rather than cached parameter values, if cached
        // parameter values are more than expirationDuration seconds old. See Best Practices in the
        // README for more information.
        self.firebaseConfig.fetch(withExpirationDuration: expirationDuration) { status, error in
            if status == .success {
                self.firebaseConfig.activate { changed, error in
                    // Handle activation completion if needed
                }
            }
            NotificationCenter.default.post(name: Notification.Name(KMFirebaseRemateConfigFinishNoti), object: self, userInfo: nil)
            completionHandler(status, error)
        }
    }

    func isDisplayAds() -> Bool {
        var isDisplayAds = userInfo[kIsDisplayAdsKey] as? Bool ?? true
        if let value = remoteConfigDatas[kIsDisplayAdsKey] as? Bool {
            isDisplayAds = value
        }
        return isDisplayAds
    }

    func isDisplayAdsEvaluateAfter() -> Bool {
        var isDisplayAds = userInfo[kIsDisplayAdsEvaluateAfterKey] as? Bool ?? true
        if let value = remoteConfigDatas[kIsDisplayAdsEvaluateAfterKey] as? Bool {
            isDisplayAds = value
        }
        return isDisplayAds
    }

    func displayHouseAdsUrl() -> String {
        var adsUrl = userInfo[kDisplayHouseAdsUrlConfigKey] as? String ?? ""
        if let value = remoteConfigDatas[kDisplayHouseAdsUrlConfigKey] as? String {
            adsUrl = value.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? ""
        }
        return adsUrl
    }

    func displayAdsUrl() -> String {
        var adsUrl = userInfo[kDisplayAdsUrlConfigKey] as? String ?? ""
        if let value = remoteConfigDatas[kDisplayAdsUrlConfigKey] as? String {
            adsUrl = value.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? ""
        }
        return adsUrl
    }

    func refreshAdsRate() -> Int {
        var adsRate = userInfo[kRefreshAdsRateDayKey] as? Int ?? 0
        if let value = remoteConfigDatas[kRefreshAdsRateDayKey] as? String {
            adsRate = Int(value)!
        }
        return adsRate
    }

    func refreshAdsRateEvaluateAfter() -> Int {
        var adsRate = userInfo[kRefreshAdsRateDayEvaluateAfterKey] as? Int ?? 0
        if let value = remoteConfigDatas[kRefreshAdsRateDayEvaluateAfterKey] as? String {
            adsRate = Int(value)!
        }
        return adsRate
    }

    func refreshAdsDate() -> Int {
        var adsDate = userInfo[kRefreshAdsDateDayKey] as? Int ?? 180
        if let value = remoteConfigDatas[kRefreshAdsDateDayKey] as? String {
            adsDate = Int(value)!
        }
        return adsDate
    }

    func refreshAdsDateEvaluateAfter() -> Int {
        var adsDate = userInfo[kRefreshAdsDateDayEvaluateAfterKey] as? Int ?? 180
        if let value = remoteConfigDatas[kRefreshAdsDateDayEvaluateAfterKey] as? String {
            adsDate = Int(value)!
        }
        return adsDate
    }

    func closeIntervalDate() -> Int {
        var intervalDate = userInfo[kCloseIntervalDateDayKey] as? Int ?? 0
        if let value = remoteConfigDatas[kCloseIntervalDateDayKey] as? String {
            intervalDate = Int(value)!
        }
        return intervalDate
    }

    func closeIntervalDateEvaluateAfter() -> Int {
        var intervalDate = userInfo[kCloseIntervalDateDayEvaluateAfterKey] as? Int ?? 0
        if let value = remoteConfigDatas[kCloseIntervalDateDayEvaluateAfterKey] as? String {
            intervalDate = Int(value)!
        }
        return intervalDate
    }

    func appEvaluateBeforeAdsCount() -> Int {
        var evaluateCount = userInfo[kAppEvaluateBeforeAdsCountKey] as? Int ?? 1
        if let value = remoteConfigDatas[kAppEvaluateBeforeAdsCountKey] as? String {
            evaluateCount = Int(value)!
        }
        return evaluateCount
    }

    func appEvaluateAfterAdsCount() -> Int {
        var evaluateCount = userInfo[kAppEvaluateAfterAdsCountKey] as? Int ?? 1
        if let value = remoteConfigDatas[kAppEvaluateAfterAdsCountKey] as? String {
            evaluateCount = Int(value)!
        }
        return evaluateCount
    }

    func showSDKRecommendInfo() -> Bool {
        guard firebaseConfig.lastFetchStatus == .success else {
            return false
        }
        return firebaseConfig["SDKRecommendKey"].boolValue
    }

    func showAPP_AveragePrice() -> Bool {
        guard firebaseConfig.lastFetchStatus == .success else {
            return false
        }
        return firebaseConfig["ShowAPP_AveragePrice"].boolValue
    }

    func showHelp_More_RecommendLink() -> Bool {
        guard firebaseConfig.lastFetchStatus == .success else {
            return false
        }
        return firebaseConfig["Help_More_Link_Recommend"].boolValue
    }
}