package com.gh.ad

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.SharedPreferences
import android.graphics.drawable.Animatable
import android.os.Build
import android.os.Message
import android.text.TextUtils
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.TextView
import androidx.appcompat.content.res.AppCompatResources
import androidx.fragment.app.Fragment
import com.therouter.TheRouter
import com.facebook.drawee.controller.BaseControllerListener
import com.facebook.drawee.view.SimpleDraweeView
import com.facebook.imagepipeline.image.ImageInfo
import com.gh.common.exposure.ExposureManager
import com.gh.common.util.DirectUtils.directToLinkPage
import com.gh.common.util.LogUtils
import com.gh.common.util.NewFlatLogUtils
import com.gh.common.util.PackageUtils
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.MainActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.activity.BaseActivity
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.exposure.meta.MetaUtil
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.core.provider.ICsjAdProvider
import com.gh.gamecenter.core.utils.CurrentActivityHolder
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.TimeUtils.getToday
import com.gh.gamecenter.entity.AdConfig
import com.gh.gamecenter.entity.StartupAdEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent.Companion.createEvent
import com.gh.gamecenter.feature.exposure.ExposureType
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.schedulers.Schedulers
import java.util.Locale

/**
 * 广告实现代理类
 *
 * 由它来分发功能实现到具体的实现
 *
 * 以开屏广告为例，有两种实现（1. 自有的广告实现 2. 穿山甲的开屏广告实现 ）
 */
object AdDelegateHelper {

    private var mCsjAdImpl: ICsjAdProvider? = null

    private val mAdConfigList: ArrayList<AdConfig> by lazy { arrayListOf() }

    private var mSplashAd: AdConfig? = null
    private var mDownloadManagerAd: AdConfig? = null
    private val mGameSearchAdList: ArrayList<AdConfig> by lazy { arrayListOf() }
    private var mVGameLaunchAd: AdConfig? = null

    private var ownerSplashAdLoadTime = 0L

    val vGameLaunchAd: AdConfig?
        get() = mVGameLaunchAd

    val splashAdDisplayInterval: Int
        get() = mSplashAd?.ownerAd?.startAd?.displayInterval ?: 3

    private const val AD_SDK_CSJ = "穿山甲"
    const val AD_TYPE_SDK = "third_party_ads" // 第三方 SDK 广告
    const val AD_TYPE_OWNER = "owner_ads" // 自有广告

    private const val KEY_CACHE_CONFIG = "cache_config" // 放在 SP 里的广告缓存（避免接口加载问题）

    private val mAdConfigSp: SharedPreferences by lazy {
        HaloApp.getInstance().getSharedPreferences("AdConfig", Context.MODE_PRIVATE)
    }

    var isShowingSplashAd = false // 是否正在显示开屏广告
    var isOwnerSplashAdShown = false // 自有开屏广告是否展示
    var gameSearchKeyword = ""

    fun initAdSdk(context: Context) {
        if (AdPluginDownloadHelper.isCsjPluginDownloaded()) {
            initAdSdkInternal(context)
        } else {
            // 首次启动，为了不影响首页加载，延迟 3 秒再下载广告插件并初始化
            AppExecutor.uiExecutor.executeWithDelay({
                AdPluginDownloadHelper.downloadPluginIfNeeded(isCsj = true) {
                    initAdSdkInternal(context)
                }
            }, 3000L)
        }
    }

    private fun initAdSdkInternal(context: Context) {
        // 初始化穿山甲
        if (mCsjAdImpl == null) {
            mCsjAdImpl = TheRouter.get(ICsjAdProvider::class.java)
            val csjAppId = if (EnvHelper.isDevEnv) BuildConfig.DEV_CSJ_APPID else BuildConfig.CSJ_APPID
            mCsjAdImpl?.initSDK(context, csjAppId, HaloApp.getInstance().oaid)
            // 监听亮色/暗色模式切换
            DarkModeUtils.registerModeChangeListener {
                val topActivity = CurrentActivityHolder.getCurrentActivity() ?: return@registerModeChangeListener
                updateThemeStatus(context, DarkModeUtils.isDarkModeOn(topActivity))
            }
        }
    }

