//
//  ADManager.swift
//  PhoneManager
//
//  Created by edy on 2025/5/26.
//
import Foundation
import GoogleMobileAds
import UserMessagingPlatform
import AppTrackingTransparency
import AdSupport
import AppLovinSDK
import FBAudienceNetwork
import SVProgressHUD
import IronSource
import UnityAds
import FirebaseAnalytics

class ADManager : NSObject, FullScreenContentDelegate {
    
    #if DEBUG
        private static let REWARDED_INTERSTITIALAD_KEY : String = "ca-app-pub-3940256099942544/6978759866"
        private static let INTERSTITIALAD_KEY : String = "ca-app-pub-3940256099942544/4411468910"
        private static let ADConfigUrl = "https://api.sayyedandroid.online/getconfigbackBytest?pkg=com.app.phonemanager"
       // info.plist:  ca-app-pub-3940256099942544~1458002511
    #else
        private static let REWARDED_INTERSTITIALAD_KEY : String = "ca-app-pub-3480207748580737/3389219669"
        private static let INTERSTITIALAD_KEY : String = "ca-app-pub-3480207748580737/5836950888"
        private static let ADConfigUrl = "https://api.sayyedandroid.online/getconfigback?pkg=com.app.phonemanager"
        //info.plist:  ca-app-pub-3480207748580737~4236262472
    #endif

    static let shared : ADManager = ADManager()
    
    private var adConfigModel:ADConfigModel?
    
    var adFromName:String = ""
    
    // 看完广告的回调
    var finisedCallBack:(() ->Void)?
    
    // 广告都没播放成功回调
    var failueFinishedCallBack:((_ error:ADShowError?) ->Void)?
    
    // 激励插页广告
    var rewardedInterstitialAd: RewardedInterstitialAd?
    
    // 插页广告
    var interstitial: InterstitialAd?
    
    
    var currentTimes : Int = 3
    
    /// 记录激励上次展示广告的时间
    private var rewardlastAdShowTime: Date?
    /// 记录插屏上次展示广告的时间
    private var interstitiallastAdShowTime: Date?
    
    
    var onlineVersion = "2.2.8"
    private var currentVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "2.2.8"
    
    
    
    /// 默认每日免费删除次数
    var defaultFreeTimes : Int {
        get {
            // 获取存储的时间
            if let saveTime = UserDefaults.standard.object(forKey: "saveTime") as? Date{
                // 判断时间是不是同一天
                let calendar = Calendar.current
                let isSameDay = calendar.isDate(saveTime, inSameDayAs: Date())
                if isSameDay {
                    // 如果是同一天
                    if let times =  UserDefaults.standard.object(forKey: "saveAdvTimes") as? Int{
                        return times
                    }
                    // 如果等于0 那啥也不做
                    return 0
                }else{
                    // 如果不是同一天，重置次数
                    UserDefaults.standard.set(Date(), forKey: "saveTime")
                    UserDefaults.standard.set(ADManager.shared.currentTimes, forKey: "saveAdvTimes")
                    return ADManager.shared.currentTimes
                }
            }else{
                UserDefaults.standard.set(Date(), forKey: "saveTime")
                UserDefaults.standard.set(ADManager.shared.currentTimes, forKey: "saveAdvTimes")
                return ADManager.shared.currentTimes
            }
        }
    }
    
    /// 广告策略  第一次可删除5张，第二次可删除5张，第三次可删除4张
    let advDeleteResouceDic : [Int:Int] = [3:5,2:5,1:4,0:0]
    
    // 重试机制一次
    var interstitialOnceAgin = false
    // 重试机制一次
    var rewardOnceAgin = false
    
    /// 能请求广告
    var canRequestAds: Bool {
        return ConsentInformation.shared.canRequestAds
    }
    
    // 是否有权限
    var isPrivacyOptionsRequired: Bool {
        return ConsentInformation.shared.privacyOptionsRequirementStatus == .required
    }
    
