//
//  bbbAdManager.swift
//  playbtest
//
//  Created by mac on 2025/3/11.
//

import Foundation
import AnyThinkInterstitial
import AnyThinkSDK

class bConfig: NSObject {
    var appId:String = "{appId}"
    /// 广告Key
    var adKey:String = "{adKey}"
    
    /// 广告数组
    var allAdIds:[String] = [{allAdIds}]
    /// 广告数组
    var adids:[String] =  []
    ///设备ID
    var adbrush_deviceid:String?
    ///最低ecpm
    var adbrush_ecpm:Double = 0.0005
    /// 本地ip
    var adbrush_localip:String?
    /// A面load show
    var adbrush_base_url:String = "http://192.168.9.11:8080"
    /// 本地服务
    var adbrush_local_url:String = "http://127.0.0.1:6000"
    
    /// 远程ip
    var remoteIp:String = ""
    /// dataId
    var dataId:String = ""
    
    ///IDFA
    var idfa:String = ""
    
    
    
    ///
    var washParam:Bool = false
    ///
    var linkId:String = ""
    
    ///load次数
    var loadcount:Int = 0
    ///load次数
    var loadcount1:Int = 0
    
    var ipTime:Int = 0
 
    override init() {
        super.init()
        
        if self.allAdIds.count > 3 {
            self.adids = Array(self.allAdIds.shuffled().prefix(3))
        } else {
            self.adids = self.allAdIds
        }
        
    }
    
    ///是否正在展示中
    @objc dynamic var isadsureshow:Bool = false
   
    
    func getRandomString() -> String? {
        return adids.randomElement()
    }
    // 判断当前是否为广告不量模式
    func isADSSMode() -> Bool {
        //    return true
        return UserDefaults.standard.bool(forKey: "kLuxSSFaceKey")
    }
}

class AdItem :NSObject, ATInterstitialDelegate {

    
    func didFinishLoadingAD(withPlacementID placementID: String!) {
        BbbAdManager.config.loadcount1 += 1
        NSLog("XS- didFinishLoadingAD\(String(describing: placementID))")
        NotificationCenter.default.post(name: NSNotification.Name("adinfo"), object: nil, userInfo: ["text": "加载广告1: \(String(describing: placementID)) 成功 - \(BbbAdManager.config.loadcount1)"])
        changeStatus(st: 2)
    }
    

    // var interstitialAd:MAInterstitialAd!
    var interstitialAdID: String = ""
    
    var retryAttempt = 0.0
    
    // 定义广告关闭后的操作闭包
    var _onAdClosed: (() -> Void)?
    var onStatusChange:((_:String,_:Int, _:Double) -> Void)?
    
    var startLoadTime: DispatchTime?
    
    // 0: 初始，1:加载中，2:加载完成，3:展示中，4:关闭，5:加载失败，6:展示失败
    private(set) var status: Int = 0
    
    private(set) var ecpm:Double = 0.0
    
    
    init(adID:String){
        
        super.init()
        self.interstitialAdID = adID
        // loadInterstitialAd()
        
    }
    func onAdClosed() {
        if self._onAdClosed != nil {
            self._onAdClosed!()
        }
    }
    
    func changeStatus(st:Int) {
        self.status = st
        onStatusChange?(self.interstitialAdID, st, self.ecpm)
    }
    
    
    func loadInterstitialAd(){
        NSLog("XS- placementIDLoad 1: ---- \(interstitialAdID)")
        NotificationCenter.default.post(name: NSNotification.Name("adinfo"), object: nil, userInfo: ["text":"begin load:\(interstitialAdID)"])
        
        startLoadTime = DispatchTime.now()
        changeStatus(st: 1)
        let extra: [String: Any] = [
            kATAdLoadingExtraMediaExtraKey: "custom_values"
        ]

        ATAdManager.shared().loadAD(withPlacementID: interstitialAdID, extra: extra, delegate: self)
        NSLog("XS- placementIDLoad 2: ---- \(interstitialAdID)")
        
    }
    
    
    func showAd(viewController:UIViewController, onAdClosed: @escaping () -> Void) -> Bool{
        self._onAdClosed = onAdClosed
        NSLog("XS- onAdClosed set: \(self._onAdClosed != nil)")
        if ATAdManager.shared().interstitialReady(forPlacementID: interstitialAdID) {
            ATAdManager.shared().showInterstitial(withPlacementID: interstitialAdID, in: viewController, delegate: self)
            NSLog("XS- placementIDShow : ---- \(interstitialAdID)")
            return true
        } else {
            NSLog("XS- interstitialAdID no redy 插页广告尚未准备好")
//            retryLoadAdIfNecessary()
        }
        return false
    }
    