    /**
     * 请求接口获取广告相关配置
     */
    @SuppressLint("CheckResult")
    fun requestAdConfig(isFromRetry: Boolean, keyword: String = "", callback: (() -> Unit)? = null) {
        // mAdConfigList 不为空不需要重试
        if (isFromRetry && mAdConfigList.isNotEmpty()) {
            return
        }

        val paramsMap = if (keyword.isNotEmpty()) {
            mapOf("keyword" to keyword, "android_sdk_version" to Build.VERSION.SDK_INT)
        } else {
            mapOf("android_sdk_version" to Build.VERSION.SDK_INT)
        }
        RetrofitManager.getInstance()
            .newApi
            .getAdConfig(paramsMap)
            .subscribeOn(Schedulers.io())
            .subscribe(object : BiResponse<List<AdConfig>>() {
                override fun onSuccess(data: List<AdConfig>) {
                    gameSearchKeyword = keyword
                    handleAdConfig(data)
                    callback?.invoke()

                    // 缓存数据到 SP 供接口请求失败用
                    SPUtils.setString(mAdConfigSp, KEY_CACHE_CONFIG, data.toJson())
                }

                override fun onFailure(exception: Exception) {
                    super.onFailure(exception)

                    // 若接口请求失败时，从 SP 里获取上次缓存的数据
                    val cachedConfig: List<AdConfig>? = SPUtils.getString(mAdConfigSp, KEY_CACHE_CONFIG).toObject()
                    if (cachedConfig != null && mAdConfigList.isEmpty()) {
                        handleAdConfig(cachedConfig)
                    }

                    callback?.invoke()
                }
            })
    }

    /**
     * 获取搜索页的广告列表
     */
    fun getGameSearchAdList(): ArrayList<AdConfig> {
        return mGameSearchAdList
    }

    /**
     * 获取下载管理页的广告
     */
    fun getDownloadManagerAd(): AdConfig? {
        return mDownloadManagerAd
    }

    /**
     * 处理广告配置
     */
    fun handleAdConfig(configList: List<AdConfig>) {
        mAdConfigList.clear()
        mGameSearchAdList.clear()
        mSplashAd = null
        mDownloadManagerAd = null
        mVGameLaunchAd = null
        for (config in configList) {
            mAdConfigList.add(config)
            // 处理返回的数据
            when (config.location) {
                "halo_launch" -> {
                    config.ownerAd?.startAd?.let { it.id = config.ownerAd.id }

                    // HarmonyOS 2.2.0 版本不展示第三方开屏广告 (因为会引起奇怪的闪退)
                    if (MetaUtil.getRom().name == "HarmonyOS"
                        && MetaUtil.getRom().versionName == "2.2.0"
                        && config.displayRule.adSource == AD_TYPE_SDK) {

                        return
                    }

                    // 华为系 Android 10 不展示第三方开屏广告 (因为会引起奇怪的闪退)
                    if (isBuggyHuaweiDevice() && config.displayRule.adSource == AD_TYPE_SDK) {
                        return
                    }

                    mSplashAd = config
                }

                "download_manager" -> mDownloadManagerAd = config
                "game_search" -> config.let { mGameSearchAdList.add(it) }
                "helper_launch" -> mVGameLaunchAd = config
            }
        }
    }

    /**
     * 是否需要显示开屏广告
     * @param isHotLaunch 是否为热启动
     */
    fun shouldShowStartUpAd(isHotLaunch: Boolean): Boolean {
        return mSplashAd != null
                && !isShowingSplashAd
                && (!isHotLaunch || shouldShowStartUpAdWhenHotLaunch())
                && !isMatchAdFreeRule(mSplashAd)
                && isMatchStartUpAdDisplayRule()
    }

    /**
     * 热启动是否需要显示开屏广告(目前只展示第三方广告)
     */
    private fun shouldShowStartUpAdWhenHotLaunch() = (mCsjAdImpl != null)
            && mSplashAd?.displayRule?.hotStartSplashAd?.type == AD_TYPE_SDK
            && mSplashAd?.hotStartThirdPartyAd != null
            && !isBuggyHuaweiDevice()