    /// 初始化SDK
    func initAdertisementSDK() {
        getADConfig()
        ALPrivacySettings.setDoNotSell(true)
        LevelPlay.setConsent(true)
        LevelPlay.setMetaDataWithKey("do_not_sell", value: "YES")
        FBAdSettings.setAdvertiserTrackingEnabled(true)
        let gdprMetaData = UADSMetaData()
        gdprMetaData.set("gdpr.consent", value: true)
        gdprMetaData.commit()
        
        MobileAds.shared.start { status in
            let adapterStatuses = status.adapterStatusesByClassName
            for adapter in adapterStatuses {
                let adapterStatus = adapter.value
                NSLog("Adapter Name: %@, Description: %@, Latency: %f", adapter.key,
                      adapterStatus.description, adapterStatus.latency)
            }
            // 隐私设置
            ALPrivacySettings.setHasUserConsent(true)
        }
    }
    
    ///  获取激励插页广告
    func loadRewardedInterstitialAd() async {
        
        guard dealVersionShowAD(),dealConfigShowAD(.reward) else{
            return
        }
        
        APIReportManager.shared.startReport(type: .ad_pull_start, ext: ["ad_type":"rewardAd"])
        do {
            rewardedInterstitialAd = try await RewardedInterstitialAd.load(
                with: ADManager.REWARDED_INTERSTITIALAD_KEY, request: Request())
            rewardedInterstitialAd?.fullScreenContentDelegate = self
            
            rewardedInterstitialAd?.paidEventHandler = {[weak self] value in
                guard let weakSelf = self else { return }
                print("激励广告价值回调",value)
                let valueMicros = value.value
                let currencyCode = value.currencyCode
                let precision = value.precision
                
                // 获取基础广告信息
                var pram = weakSelf.loadedAdNetworkResponseInfo(ad: weakSelf.rewardedInterstitialAd)
                // 添加价值相关信息到 pram 字典中
                pram["valueMicros"] = "\(valueMicros)"
                pram["currencyCode"] = currencyCode
                pram["precision"] = "\(precision.rawValue)"
                
                print("广告价值和来源", pram)
                
                AdRevenueTracker().onPaidEvent(adValue: value)
                
                // 使用 APIReportManager 上报广告价值
                APIReportManager().startReport(type: .ad_price, ext: pram)
                
            }
            APIReportManager.shared.startReport(
                type: .ad_pull,
                ext: ["ad_type":"rewardAd",
                      "status":"1",
                      "from":"",
                     ]
            )
        } catch {
            if rewardOnceAgin == false{
                rewardOnceAgin = true
                Task{
                    await loadRewardedInterstitialAd()
                }
            }
            print("Failed to load rewarded interstitial ad with error: \(error.localizedDescription)")
            APIReportManager.shared.startReport(
                type: .ad_pull,
                ext: ["ad_type":"rewardAd",
                      "status":"2",
                      "from":"",
                      "errMsg":error.localizedDescription]
            )
        }
    }
    
    
    
    /// 获取单纯的插页广告
    fileprivate func loadInterstitial() async {
        
        guard dealVersionShowAD(),dealConfigShowAD(.inter) else{
            return
        }
        
        APIReportManager.shared.startReport(type: .ad_pull_start, ext: ["ad_type":"interAd"])
        do {
            interstitial = try await InterstitialAd.load(
                with: ADManager.INTERSTITIALAD_KEY, request: Request())
            interstitial?.fullScreenContentDelegate = self
            interstitial?.paidEventHandler = {[weak self] value in
                guard let weakSelf = self else { return }
                print("插屏广告价值回调",value)
                let valueMicros = value.value
                let currencyCode = value.currencyCode
                let precision = value.precision
                
                // 获取基础广告信息
                var pram = weakSelf.loadedAdNetworkResponseInfo(ad: weakSelf.interstitial)
                // 添加价值相关信息到 pram 字典中
                pram["valueMicros"] = "\(valueMicros)"
                pram["currencyCode"] = currencyCode
                pram["precision"] = "\(precision.rawValue)"
                
                print("广告价值和来源", pram)
                // 使用 APIReportManager 上报广告价值
                AdRevenueTracker().onPaidEvent(adValue: value)
                APIReportManager().startReport(type: .ad_price, ext: pram)
                
            }
            
            APIReportManager.shared.startReport(
                type: .ad_pull,
                ext: ["ad_type":"interAd",
                      "status":"1",
                      "from":"",
                     ]
            )
        } catch {
            if interstitialOnceAgin == false{
                interstitialOnceAgin = true
                Task{
                    await loadInterstitial()
                }
            }
            print("Failed to load interstitial ad with error: \(error.localizedDescription)")
            APIReportManager.shared.startReport(
                type: .ad_pull,
                ext: ["ad_type":"interAd",
                      "status":"2",
                      "from":"",
                      "errMsg":error.localizedDescription]
            )
        }
    }
    
