package com.gamedog.statisticreporter.adjust


import android.os.Handler
import android.os.HandlerThread
import android.text.TextUtils
import com.adjust.sdk.Adjust
import com.adjust.sdk.AdjustAdRevenue
import com.adjust.sdk.AdjustConfig
import com.adjust.sdk.AdjustEvent
import com.adjust.sdk.LogLevel
import com.adjust.sdk.OnAttributionChangedListener
import com.ama.core.architecture.BaseApp
import com.ama.core.architecture.util.AndroidUtil
import com.ama.core.architecture.util.SpUtil
import com.gamedog.statisticreporter.StatisticUtil
import com.gamedog.statisticreporter.adjust.AdjustManager.Companion.USER_TYPE_BUY
import com.remax.base.ads.AdRevenueData
import com.remax.base.ads.AdRevenueManager
import com.remax.base.ads.AdRevenueReporter
import com.remax.bill.BuildConfig


class AdjustManager private constructor() {
    companion object {
        @Volatile
        private var INSTANCE: AdjustManager? = null

        fun instance(): AdjustManager {
            return INSTANCE ?: synchronized(this) {
                INSTANCE ?: AdjustManager().also { INSTANCE = it }
            }
        }


        const val ATTRI_TYPE_ORGANIC = "Organic"
        const val ATTRI_TYPE_UNTRUSTED = "Untrusted Devices"
        const val ATTRI_TYPE_GOOGLE = "Google Organic Search"

        const val USER_TYPE_NORMAL = 1
        const val USER_TYPE_BUY = 2
    }

    private var mAdjustInitStartMs: Long = 0
    private val mAppContext = BaseApp.appContext()
    private val mSpHelper = SpHelper()
    private val mUserFromCheckRunnable = kotlinx.coroutines.Runnable {
        run {
            // 所有用户一开始都是自然用户的状态，需要通过调用setOnAttributionChangedListener这个方法（这个方法就是返回用户改变后的状态），获得买量来源信息
            Adjust.getAttribution { attribution ->
                val networkFrom = attribution.network
                var userTypeInt = 0
                if (!TextUtils.isEmpty(networkFrom)) {
                    if (networkFrom.contains(ATTRI_TYPE_GOOGLE) || networkFrom.contains(ATTRI_TYPE_UNTRUSTED)) {
                        userTypeInt = USER_TYPE_NORMAL
                    } else if (!networkFrom.contains(ATTRI_TYPE_ORGANIC)) {
                        userTypeInt = USER_TYPE_BUY
                    }
                }

                if (userTypeInt > 0) {
                    saveUserType(USER_TYPE_NORMAL)
                    mChecker.stopPolling()
                }
            }
        }
    }

    private fun saveUserType(userType: Int) {
        StatisticUtil.reportEvents(StatisticUtil.KEY_adjust_get_success, mapOf("pass_time" to
                (System.currentTimeMillis() - mAdjustInitStartMs)/1000 + 1)
        )
        mSpHelper.saveUserType(userType)
    }

    private val mChecker: PollCheckHelper = PollCheckHelper(180,
        3, mUserFromCheckRunnable, {
            saveUserType(USER_TYPE_NORMAL)
        })


    fun initSdk(appToken: String) {
        val isDebug = BuildConfig.DEBUG
        val environment = if (isDebug) AdjustConfig.ENVIRONMENT_SANDBOX else AdjustConfig.ENVIRONMENT_PRODUCTION
        val config = AdjustConfig(mAppContext, appToken, environment).apply {
            setLogLevel(if (isDebug) LogLevel.VERBOSE else LogLevel.WARN)
            enableSendingInBackground()
            enableCoppaCompliance()
            enableCostDataInAttribution()

            onAttributionChangedListener = OnAttributionChangedListener {
            }
        }
        StatisticUtil.reportEvents(StatisticUtil.KEY_adjust_init)
        mAdjustInitStartMs = System.currentTimeMillis()
        Adjust.initSdk(config)
        Adjust.enable()

        if (!mSpHelper.hasIdentityUserType()) {
            mChecker.startPolling()
        }
        setReporter2Bill()
    }