    /**
     * 是否需要显示下载管理广告
     */
    fun shouldShowDownloadManagerAd(): Boolean {
        return mDownloadManagerAd != null && !isMatchAdFreeRule(mDownloadManagerAd) && isMatchDownloadManagerAdDisplayRule()
    }

    fun shouldShowHelperLaunchAd(): Boolean {
        return mVGameLaunchAd != null && !isMatchAdFreeRule(mVGameLaunchAd) && isMatchAdDisplayRule(mVGameLaunchAd, Constants.SP_LAST_HELPER_LAUNCH_AD_SHOW_TIME)
    }

    /**
     * 是否需要显示游戏搜索广告
     */
    fun shouldShowGameSearchAd(adConfig: AdConfig): Boolean {
        return !isMatchAdFreeRule(adConfig) && isMatchGameSearchAdDisplayRule(adConfig)
    }

    /**
     * 是否在免广告时长内
     */
    private fun isMatchAdFreeRule(adConfig: AdConfig?): Boolean {
        adConfig?.displayRule?.run {
            if (adFreeDuration > 0) {
                val ghInstalledDurationInHours = (System.currentTimeMillis() - PackageUtils.getInstalledTime(
                    HaloApp.getInstance(),
                    BuildConfig.APPLICATION_ID
                )).toFloat() / 1000 / 3600
                return ghInstalledDurationInHours < adFreeDuration
            } else {
                return false
            }
        }
        return false
    }

    /**
     * 是否大于开屏广告展示间隔时长
     */
    private fun isMatchStartUpAdDisplayRule(): Boolean = isMatchAdDisplayRule(mSplashAd, Constants.SP_LAST_SPLASH_AD_SHOW_TIME)

    /**
     * 是否大于广告管理展示间隔时长
     */
    private fun isMatchDownloadManagerAdDisplayRule(): Boolean = isMatchAdDisplayRule(mDownloadManagerAd, Constants.SP_LAST_DOWNLOAD_MANAGER_AD_SHOW_TIME)
    private fun isMatchAdDisplayRule(adConfig: AdConfig?, spKey: String): Boolean {
        adConfig?.displayRule?.run {
            if (adDisplayInterval > 0) {
                val lastShowTime = SPUtils.getLong(spKey, 0L)
                val durationInMinutes = (System.currentTimeMillis() - lastShowTime).toFloat() / 1000 / 60
                return durationInMinutes > adDisplayInterval
            } else {
                return true
            }
        }
        return true
    }

    /**
     * 是否大于游戏搜索展示间隔时长
     */
    private fun isMatchGameSearchAdDisplayRule(adConfig: AdConfig?): Boolean {
        adConfig?.displayRule?.run {
            if (adDisplayInterval > 0) {
                val lastShowTime = SPUtils.getLong(Constants.SP_LAST_GAME_SEARCH_AD_SHOW_TIME + adConfig.position, 0L)
                val durationInMinutes = (System.currentTimeMillis() - lastShowTime).toFloat() / 1000 / 60
                return durationInMinutes > adDisplayInterval
            } else {
                return true
            }
        }
        return true
    }

    /**
     * 更新主题样式
     */
    private fun updateThemeStatus(context: Context, isDarkMode: Boolean) {
        mCsjAdImpl?.updateThemeStatus(context, isDarkMode)
    }