    /// 开始显示
    /// - Parameter completed: 准备完成后回调
    func showRewardedInterstitialAd(from:String,
                                    finisedCallBack:(@escaping () ->Void),
                                    showFailBlock:@escaping (ADShowError?) ->Void) {
        guard dealVersionShowAD(),dealConfigShowAD(.reward) else{
            rewardedInterstitialAd = nil
            self.finisedCallBack = finisedCallBack
            finisedCallBack()
            return
        }
        // 检查是否在上次广告展示后的 30 秒内
        if let lastAdShowTime = rewardlastAdShowTime {
            let timeSinceLastAd = Date().timeIntervalSince(lastAdShowTime)
            if timeSinceLastAd < 30 {
                self.failueFinishedCallBack = showFailBlock
                showErrMessage(.limit)
                return
            }
        }
        guard let ad = self.rewardedInterstitialAd else {
            Task {
                await self.loadRewardedInterstitialAd()
            }
            if interstitial != nil{
                self.adFromName = from
                self.finisedCallBack = finisedCallBack
                self.failueFinishedCallBack = showFailBlock
                showInterAdWhenNotLoad()
            }else{
                self.failueFinishedCallBack = showFailBlock
                showErrMessage(.noAd)
            }
            return
        }
        self.adFromName = from
        self.finisedCallBack = finisedCallBack
        self.failueFinishedCallBack = showFailBlock
        APIReportManager.shared.startReport(
            type: .ad_prepare_show,
            ext: ["ad_type": "rewardAd","from":self.adFromName])
        
        DispatchQueue.main.async {
            do{
                try ad.canPresent(from: nil)
                ad.present(from: nil){}
            }
            catch{
                APIReportManager.shared.startReport(
                    type: .ad_show_error,
                    ext: ["ad_type": "rewardAd","from":self.adFromName,"reason":"can not Present ad"])
                print("无法展示广告")
                self.failueFinishedCallBack = showFailBlock
                self.showErrMessage(.presentFail)
            }
        }
    }
    