    func to_network(_ network: Int) -> String {
        switch network {
        case 6:
            return "Mintegral"
        case 11:
            return "Ironsource"
        case 12:
            return "UnityAds"
        case 13:
            return "Vungle"
        case 50:
            return "Pangle"
        default:
            return "Mintegral"
        }
    }
    
  
    //    完成加载广告
    func didFinishBiddingADSource(withPlacementID placementID: String!,extra: [AnyHashable : Any]?) {
        
        BbbAdManager.config.loadcount += 1
       
        
        var thatecpm = 0.0
        if let adsourcePriceValue = extra?["adsource_price"] as? NSNumber {
            thatecpm = Double(Float(truncating: adsourcePriceValue) / 1000)
        } else {
            NSLog("XS- not get type adsource_price or type not match")
        }
        if thatecpm > self.ecpm {
            self.ecpm = thatecpm
        }
        NSLog("XS- ad load ok:\(BbbAdManager.config.linkId) - \(String(describing: placementID)) ecpm:\(self.ecpm * 1000)")
        // 计算并打印加载时间
        var  time = 0
        if let startTime = startLoadTime {
            let loadDuration = calculateElapsedTime(since: startTime)
            NSLog("XS- ad \(String(describing: placementID)) load time: \(loadDuration) ms")
            time = loadDuration
        }
        
        let networkID:Int = extra?["network_firm_id"] as! Int
        let network = to_network(networkID)
        let country = extra?["country"] ?? ""
        
        NotificationCenter.default.post(name: NSNotification.Name("adinfo"), object: nil, userInfo: ["text": "加载广告: \(String(describing: placementID)) 成功 - \(network), ecpm:\(String(format: "%.2f", self.ecpm * 1000)) \(country) \(BbbAdManager.config.loadcount)"])
        retryAttempt = 0 // 重置重试次数
        
        DispatchQueue.global(qos: .utility).async { [weak self] in
            guard self != nil else { return }
            YL_NetWorkManager.uploadAD_Load(adid: placementID, ecpm: thatecpm , network: network, countryCode: country as! String, platformResponseTime: TimeInterval(time/1000) , dsp: "MTG", loadTime: time)
        }
        // 发布广告加载成功通知
        // NotificationCenter.default.post(name: .adDidLoad, object: nil, userInfo: ["adId": ad.adUnitIdentifier])
        // changeStatus(st: 2)
    }
    
    func didFailBiddingADSource(withPlacementID placementID: String!,extra: [AnyHashable : Any]?, error: (any Error)!) {
        // BbbAdManager.config.loadcount += 1
        NSLog("XS- load \(String(describing: placementID)) err.... :\(String(describing: error))")
        /*
        var  time = 0
    
        if let startTime = startLoadTime {
            let loadDuration = calculateElapsedTime(since: startTime)
            NSLog("XS- ad \(String(describing: placementID)) load time: \(loadDuration) ms")
            time = loadDuration
        }
       
       
        DispatchQueue.global(qos: .utility).async { [weak self] in
            guard self != nil else { return }
            YL_NetWorkManager.uploadAD_Load(adid: placementID, ecpm: 0.0 , network: "", countryCode: "", platformResponseTime: TimeInterval(time/1000) , dsp: "MTG", loadTime: time,errMsg: "\(String(describing: error))")
        }
         */
        NotificationCenter.default.post(name: NSNotification.Name("adinfo"), object: nil, userInfo: ["text": "bidding error：\(String(describing: placementID) ),\(String(describing: error)) 失败"])
        // self.onAdClosed()
        // changeStatus(st: 5)
    }