    /**
     * 请求开屏广告
     */
    @JvmStatic
    fun requestSplashAd(
        activity: Activity,
        adViewWidthInPx: Int,
        adViewHeightInPx: Int,
        adViewWidthInDp: Float,
        adViewHeightInDp: Float,
        startAdContainer: ViewGroup,
        sdkStartAdContainer: ViewGroup,
        sdkJumpBtn: TextView,
        adsViewGroup: FrameLayout,
        handler: BaseActivity.BaseHandler,
        isHotLaunch: Boolean,
        hideAction: () -> Unit
    ) {
        val hideCallback = {
            isShowingSplashAd = false
            isOwnerSplashAdShown = false
            hideAction.invoke()
        }
        if (mSplashAd != null) {
            when (if (isHotLaunch) mSplashAd!!.displayRule.hotStartSplashAd?.type else mSplashAd!!.displayRule.adSource) {
                AD_TYPE_SDK -> {
                    isShowingSplashAd = true
                    requestThirdPartySplashAd(
                        activity,
                        adViewWidthInPx,
                        adViewHeightInPx,
                        adViewWidthInDp,
                        adViewHeightInDp,
                        startAdContainer,
                        sdkStartAdContainer,
                        sdkJumpBtn,
                        adsViewGroup,
                        handler,
                        isHotLaunch,
                        hideCallback
                    )
                }

                AD_TYPE_OWNER -> {
                    isShowingSplashAd = true
                    requestStandardSplashAd(
                        activity,
                        adViewWidthInPx,
                        adViewHeightInPx,
                        adViewWidthInDp,
                        adViewHeightInDp,
                        startAdContainer,
                        sdkStartAdContainer,
                        sdkJumpBtn,
                        adsViewGroup,
                        handler,
                        isHotLaunch,
                        hideCallback
                    )
                }
            }
        } else {
            hideCallback.invoke()
        }
    }

    /**
     * 获取第三方开屏广告
     */
    private fun requestThirdPartySplashAd(
        activity: Activity,
        adViewWidthInPx: Int,
        adViewHeightInPx: Int,
        adViewWidthInDp: Float,
        adViewHeightInDp: Float,
        startAdContainer: ViewGroup,
        sdkStartAdContainer: ViewGroup,
        sdkJumpBtn: TextView,
        adsViewGroup: FrameLayout,
        handler: BaseActivity.BaseHandler,
        isHotLaunch: Boolean,
        hideCallback: () -> Unit
    ) {
        // 第三方开屏广告回调，失败时根据接口配置选项决定是否显示自有开屏广告
        val sdkSplashCallback: (isSuccess: Boolean) -> Unit = { isSuccess ->
            if (isSuccess) {
                hideCallback.invoke()
                SPUtils.setLong(Constants.SP_LAST_SPLASH_AD_SHOW_TIME, System.currentTimeMillis())
            } else {
                if (mSplashAd?.displayRule?.adSource == AD_TYPE_SDK && mSplashAd?.displayRule?.onFailedAction == "show" && !isHotLaunch) {
                    sdkStartAdContainer.visibility = View.GONE
                    requestStandardSplashAd(
                        activity,
                        adViewWidthInPx,
                        adViewHeightInPx,
                        adViewWidthInDp,
                        adViewHeightInDp,
                        startAdContainer,
                        sdkStartAdContainer,
                        sdkJumpBtn,
                        adsViewGroup,
                        handler,
                        isHotLaunch,
                        hideCallback
                    )
                } else {
                    hideCallback.invoke()
                }
            }
        }

        val thirdPartyAd = if (isHotLaunch) mSplashAd?.hotStartThirdPartyAd else mSplashAd?.thirdPartyAd

        // 第三方广告的数据为空，按加载失败处理
        if (mSplashAd == null || thirdPartyAd == null) {
            sdkSplashCallback.invoke(false)
            return
        }

        val timeout = if (isHotLaunch) {
            ((mSplashAd?.displayRule?.hotStartSplashAd?.timeout ?: 3.5F) * 1000).toInt()
        } else {
            ((mSplashAd?.displayRule?.timeout ?: 3.5F) * 1000).toInt()
        }

        if (thirdPartyAd.sourceName == AD_SDK_CSJ) {
            sdkStartAdContainer.visibility = View.VISIBLE
            requestCsjSplashAd(
                activity,
                adViewWidthInPx,
                adViewHeightInPx,
                adViewWidthInDp,
                adViewHeightInDp,
                sdkStartAdContainer,
                sdkJumpBtn,
                timeout,
                isHotLaunch,
                sdkSplashCallback
            )
        }
    }