    /// 开始显示
    /// - Parameter completed: 准备完成后回调
    func showInterstitialAd(from:String,
                            finisedCallBack:@escaping(() ->Void),
                            showFailBlock:@escaping ((ADShowError?) ->Void)) {
        
        guard dealVersionShowAD(),dealConfigShowAD(.inter) else{
            self.finisedCallBack = finisedCallBack
            finisedCallBack()
            interstitial = nil
            return
        }
        
        if let lastAdShowTime = interstitiallastAdShowTime {
            let timeSinceLastAd = Date().timeIntervalSince(lastAdShowTime)
            if timeSinceLastAd < 30 {
                self.failueFinishedCallBack = showFailBlock
                showFailBlock(.limit)
                return
            }
        }
    
        guard let ad = self.interstitial else {
            Task{
                await loadInterstitial()
            }
            if rewardedInterstitialAd != nil{
                self.adFromName = from
                self.finisedCallBack = finisedCallBack
                self.failueFinishedCallBack = showFailBlock
                showRewardADWhenNotLoad()
            }else{
                self.failueFinishedCallBack = showFailBlock
                showFailBlock(.noAd)
            }
            return
        }
        
        self.adFromName = from
        self.finisedCallBack = finisedCallBack
        self.failueFinishedCallBack = showFailBlock

        APIReportManager.shared.startReport(
            type: .ad_prepare_show,
            ext: ["ad_type": "interAd","from":adFromName])
        
        DispatchQueue.main.async {
            do{
                try ad.canPresent(from: nil)
                ad.present(from: nil)
            }
            catch{
                APIReportManager.shared.startReport(
                    type: .ad_show_error,
                    ext: ["ad_type": "interAd","from":self.adFromName,"reason":"can not Present ad"])
                print("无法展示广告")
                showFailBlock(.presentFail)
            }
        }
    }
    
    
    func showInterAdWhenNotLoad(){
        guard let ad = interstitial else{
            return
        }
        Print("激励无法展示，加载备用插屏广告")
        DispatchQueue.main.async {
            do{
                try ad.canPresent(from: nil)
                ad.present(from: nil)
            }
            catch{
                APIReportManager.shared.startReport(
                    type: .ad_show_error,
                    ext: ["ad_type": "interAd","from":self.adFromName,"reason":"can not Present ad"])
                print("无法展示广告")
                self.failueFinishedCallBack?(.presentFail)
            }
        }
    }
    
    func showRewardADWhenNotLoad(){
        
        guard let ad = rewardedInterstitialAd else{
            return
        }
        Print("插屏无法展示，加载备用激励广告")
        DispatchQueue.main.async {
            do{
                try ad.canPresent(from: nil)
                ad.present(from: nil){}
            }
            catch{
                APIReportManager.shared.startReport(
                    type: .ad_show_error,
                    ext: ["ad_type": "rewardAd","from":self.adFromName,"reason":"can not Present ad"])
                print("无法展示广告")
                self.failueFinishedCallBack?(.presentFail)
            }
        }
    }
    
    // MARK: - GADFullScreenContentDelegate
    func adWillPresentFullScreenContent(_ ad: FullScreenPresentingAd) {
        print("Ad did present full screen content.")
        var ad_type = "interAd"
        if let _ = ad as? RewardedInterstitialAd{
            ad_type = "rewardAd"
            rewardlastAdShowTime = Date()
        }else{
            interstitiallastAdShowTime = Date()
        }
    
        APIReportManager.shared.startReport(
            type: .ad_show,
            ext: ["ad_type": ad_type,"from":adFromName])
    }
    
    
    func ad(_ ad: FullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
        print("Ad failed to present full screen content with error \(error.localizedDescription).")
        
        var ad_type = "interAd"
        if let _ = ad as? RewardedInterstitialAd{
            ad_type = "rewardAd"
        }
        APIReportManager.shared.startReport(
            type: .ad_show_error,
            ext: ["ad_type": ad_type,"from":adFromName,"reason":error.localizedDescription])
        interstitiallastAdShowTime = nil
        rewardlastAdShowTime = nil
        self.rewardedInterstitialAd = nil
        self.interstitial = nil
        
        failueFinishedCallBack?(.fail(error))
    }
    
    func adDidDismissFullScreenContent(_ ad: FullScreenPresentingAd) {
        print("Ad did dismiss full screen content.")
        if let _ = ad as? RewardedInterstitialAd{
            self.rewardedInterstitialAd = nil
            Task {
                await self.loadRewardedInterstitialAd()
            }
        }else{
            self.interstitial = nil
            Task {
                await self.loadInterstitial()
            }
        }

        finisedCallBack?()
    }
    
    
    