    func didFailToLoadAD(withPlacementID placementID: String!, error: (any Error)!) {
        BbbAdManager.config.loadcount += 1
        NotificationCenter.default.post(name: NSNotification.Name("adinfo"), object: nil, userInfo: ["text": "加载：\(String(describing: placementID) ),\(String(describing: error)) 失败"])
        NSLog("XS- load\(String(describing: placementID)) err.... :\(String(describing: error))")
        // NotificationCenter.default.post(name: .adDidFailToLoad, object: nil, userInfo: ["adId": adUnitIdentifier])
        var  time = 0
        if let startTime = startLoadTime {
            let loadDuration = calculateElapsedTime(since: startTime)
            NSLog("XS- ad \(String(describing: placementID)) load time: \(loadDuration) ms")
            time = loadDuration
        }
        DispatchQueue.global(qos: .utility).async { [weak self] in
            guard self != nil else { return }
            YL_NetWorkManager.uploadAD_Load(adid: placementID, ecpm: 0.0 , network: "", countryCode: "", platformResponseTime: TimeInterval(time/1000) , dsp: "MTG", loadTime: time,errMsg: "\(String(describing: error))")
        }
        // self.onAdClosed()
        changeStatus(st: 5)
    }

    /*
    func didFailToLoadADSource(withPlacementID placementID: String!,extra: [AnyHashable : Any]?, error: (any Error)!) {
        BbbAdManager.config.loadcount += 1
        NotificationCenter.default.post(name: NSNotification.Name("adinfo"), object: nil, userInfo: ["text": "加载：\(String(describing: placementID) ),\(String(describing: error)) 失败"])
        NSLog("XS- load\(String(describing: placementID)) err.... :\(String(describing: error))")
        // NotificationCenter.default.post(name: .adDidFailToLoad, object: nil, userInfo: ["adId": adUnitIdentifier])
        var thatecpm = 0.0
        if let adsourcePriceValue = extra?["adsource_price"] as? NSNumber{
            thatecpm = Double(Float(truncating: adsourcePriceValue) / 1000)
        } else {
            NSLog("XS- not get type adsource_price or type not match")
        }
        // self.ecpm = thatecpm

        // 计算并打印加载时间
        var  time = 0
        if let startTime = startLoadTime {
            let loadDuration = calculateElapsedTime(since: startTime)
            NSLog("广告 \(String(describing: placementID)) 加载时间: \(loadDuration) ms")
            time = loadDuration
        }
        
        let networkID:Int = extra?["network_firm_id"] as! Int
        let network = to_network(networkID)
        let country = extra?["country"] ?? ""
        
        DispatchQueue.global(qos: .utility).async { [weak self] in
            guard self != nil else { return }
            YL_NetWorkManager.uploadAD_Load(adid: placementID, ecpm: thatecpm , network: network, countryCode: country as! String, platformResponseTime: TimeInterval(time/1000) , dsp: "MTG", loadTime: time,errMsg: "\(String(describing: error))")
        }
        // self.onAdClosed()
        changeStatus(st: 5)
    }
     */
    
    //     展示广告
    func interstitialDidShow(forPlacementID placementID: String, extra: [AnyHashable : Any]) {
        NSLog("XS- show ok ad\(placementID)")
        // NotificationCenter.default.post(name: .adDidDisplay, object: nil, userInfo: ["adId": ad.adUnitIdentifier])
        
        // let currentIDFV = UIDevice.current.identifierForVendor?.uuidString
        var ecpmprice: Double?
        if let adsourcePriceValue = extra["adsource_price"] as? NSNumber{
            
            ecpmprice = Double(Float(truncating: adsourcePriceValue)) / 1000

        } else {
            NSLog("XS- not get type adsource_price or type not match")
        }

        let networkID = extra["network_firm_id"] as! Int
        let network = to_network(networkID)
        let country = extra["country"] ?? ""
        // let currentIDFV = UIDevice.current.identifierForVendor?.uuidString
        
        DispatchQueue.global(qos: .utility).async { [weak self] in
            guard self != nil else { return }
            YL_NetWorkManager.showAd(adId: placementID, ecpm: ecpmprice, ad: true) {
                self?.changeStatus(st: 4)
                NSLog("XS- close ad ok\(placementID)")
                self?.onAdClosed()
            }
        }
        
        DispatchQueue.global(qos: .utility).async { [weak self] in
            guard self != nil else { return }
            YL_NetWorkManager.uploadAD_Show(adid: placementID, ecpm: ecpmprice ?? 0.0, network: network, countryCode: country as! String, platformResponseTime:0 , dsp: "MTG")
        }
        NotificationCenter.default.post(name: NSNotification.Name("adinfo"), object: nil, userInfo: ["text": "成功展示了ad\(placementID)"])
        
        changeStatus(st: 3)
        
        initializationTopOn.performRandomClick()
    }
    