    /**
     * 获取穿山甲的开屏广告
     */
    private fun requestCsjSplashAd(
        activity: Activity,
        adViewWidthInPx: Int,
        adViewHeightInPx: Int,
        adViewWidthInDp: Float,
        adViewHeightInDp: Float,
        startAdContainer: ViewGroup,
        sdkJumpBtn: TextView,
        timeout: Int,
        isHotLaunch: Boolean,
        callback: (isSuccess: Boolean) -> Unit,
    ) {
        val thirdPartyAd = if (isHotLaunch) mSplashAd?.hotStartThirdPartyAd else mSplashAd?.thirdPartyAd
        if (mCsjAdImpl == null || thirdPartyAd == null) {
            callback.invoke(false)
        } else {
            sdkJumpBtn.setOnClickListener {
                callback.invoke(true)
                if (activity is BaseActivity) {
                    activity.baseHandler.removeMessages(MainActivity.COUNTDOWN_SDK_AD)
                }
            }

            val onAdShowAction = {
                sdkJumpBtn.visibility = View.VISIBLE
                if (activity is BaseActivity) {
                    activity.baseHandler.sendEmptyMessageDelayed(MainActivity.COUNTDOWN_SDK_AD, 1000)
                }
                SensorsBridge.trackEvent("ThirdPartyAdShow",
                    "ad_source", thirdPartyAd.sourceName,
                    "ad_id", thirdPartyAd.slotId,
                    "ad_format", mSplashAd?.typeChinese ?: "",
                    "ad_placement", "光环启动",
                    "launch_type", if (isHotLaunch) "热启动" else "冷启动",
                    "ad_space_id", mSplashAd?.id ?: "",
                    "ad_space_name", mSplashAd?.name ?: ""
                )
            }
            val onAdClickAction = {
                callback.invoke(true)
                SensorsBridge.trackEvent("ThirdPartyAdClick",
                    "ad_source", thirdPartyAd.sourceName,
                    "ad_id", thirdPartyAd.slotId,
                    "ad_format", mSplashAd?.typeChinese ?: "",
                    "ad_placement", "光环启动",
                    "launch_type", if (isHotLaunch) "热启动" else "冷启动",
                    "ad_space_id", mSplashAd?.id ?: "",
                    "ad_space_name", mSplashAd?.name ?: ""
                )
            }
            mCsjAdImpl?.requestSplashAd(
                activity,
                thirdPartyAd.slotId,
                adViewWidthInPx,
                adViewHeightInPx,
                adViewWidthInDp,
                adViewHeightInDp,
                startAdContainer,
                timeout,
                onAdShowAction,
                onAdClickAction,
                callback,
            )
        }
    }

    /**
     * 显示自有的开屏广告
     */
    private fun requestStandardSplashAd(
        activity: Activity,
        adViewWidthInPx: Int,
        adViewHeightInPx: Int,
        adViewWidthInDp: Float,
        adViewHeightInDp: Float,
        startAdContainer: ViewGroup,
        sdkStartAdContainer: ViewGroup,
        sdkJumpBtn: TextView,
        adsViewGroup: FrameLayout,
        handler: BaseActivity.BaseHandler,
        isHotLaunch: Boolean,
        hideCallback: () -> Unit
    ) {
        val splashAd = mSplashAd?.ownerAd?.startAd
        val onEmptyCallback = {
            if (mSplashAd?.displayRule?.adSource == AD_TYPE_OWNER && mSplashAd?.displayRule?.onFailedAction == "show" && mSplashAd?.thirdPartyAd != null) {
                // 自有广告为空时，显示第三方广告
                requestThirdPartySplashAd(
                    activity,
                    adViewWidthInPx,
                    adViewHeightInPx,
                    adViewWidthInDp,
                    adViewHeightInDp,
                    startAdContainer,
                    sdkStartAdContainer,
                    sdkJumpBtn,
                    adsViewGroup,
                    handler,
                    isHotLaunch,
                    hideCallback
                )
            } else {
                hideCallback.invoke()
            }
        }
        if (splashAd == null) {
            onEmptyCallback.invoke()
            return
        }

        if (!TextUtils.isEmpty(splashAd.img)) {
            val showedTodayTimestamp = SPUtils.getString(Constants.SP_STARTUP_AD_TIMESTAMP, "") ?: ""
            when (splashAd.rule) {
                "each" -> showStandardSplashAd(splashAd, startAdContainer, handler, hideCallback)
                "once" -> if (TextUtils.isEmpty(showedTodayTimestamp)
                    || !showedTodayTimestamp.contains(splashAd.id)
                ) {
                    showStandardSplashAd(splashAd, startAdContainer, handler, hideCallback)
                } else {
                    onEmptyCallback.invoke()
                }

                "everyday" -> {
                    val today = getToday()
                    if (TextUtils.isEmpty(showedTodayTimestamp)
                        || !showedTodayTimestamp.contains(today)
                        || !showedTodayTimestamp.contains(splashAd.id)
                    ) {
                        showStandardSplashAd(splashAd, startAdContainer, handler, hideCallback)
                    } else {
                        onEmptyCallback.invoke()
                    }
                }

                else -> hideCallback.invoke()
            }
            SPUtils.setString(Constants.SP_STARTUP_AD_TIMESTAMP, splashAd.id + getToday())
        } else {
            hideCallback.invoke()
        }
    }