    func adDidRecordClick(_ ad: any FullScreenPresentingAd) {
        print("点击广告")
        
        let pram = loadedAdNetworkResponseInfo(ad: ad)
        
        APIReportManager.shared.startReport(
            type:.ad_click,
            ext:pram)
    }
    
    
    func showErrMessage(_ type:ADShowError = .unkown){
        // 这里如果还没有，则弹出框
        DispatchQueue.main.async {
            let alert = UIAlertController(title: nil, message: "Ad wasn't ready", preferredStyle: .alert)
            GETCURRENTNAV()?.present(alert, animated: true, completion: nil)
            // 1 秒后关闭弹窗
            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                alert.dismiss(animated: true) {
                    self.failueFinishedCallBack?(type)
                }
            }
        }
    }
    
    func failShowErrMessage(){
        // 这里如果还没有，则弹出框
        DispatchQueue.main.async {
            let alert = UIAlertController(title: nil, message: "Ad wasn't ready", preferredStyle: .alert)
            GETCURRENTNAV()?.present(alert, animated: true, completion: nil)
            // 1 秒后关闭弹窗
            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                alert.dismiss(animated: true) {
                    
                }
            }
        }
    }

}
    


extension ADManager{
    
    
    func loadedAdNetworkResponseInfo(ad: FullScreenPresentingAd?) ->[String:String]{

        var adNetworkName = ""
        var adSourceName = ""
        var adSourceID = ""
        var adSourceInstanceName = ""
        var adNetworkClassName = ""
        var adSourceInstanceID = ""
        
        if let rewardedAd = ad as? RewardedInterstitialAd {
            adNetworkName = rewardedAd.responseInfo.loadedAdNetworkResponseInfo?.adNetworkClassName ?? "unknown"
            adSourceName = rewardedAd.responseInfo.loadedAdNetworkResponseInfo?.adSourceName ?? "unknown"
            adSourceID = rewardedAd.responseInfo.loadedAdNetworkResponseInfo?.adSourceID ?? "unknown"
            adSourceInstanceName = rewardedAd.responseInfo.loadedAdNetworkResponseInfo?.adSourceInstanceName ?? "unknown"
            adNetworkClassName = rewardedAd.responseInfo.loadedAdNetworkResponseInfo?.adNetworkClassName ?? "unknown"
            adSourceInstanceID = rewardedAd.responseInfo.loadedAdNetworkResponseInfo?.adSourceInstanceID ?? "unknown"
            
        } else if let interstitialAd = ad as? InterstitialAd {
           
            adNetworkName = interstitialAd.responseInfo.loadedAdNetworkResponseInfo?.adNetworkClassName ?? "unknown"
            adSourceName =  interstitialAd.responseInfo.loadedAdNetworkResponseInfo?.adSourceName ?? "unknown"
            adSourceID = interstitialAd.responseInfo.loadedAdNetworkResponseInfo?.adSourceID ?? "unknown"
            adSourceInstanceName = interstitialAd.responseInfo.loadedAdNetworkResponseInfo?.adSourceInstanceName ?? "unknown"
            adNetworkClassName = interstitialAd.responseInfo.loadedAdNetworkResponseInfo?.adNetworkClassName ?? "unknown"
            adSourceInstanceID = interstitialAd.responseInfo.loadedAdNetworkResponseInfo?.adSourceInstanceID ?? "unknown"
        }
        
        var pram = [
            "from":adFromName,
            "networkname":adNetworkName,
            "adSourceName":adSourceName,
            "adSourceInstanceName":adSourceInstanceName,
            "adSourceId":adSourceID,
            "adNetworkClassName":adNetworkClassName,
            "adSourceInstanceId":adSourceInstanceID,
        ]
        
        if let rewardAd = ad as? RewardedInterstitialAd{
            pram["ad_type"] = "rewardAd"
            pram["adUnitId"] = rewardAd.adUnitID
        }else if let interstitial = ad as? InterstitialAd{
            pram["ad_type"] = "interAd"
            pram["adUnitId"] = interstitial.adUnitID
        }
        return pram
    }
}



