package com.base.appzxhy.business.ads.admob

import android.os.Bundle
import com.base.appzxhy.MyApplication
import com.base.appzxhy.bean.config.AdConfigBean
import com.base.appzxhy.business.ads.SolarEngineEvent
import com.base.appzxhy.business.ads.taichiPref
import com.base.appzxhy.business.ads.taichiSharedPreferencesEditor
import com.base.appzxhy.business.helper.EventUtils
import com.base.appzxhy.utils.LogEx
import com.facebook.appevents.AppEventsConstants
import com.facebook.appevents.AppEventsLogger
import com.google.android.gms.ads.AdValue
import com.google.android.gms.ads.AdView
import com.google.android.gms.ads.OnPaidEventListener
import com.google.android.gms.ads.appopen.AppOpenAd
import com.google.android.gms.ads.interstitial.InterstitialAd
import com.google.android.gms.ads.nativead.NativeAd
import com.google.android.gms.ads.rewarded.RewardedAd
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.ktx.Firebase
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import org.json.JSONObject
import java.math.BigDecimal
import java.util.Currency
import kotlin.random.Random

class AdmobOnPaidEventListener(
    private val ad: Any?,
    private val coroutineScope: CoroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
) : OnPaidEventListener {

    override fun onPaidEvent(adValue: AdValue) {
        ad ?: return
        onPaidEvent2(ad, adValue)
    }

    fun onPaidEvent2(ad: Any?, adValue: AdValue) {
        coroutineScope.launch {
            try {
                val flag = eventAdRatio()
                if (flag) {
                    SolarEngineEvent.eventSolar(ad, adValue.valueMicros)
                    eventFireBase(adValue)
                    eventEvent(adValue)
                }
            } catch (e: Exception) {
                EventUtils.event("onPaidEvent_Error")
            }
        }
    }

    fun eventAdRatio(): Boolean {
        val adRatio = AdConfigBean.Companion.adsConfigBean.adRatio
        val random = Random.Default.nextInt(1, 100)
        if (random > adRatio) {
            taichiSharedPreferencesEditor.putFloat("TaichiTroasCache", 0f)
            taichiSharedPreferencesEditor.commit()
            EventUtils.event("ad_price_limit")
            return false
        }
        return true
    }

    /**
     * 上报给firebase
     */
    fun eventFireBase(adValue: AdValue) {

        val valueMicros = adValue.valueMicros
        val currencyCode = adValue.currencyCode
        val currentImpressionRevenue = adValue.valueMicros.toDouble() / 1000000.0

        //sp里面的价格值
        val previousTaichiTroasCache = taichiPref.getFloat("TaichiTroasCache", 0f)

        //当前缓存加个值
        val currentTaichiTroasCache = (previousTaichiTroasCache + currentImpressionRevenue).toFloat()

        //价值上报阀值
        val taichiAdValue = AdConfigBean.Companion.adsConfigBean.taichiAdValue / 100f

        val params = Bundle()
        params.putDouble(FirebaseAnalytics.Param.VALUE, currentImpressionRevenue)
        params.putString(FirebaseAnalytics.Param.CURRENCY, "USD")
        LogEx.logDebug("EventOnPaidEventListener", "precisionType=${adValue.precisionType}")
        val precisionType = when (adValue.precisionType) {
            0 -> "UNKNOWN"
            1 -> "ESTIMATED"
            2 -> "PUBLISHER_PROVIDED"
            3 -> "PRECISE"
            else -> "Invalid"
        }
        params.putString("precisionType", precisionType)


        val fbLogger = AppEventsLogger.newLogger(MyApplication.Companion.appContext)

        //上报
        fbLogger.logPurchase(BigDecimal.valueOf(currentImpressionRevenue), Currency.getInstance(currencyCode))


        //上报ad_price
        Firebase.analytics.logEvent("ad_price", Bundle().apply {
            putDouble("valueMicros", valueMicros / 1000000.0)
        })

        //上报Ad_Impression_Revenue
        Firebase.analytics.logEvent("Ad_Impression_Revenue", params)

        //上报Total_Ads_Revenue_001
        if (currentTaichiTroasCache >= taichiAdValue) {//如果超过0.01就触发一次tROAS taichi事件
            val roasbundle = Bundle()
            roasbundle.putDouble(FirebaseAnalytics.Param.VALUE, currentTaichiTroasCache.toDouble())
            roasbundle.putString(FirebaseAnalytics.Param.CURRENCY, "USD")
            Firebase.analytics.logEvent("Total_Ads_Revenue_001", roasbundle)
            taichiSharedPreferencesEditor.putFloat("TaichiTroasCache", 0f)//重新清零，开始计算

            val parameters = Bundle()
            parameters.putString(AppEventsConstants.EVENT_PARAM_CURRENCY, "USD")
            fbLogger.logEvent("ad_value", currentTaichiTroasCache.toDouble(), parameters)
        } else {
            taichiSharedPreferencesEditor.putFloat("TaichiTroasCache", currentTaichiTroasCache)
        }
        taichiSharedPreferencesEditor.commit()
    }

    /**
     * 上报给服务器
     */
    fun eventEvent(adValue: AdValue) {
        val valueMicros = adValue.valueMicros
        val currencyCode = adValue.currencyCode
        val precision = adValue.precisionType

        val obj = JSONObject()
        obj.put("valueMicros", valueMicros)
        obj.put("currencyCode", currencyCode)
        obj.put("precision", precision)

        var key = "ad_price"
        when (ad) {
            is AppOpenAd -> {
                val adUnitId = ad.adUnitId
                val loadedAdapterResponseInfo = ad.responseInfo.loadedAdapterResponseInfo
                val adSourceName = loadedAdapterResponseInfo?.adSourceName
                val adSourceId = loadedAdapterResponseInfo?.adSourceId
                val adSourceInstanceName = loadedAdapterResponseInfo?.adSourceInstanceName
                val adSourceInstanceId = loadedAdapterResponseInfo?.adSourceInstanceId
                val sessionId = ad.responseInfo.responseId
                val extras = ad.responseInfo.responseExtras
                val mediationGroupName = extras.getString("mediation_group_name")
                val mediationABTestName = extras.getString("mediation_ab_test_name")
                val mediationABTestVariant = extras.getString("mediation_ab_test_variant")
                obj.put("ad_unit", "openAd")
                obj.put("adUnitId", adUnitId)
                obj.put("adSourceName", adSourceName)
                obj.put("adSourceId", adSourceId)
                obj.put("adSourceInstanceName", adSourceInstanceName)
                obj.put("adSourceInstanceId", adSourceInstanceId)
                obj.put("mediationGroupName", mediationGroupName)
                obj.put("mediationABTestName", mediationABTestName)
                obj.put("mediationABTestVariant", mediationABTestVariant)
                obj.put("session_id", sessionId)
            }

            is InterstitialAd -> {
                val adUnitId = ad.adUnitId
                val loadedAdapterResponseInfo = ad.responseInfo.loadedAdapterResponseInfo
                val adSourceName = loadedAdapterResponseInfo?.adSourceName
                val adSourceId = loadedAdapterResponseInfo?.adSourceId
                val adSourceInstanceName = loadedAdapterResponseInfo?.adSourceInstanceName
                val adSourceInstanceId = loadedAdapterResponseInfo?.adSourceInstanceId
                val sessionId = ad.responseInfo.responseId
                val extras = ad.responseInfo.responseExtras
                val mediationGroupName = extras.getString("mediation_group_name")
                val mediationABTestName = extras.getString("mediation_ab_test_name")
                val mediationABTestVariant = extras.getString("mediation_ab_test_variant")
                obj.put("ad_unit", "interAd")
                obj.put("adUnitId", adUnitId)
                obj.put("adSourceName", adSourceName)
                obj.put("adSourceId", adSourceId)
                obj.put("adSourceInstanceName", adSourceInstanceName)
                obj.put("adSourceInstanceId", adSourceInstanceId)
                obj.put("mediationGroupName", mediationGroupName)
                obj.put("mediationABTestName", mediationABTestName)
                obj.put("mediationABTestVariant", mediationABTestVariant)
                obj.put("session_id", sessionId)
            }

            is RewardedAd -> {
                val loadedAdapterResponseInfo = ad.responseInfo.loadedAdapterResponseInfo
                val adSourceName = loadedAdapterResponseInfo?.adSourceName
                val adSourceId = loadedAdapterResponseInfo?.adSourceId
                val adSourceInstanceName = loadedAdapterResponseInfo?.adSourceInstanceName
                val adSourceInstanceId = loadedAdapterResponseInfo?.adSourceInstanceId
                val sessionId = ad.responseInfo.responseId
                val extras = ad.responseInfo.responseExtras
                val mediationGroupName = extras.getString("mediation_group_name")
                val mediationABTestName = extras.getString("mediation_ab_test_name")
                val mediationABTestVariant = extras.getString("mediation_ab_test_variant")
                obj.put("adSourceName", adSourceName)
                obj.put("adSourceId", adSourceId)
                obj.put("adSourceInstanceName", adSourceInstanceName)
                obj.put("adSourceInstanceId", adSourceInstanceId)
                obj.put("mediationGroupName", mediationGroupName)
                obj.put("mediationABTestName", mediationABTestName)
                obj.put("mediationABTestVariant", mediationABTestVariant)
                obj.put("session_id", sessionId)
            }

            is NativeAd -> {
                key = "ad_price"
                val loadedAdapterResponseInfo = ad.responseInfo?.loadedAdapterResponseInfo
                val adSourceName = loadedAdapterResponseInfo?.adSourceName
                val adSourceId = loadedAdapterResponseInfo?.adSourceId
                val adSourceInstanceName = loadedAdapterResponseInfo?.adSourceInstanceName
                val adSourceInstanceId = loadedAdapterResponseInfo?.adSourceInstanceId
                val sessionId = ad.responseInfo?.responseId
                val extras = ad.responseInfo?.responseExtras
                val mediationGroupName = extras?.getString("mediation_group_name")
                val mediationABTestName = extras?.getString("mediation_ab_test_name")
                val mediationABTestVariant = extras?.getString("mediation_ab_test_variant")
                obj.put("ad_unit", "nativeAd")
                obj.put("adSourceName", adSourceName)
                obj.put("adSourceId", adSourceId)
                obj.put("adSourceInstanceName", adSourceInstanceName)
                obj.put("adSourceInstanceId", adSourceInstanceId)
                obj.put("mediationGroupName", mediationGroupName)
                obj.put("mediationABTestName", mediationABTestName)
                obj.put("mediationABTestVariant", mediationABTestVariant)
                obj.put("session_id", sessionId)
            }

            else -> {
                runCatching {
                    val adView = ad as AdView
                    val adUnitId = adView.adUnitId
                    val loadedAdapterResponseInfo = adView.responseInfo?.loadedAdapterResponseInfo
                    val adSourceName = loadedAdapterResponseInfo?.adSourceName
                    val adSourceId = loadedAdapterResponseInfo?.adSourceId
                    val adSourceInstanceName = loadedAdapterResponseInfo?.adSourceInstanceName
                    val adSourceInstanceId = loadedAdapterResponseInfo?.adSourceInstanceId
                    val sessionId = adView.responseInfo?.responseId
                    val extras = adView.responseInfo?.responseExtras
                    val mediationGroupName = extras?.getString("mediation_group_name")
                    val mediationABTestName = extras?.getString("mediation_ab_test_name")
                    val mediationABTestVariant = extras?.getString("mediation_ab_test_variant")
                    obj.put("ad_unit", "banner")
                    obj.put("adUnitId", adUnitId)
                    obj.put("adSourceName", adSourceName)
                    obj.put("adSourceId", adSourceId)
                    obj.put("adSourceInstanceName", adSourceInstanceName)
                    obj.put("adSourceInstanceId", adSourceInstanceId)
                    obj.put("mediationGroupName", mediationGroupName)
                    obj.put("mediationABTestName", mediationABTestName)
                    obj.put("mediationABTestVariant", mediationABTestVariant)
                    obj.put("session_id", sessionId)
                }
            }
        }
        EventUtils.event(key, ext = obj)

    }
}