    private fun setReporter2Bill() {
        AdRevenueManager.addReporter(object: AdRevenueReporter {
            override fun reportAdRevenue(adRevenueData: AdRevenueData) {
                reportAdRevenueInfo(adRevenueData)
            }
        } )
    }

    fun reportAdRevenueInfo(revenueValue: AdRevenueData) {
        val adjustAdRevenue = AdjustAdRevenue(getRandomFixSourceStr()).apply {
            setRevenue(revenueValue.revenue.value, revenueValue.revenue.currencyCode /*"USD"*/)  // ad收益数值及单位
            setAdRevenueNetwork(revenueValue.adRevenueNetwork) // 渠道来源
            setAdRevenueUnit(revenueValue.adRevenueUnit)  // ad收入来源单元
            setAdRevenuePlacement(revenueValue.adRevenuePlacement)  // 位置
        }
        Adjust.trackAdRevenue(adjustAdRevenue)
    }

    /**
     *   val event = AdjustEvent("g3mfiw")
     *   event.setCallbackId("f2e728d8-271b-49ab-80ea-27830a215147")
     */
    fun reportAdjustEvent(event: AdjustEvent, callbackId: String?) {
        callbackId?.let {
            event.callbackId = callbackId
        }
        Adjust.trackEvent(event)
    }

    fun isUserBuy(): Boolean {
        return mSpHelper.isUserBuy()
    }





    //----------------------- PRIVATE ------------------------//
    private fun getRandomFixSourceStr(): String {
        val randomInt = AndroidUtil.randomInt(1, 10)
        return if (randomInt <= 2) "ironsource_sdk" else "applovin_max_sdk"
    }



}



class SpHelper {
    companion object {
        const val KEY_USER_FROM_TYPE = "KEY_USER_FROM_TYPE"  // 1:自然用户  2：买量用户
    }

    private var mUserType = SpUtil.instance().getInt(KEY_USER_FROM_TYPE)

    fun hasIdentityUserType(): Boolean {
        return mUserType > 0
    }

    fun saveUserType(userType: Int) {
        mUserType = userType
        SpUtil.instance().putInt(KEY_USER_FROM_TYPE, mUserType)
    }

    fun isUserBuy(): Boolean {
        return mUserType == USER_TYPE_BUY
    }

}


class PollCheckHelper(private val mTotalCheckSec: Int,
                      private val mTotalCheckGapSec: Int,
                      private val mCheckRunnable: Runnable,
                      private val mFinishCallback: ()->Unit) {

    private var handlerThread: HandlerThread? = null
    private var handler: Handler? = null
    private var mStartMs: Long = 0L
    private var mPollRunnable: Runnable? = null
    private var mHasStop = false
    private var mHasStarted = false


    fun startPolling() {
        if (mHasStarted) {
            return
        }
        handlerThread = HandlerThread("PollingThread").apply { start() }
        handler = Handler(handlerThread!!.looper)
        mStartMs = System.currentTimeMillis()

        mPollRunnable = Runnable {
            mCheckRunnable.run()
            val hasExpired = System.currentTimeMillis() - mStartMs >= mTotalCheckSec * 1000
            if (hasExpired || mHasStop) {
                stopPolling()
                if (hasExpired) {
                    mFinishCallback.invoke()
                }
            } else {
                handler?.postDelayed(mPollRunnable!!, mTotalCheckGapSec * 1000L)
            }
        }
        handler?.post(mPollRunnable!!)
        mHasStarted = true
    }

    fun stopPolling() {
        mHasStop = true
        mPollRunnable?.let {
            handler?.removeCallbacks(it)
        }
        handlerThread?.quitSafely()
        mPollRunnable = null
    }

}