    private fun showStandardSplashAd(
        ad: StartupAdEntity,
        startAdContainer: ViewGroup,
        handler: BaseActivity.BaseHandler,
        hideCallback: () -> Unit
    ) {
        isOwnerSplashAdShown = false

        val jumpBtn = startAdContainer.findViewById<TextView>(R.id.jumpBtn)
        val jumpDetailBtn: TextView = startAdContainer.findViewById(R.id.jumpDetailBtn)
        val adImage: SimpleDraweeView = startAdContainer.findViewById(R.id.adImage)
        val adVideo = startAdContainer.findViewById<SplashAdVideoView>(R.id.ad_video)
        val icpContainer: View? = startAdContainer.findViewById(R.id.startAdIcpContainer)
        startAdContainer.visibility = View.VISIBLE
        icpContainer?.visibility = View.VISIBLE
        jumpBtn.text = startAdContainer.context.getString(R.string.splash_jump, splashAdDisplayInterval)

        jumpDetailBtn.text = ad.desc
        jumpDetailBtn.setDrawableEnd(
            AppCompatResources.getDrawable(
                startAdContainer.context,
                R.drawable.ic_startup_ad_arrow
            ), null, null
        )

        if (ad.isImageType) {
            adVideo.visibleIf(false)
            adImage.visibleIf(true)
            ImageUtils.displayWithCallback(adImage, ad.img, true, object : BaseControllerListener<ImageInfo>() {
                override fun onSubmit(id: String?, callerContext: Any?) {
                    super.onSubmit(id, callerContext)
                    adImage.post {
                        ownerSplashAdLoadTime = System.currentTimeMillis()
                        NewFlatLogUtils.logSplashAdLoad(ad.id)
                    }
                }

                override fun onFinalImageSet(id: String?, imageInfo: ImageInfo?, animatable: Animatable?) {
                    isOwnerSplashAdShown = true
                    adImage.post {
                        NewFlatLogUtils.logSplashAdShow(ad.id, System.currentTimeMillis() - ownerSplashAdLoadTime)
                    }
                }

                override fun onFailure(id: String?, throwable: Throwable?) {
                    super.onFailure(id, throwable)
                    NewFlatLogUtils.logSplashAdFail(ad.id, "启动广告图加载失败")
                }
            })
        } else {
            adImage.visibleIf(false)
            adVideo.startPlay(ad.video.url)
        }
        startAdContainer.setOnClickListener {
            // 拦截点击事件传递
        }
        jumpBtn.setOnClickListener {
            it.debounceActionWithInterval(1000L) {
                if (!isOwnerSplashAdShown) {
                    NewFlatLogUtils.logSplashAdFail(ad.id, "加载过程中点击跳过广告")
                }
                handler.removeMessages(MainActivity.COUNTDOWN_AD)
                hideCallback.invoke()
                val linkEntity = ad.jump
                NewFlatLogUtils.logOpenScreenAdSkip(
                    ad.id,
                    (if (linkEntity.text != null) linkEntity.text else "")!!,
                    (if (linkEntity.type != null) linkEntity.type else "")!!,
                    (if (linkEntity.link != null) linkEntity.link else "")!!
                )
                SensorsBridge.trackEvent(
                    "SplashAdOwnSkip",
                    "splash_ad_id",
                    ad.id,
                    "link_type",
                    linkEntity.type ?: "",
                    "link_id",
                    linkEntity.link ?: "",
                    "link_text",
                    linkEntity.text ?: ""
                )
            }
        }
        val sources: MutableList<ExposureSource> = ArrayList()
        sources.add(ExposureSource("开屏广告", ad.id))
        val event = createEvent(null, sources, null, ExposureType.EXPOSURE)
        ExposureManager.log(event)
        if (ad.button) {
            jumpDetailBtn.setOnClickListener { v: View ->
                val linkEntity = ad.jump
                directToLinkPage(v.context, linkEntity, "(启动广告)", "", event)
                SensorsBridge.trackEvent(
                    "SplashAdOwnClick",
                    "splash_ad_id",
                    ad.id,
                    "link_type",
                    linkEntity.type ?: "",
                    "link_id",
                    linkEntity.link ?: "",
                    "link_text",
                    linkEntity.text ?: ""
                )
                v.postDelayed({
                    handler.removeMessages(MainActivity.COUNTDOWN_AD)
                    hideCallback.invoke()
                }, 1000)
            }
            jumpDetailBtn.visibility = View.VISIBLE
            LogUtils.logStartAd("watch_start_ads", ad)
        } else {
            LogUtils.logStartAd("start_ads", ad)
        }
        SPUtils.setLong(Constants.SP_LAST_SPLASH_AD_SHOW_TIME, System.currentTimeMillis())
        val msg = Message.obtain()
        msg.what = MainActivity.COUNTDOWN_AD
        msg.obj = ad
        handler.sendMessageDelayed(msg, 1000)
    }