extension ADManager {
    /// 获取IDFA
    func getIDFA() -> String {
        if #available(iOS 14, *) {
            let status = ATTrackingManager.trackingAuthorizationStatus
            switch status {
            case .authorized:
                return ASIdentifierManager.shared().advertisingIdentifier.uuidString
            case .denied, .restricted, .notDetermined:
                requestIDFAPermission { staus in
                    
                }
                return ""
            @unknown default:
                return ""
            }
        } else {
            // iOS 14以下版本
            if ASIdentifierManager.shared().isAdvertisingTrackingEnabled {
                return ASIdentifierManager.shared().advertisingIdentifier.uuidString
            }
            return ""
        }
    }
    
    /// 请求IDFA权限
    func requestIDFAPermission(completion: @escaping (ATTrackingManager.AuthorizationStatus) -> Void) {
        if #available(iOS 14, *) {
            ATTrackingManager.requestTrackingAuthorization { status in
                DispatchQueue.main.async {
                    completion(status)
                }
            }
        } else {
            completion(.authorized)
        }
    }
}



extension ADManager{
    
    /// 获取App Store上的版本号
      func getAppStoreVersion(completion: @escaping (String?) -> Void) {
          guard let bundleId = Bundle.main.bundleIdentifier else {
              completion(nil)
              return
          }
          let randomParam = arc4random() % 1000
          let urlString = "https://itunes.apple.com/lookup?bundleId=\(bundleId)&random=\(randomParam)"
          guard let url = URL(string: urlString) else {
              completion(nil)
              return
          }
          
          let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
              guard let data = data,
                    let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
                    let results = json["results"] as? [[String: Any]],
                    let firstResult = results.first,
                    let version = firstResult["version"] as? String else {
                  completion(nil)
                  return
              }
              completion(version)
          }
          task.resume()
      }
    
    
    func dealConfigShowAD(_ type:ADTypeEnum) ->Bool{
        let totalShow = adConfigModel?.showAd ?? true
        let adShow = type == .inter ? (adConfigModel?.showInter ?? true) : (adConfigModel?.showReward ?? true)
        return (totalShow && adShow)
    }
    
    func dealVersionShowAD() -> Bool {
        let currentVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "2.2.8"
        
        // 将版本号按点号分割成数组
        let currentComponents = currentVersion.components(separatedBy: ".")
        let onlineComponents = onlineVersion.components(separatedBy: ".")
        
        // 比较每个版本号部分
        let maxLength = max(currentComponents.count, onlineComponents.count)
        for i in 0..<maxLength {
            let current = i < currentComponents.count ? (Int(currentComponents[i]) ?? 0) : 0
            let online = i < onlineComponents.count ? (Int(onlineComponents[i]) ?? 0) : 0
            
            if current < online {
                return true  // 当前版本小于线上版本
            } else if current > online {
                return false // 当前版本大于线上版本
            }
        }
        
        return true // 版本相同
    }
}


extension ADManager{
    
    func getADConfig(){
       
        HttpRequest.getFormData(to: ADManager.ADConfigUrl) { (result: Result<ADConfigModel, Error>) in
            switch result {
            case .success(let ad):
                print("adconfig: \(ad)")
                ADManager.shared.adConfigModel = ad
                ADManager.shared.saveADConfigToLocal(model: ad)
                self.loadAD()
            case .failure(let error):
                print("Error: \(error)")
                self.getADConfigFromLocal()
            }
        }
    }
    
    
    func loadAD(){
        Task {
            // 同时load两个广告内容
            await self.loadInterstitial()
            await self.loadRewardedInterstitialAd()
        }
    }
    
    
    func saveADConfigToLocal(model:ADConfigModel){
        let dic = SYCodeable.modelToDictionary(model)
        UserDefaults.standard.setValue(dic, forKey: "ad_config_local_info")
        UserDefaults.standard.synchronize()
    }
    
    func getADConfigFromLocal(){
        if let dic = UserDefaults.standard.value(forKey: "ad_config_local_info") as? [String:Any]{
            self.adConfigModel = SYCodeable.decode(dic, modelType: ADConfigModel.self)
        }
        self.loadAD()
    }
}