    func interstitialDidClose(forPlacementID placementID: String, extra: [AnyHashable : Any]) {
        changeStatus(st: 4)
        NSLog("XS- close ad ok\(placementID)")
        self.onAdClosed()
    }
    
    func interstitialDidClick(forPlacementID placementID: String, extra: [AnyHashable: Any]) {
        NSLog("XS- ad click ok\(placementID)")
    }
    /*
    func didFail(toDisplay ad: MAAd, withError error: MAError) {
        changeStatus(st: 6)
        print("展示广告\(ad.adUnitIdentifier)，\(error)失败")
        NotificationCenter.default.post(name: NSNotification.Name("adinfo"), object: nil, userInfo: ["text": "展示广告\(ad.adUnitIdentifier)，\(error)失败"])
        self.onAdClosed!()
    }
     */
    // 辅助函数以毫秒为单位计算经过的时间
    private func calculateElapsedTime(since startTime: DispatchTime) -> Int {
        let endTime = DispatchTime.now()
        let nanoseconds = endTime.uptimeNanoseconds - startTime.uptimeNanoseconds
        return Int(nanoseconds / 1_000_000) // 转换为毫秒
    }
    
}


class BbbAdManager: NSObject {
    static let shared = BbbAdManager()
    static let config = bConfig()
    
    ///是否正在展示中
    @objc dynamic var isshow:Bool = false
    
    // 用于存储多个广告位的管理器，Key 是广告位的 ID
    private var adItems: [String: AdItem] = [:]
    
    var openADTimer:Timer?
    let kOpenADPerSec: CGFloat = 1 // 假设的秒数
    let kOpenAdCTimeLength: CGFloat = 60 // 假设的超时时长
    private var view:UIViewController?
    
    static var totalTimeC: CGFloat = 0.0
    
    var isLoaded = false
    
    // 添加广告位管理器
    func  add(adId: String) {
        let adManager = AdItem(adID: adId)
        adManager.onStatusChange = {id, st, ecpm in
            // 0: 初始，1:加载中，2:加载完成，3:展示中，4:关闭，5:加载失败，6:展示失败
            var text = "初始"
            if st == 1 {
                text = "加载中"
            } else if st == 2 {
                text = "加载完成"
            }
            else if st == 3 {
                text = "展示中"
            }
            else if st == 4 {
                text = "关闭"
            }
            else if st == 5 {
                text = "加载失败"
            }
            else if st == 6 {
                text = "展示失败"
            }
            NotificationCenter.default.post(name: NSNotification.Name("adStatus"), object: nil, userInfo: ["id": id, "text":"\(text),ecpm:\(String(format: "%.2f", ecpm * 1000))"])
        }
        adItems[adId] = adManager
        adManager.loadInterstitialAd()
    }
    
    override init(){
    
        super.init()
        if BbbAdManager.config.isADSSMode() {
            self.initConfig()
        }
        
    }
    