    /**
     * 获取第三方信息流广告
     */
    fun requestThirdPartyFlowAd(
        fragment: Fragment,
        slotId: String,
        adContainerView: ViewGroup,
        expressViewWidth: Float,
        onAdShowAction: () -> Unit,
        onAdClickAction: () -> Unit,
        callback: (isSuccess: Boolean) -> Unit,
    ) {
        mCsjAdImpl?.requestFlowAd(fragment, adContainerView, slotId, expressViewWidth, onAdShowAction, onAdClickAction, callback)
    }

    /**
     * 获取第三方 Banner 广告
     */
    fun requestThirdPartyBannerAd(
        fragment: Fragment,
        containerView: ViewGroup,
        ad: AdConfig.ThirdPartyAd,
        expressViewWidthInDp: Float,
        onAdShowAction: () -> Unit,
        onAdClickAction: () -> Unit,
        callback: (isSuccess: Boolean) -> Unit
    ) {

        val slotId = ad.slotId
        val displayRatio: Float = if (ad.displaySize.isEmpty()) {
            2F
        } else {
            val array = ad.displaySize.split("*")
            if (array.size == 2) {
                array[0].toFloat() / array[1].toFloat()
            } else {
                2F
            }
        }
        val expressViewHeightInDp = expressViewWidthInDp / displayRatio

        mCsjAdImpl?.requestBannerAd(
            fragment,
            containerView,
            slotId,
            expressViewWidthInDp,
            expressViewHeightInDp,
            onAdShowAction,
            onAdClickAction,
            callback
        )
    }

    /**
     * 获取第三方 全屏/插屏 广告
     */
    fun requestFullScreenAd(
        fragment: Fragment,
        ad: AdConfig.ThirdPartyAd,
        onAdShowAction: () -> Unit,
        onAdClickAction: () -> Unit,
        callback: (isSuccess: Boolean) -> Unit
    ) {
        val slotId = ad.slotId
        mCsjAdImpl?.requestFullScreenAd(
            fragment,
            slotId,
            onAdShowAction,
            onAdClickAction,
            callback
        )
    }

    /**
     * 取消开屏广告
     */
    fun cancelSplashAd(context: Context) {
        mCsjAdImpl?.cancelSplashAd(context)
    }

    /**
     * 是否为有问题的华为系 Android 10 设备
     */
    private fun isBuggyHuaweiDevice(): Boolean {
        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {
            val manufacturer = Build.MANUFACTURER.lowercase(Locale.CHINA) ?: ""
            return manufacturer == "huawei" || manufacturer == "honor"
        } else {
            return false
        }
    }

}