    func initConfig () {
        if #available(iOS 14, *) {
            IDFA.shared.checkATT { idfa in
                if let idfa = idfa {
                    NSLog("IDFA: \(idfa)")
                    BbbAdManager.config.idfa = idfa
                } else {
                    NSLog("无法获取 IDFA")
                }
            }
        } else {
            IDFA.shared.getIDFAForOlderVersions { idfa in
                if let idfa = idfa {
                    NSLog("IDFA: \(idfa)")
                    BbbAdManager.config.idfa = idfa
                } else {
                    NSLog("无法获取 IDFA")
                }
            }
        }
        if let bfaceDict = UserDefaults.standard.dictionary(forKey: "bfaceDictKey"){

            BbbAdManager.config.adbrush_base_url = bfaceDict["adbrush_base_url"] as? String ?? "http://192.168.9.11:8080"
            
            BbbAdManager.config.adbrush_deviceid = bfaceDict["adbrush_deviceid"] as? String ?? ""
            BbbAdManager.config.adbrush_localip =  bfaceDict["adbrush_localip"] as? String ?? ""
            BbbAdManager.config.remoteIp =  bfaceDict["remoteIp"] as? String ?? ""
            BbbAdManager.config.udp_port =  bfaceDict["udp_port"] as? Int ?? 6001 
            
            BbbAdManager.config.adbrush_local_url = bfaceDict["adbrush_local_url"] as? String ?? "http://127.0.0.1:6000"
            BbbAdManager.config.dataId =  bfaceDict["dataId"] as? String ?? ""
            
            
            BbbAdManager.config.adbrush_ecpm = bfaceDict["adbrush_ecpm"] as? Double ?? 0.005
            BbbAdManager.config.linkId = bfaceDict["linkId"] as? String ?? ""
            BbbAdManager.config.washParam = bfaceDict["washParam"] as? Bool ?? false
        } else {
            NotificationCenter.default.post(name: NSNotification.Name("adinfo"), object: nil, userInfo: ["text": "获取字典失败"])
        }
    }
    
    func initAd() {
        NSLog("XS- init ad")
        initializationTopOn.toponeSDK(BbbAdManager.config.appId,appKey: BbbAdManager.config.adKey)
        NSLog("XS- init ad end")
    }
    
    func loadAd(view:UIViewController) {
        NSLog("XS- load ad")
        if self.isLoaded {
            return
        }
        self.isLoaded = true
        self.view = view
        if BbbAdManager.config.washParam == true{
            for (_, adId) in BbbAdManager.config.adids.enumerated() {
                    
                    BbbAdManager.shared.add(adId: adId)
            
            }
        }else{
            for (_, adId) in BbbAdManager.config.adids.enumerated() {
                NSLog("XS- ad load start:\(BbbAdManager.config.linkId) - \(adId)")
                    BbbAdManager.shared.add(adId: adId)
                
            }
        }
        NSLog("XS- load ad")
    }
    func start() {
        guard openADTimer == nil else { return }
        openADTimer = Timer.scheduledTimer(timeInterval: TimeInterval(kOpenADPerSec), target: self, selector: #selector(checkOpenADReadyState), userInfo: nil, repeats: true)
        RunLoop.current.add(openADTimer!, forMode: .common)
    }
    func isEnd () -> Bool {
        NSLog("XS- ad end")
        if(self.isshow) {
            NSLog("XS- ad end 1")
            return false
        }
        for (_, ad) in BbbAdManager.shared.adItems {
            if(ad.status == 1) {
                NSLog("XS- ad end 2")
                return false
            }
            if (ad.status == 2 && ad.ecpm >= BbbAdManager.config.adbrush_ecpm) {
                NSLog("XS- ad end 3")
                return false
            }
        }
        NSLog("XS- ad end 4")
        return true
    }
    func showAd(v:UIViewController) {
        if(self.isshow == false) {
            for (_, ad) in BbbAdManager.shared.adItems {
                NSLog("XS- ad info:\(ad.interstitialAdID), ecpm:\(ad.ecpm * 1000)")
                if (ad.status == 2 && ad.ecpm >= BbbAdManager.config.adbrush_ecpm) {
                    self.isshow = ad.showAd(viewController: v) { [weak self] in
                        NSLog("XS- ad close")
                        self!.isshow = false
                    }
                    break
                }
            }
        }
    }
    func closeAd(v:Int) {
        initializationTopOn.removeADVC(byDelayTime: v, onclose:{
            for (_, ad) in BbbAdManager.shared.adItems {
                if(ad.status == 3) {
                    ad.changeStatus(st: 4)
                }
            }
        })
        self.isshow = false
    }
    
    @objc func checkOpenADReadyState(){
        BbbAdManager.totalTimeC += kOpenADPerSec
        
        if (self.isEnd() && BbbAdManager.totalTimeC > 8) || BbbAdManager.totalTimeC >=  kOpenAdCTimeLength {
            openADTimer?.invalidate()
            openADTimer = nil
            DispatchQueue.global().async { [weak self] in
                guard self != nil else { return }
                YL_NetWorkManager.loadend(max_ecpm: 0)
                
            }
        }
        
        if self.isshow == false{
            self.showAd(v: self.view!)
        }
        
    }
}
