package com.gh.gamecenter.csj

import android.app.Activity
import android.content.Context
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.bykv.vk.openvk.*
import com.bykv.vk.openvk.TTFullVideoObject.FullVideoVsInteractionListener
import com.bykv.vk.openvk.TTVfNative.FullScreenVideoAdListener
import com.bykv.vk.openvk.TTVfNative.NtExpressVfListener
import com.bykv.vk.openvk.stub.server.MainServerManager
import com.gh.gamecenter.common.utils.PackageFlavorHelper
import com.gh.gamecenter.common.utils.doOnFragmentDestroy
import com.lightgame.utils.Utils
import java.lang.reflect.Field

object CsjAdHelper {

    const val TAG = "CsjAdHelper"

    var mIsInitialed = false

    fun init(context: Context, csjId: String, oaid: String) {

        try {
            val serverContentProvider = MainServerManager()
            val contextField: Field = serverContentProvider.javaClass.superclass.superclass.getDeclaredField("mContext")
            contextField.isAccessible = true
            contextField.set(serverContentProvider, context)
            serverContentProvider.onCreate()
        } catch (e: Exception) {
            e.printStackTrace()
        }

        // 强烈建议在应用对应的Application#onCreate()方法中调用，避免出现content为null的异常
        TTVfSdk.init(
            context,
            TTVfConfig.Builder()
                .appId(csjId)// xxxxxxx为穿山甲媒体平台注册的应用ID
                .useTextureView(true) // 默认使用SurfaceView播放视频广告,当有SurfaceView冲突的场景，可以使用TextureView
                .appName("光环助手")
                .titleBarTheme(TTVfConstant.TITLE_BAR_THEME_DARK)//落地页主题
                .allowShowNotify(true) // 是否允许sdk展示通知栏提示,若设置为false则会导致通知栏不显示下载进度，存在违规风险，请勿随意更改
                .debug(PackageFlavorHelper.IS_TEST_FLAVOR) // 测试阶段打开，可以通过日志排查问题，上线时去除该调用
                .directDownloadNetworkType(TTVfConstant.NETWORK_STATE_WIFI) // 允许直接下载的网络状态集合,没有设置的网络下点击下载apk会有二次确认弹窗，弹窗中会披露应用信息
                .supportMultiProcess(false) // 是否支持多进程，true支持
                .customController(object : TTCustomController() {
                    /**
                     * 是否允许SDK主动使用地理位置信息
                     *
                     * @return true可以获取，false禁止获取。默认为true
                     */
                    override fun isCanUseLocation(): Boolean = false

                    /**
                     * 是否允许SDK主动使用手机硬件参数，如：imei
                     *
                     * @return true可以使用，false禁止使用。默认为true
                     */
                    override fun isCanUsePhoneState() = false

                    /**
                     * 是否允许SDK主动使用WRITE_EXTERNAL_STORAGE权限
                     *
                     * @return true可以使用，false禁止使用。默认为true
                     */
                    override fun isCanUseWriteExternal(): Boolean = false

                    /**
                     * 开发者可以传入oaid
                     *
                     * @return oaid
                     */
                    override fun getDevOaid(): String = oaid
                })
                .build())

        TTVfSdk.start(object : TTVfSdk.Callback {
            override fun success() {
                Utils.log(TAG, "穿山甲初始化成功")
                mIsInitialed = true
            }

            override fun fail(p0: Int, p1: String?) {
                Utils.log(TAG, "穿山甲初始化失败， $p0 $p1")
                mIsInitialed = false
            }
        })
    }

    fun updateThemeStatus(isDarkMode: Boolean) {
        val adManager = TTVfSdk.getVfManager()
        adManager.themeStatus = if (isDarkMode) 1 else 0
    }

    /**
     * 请求启动广告
     */
    fun requestSplashAd(
        activity: Activity,
        slotId: String,
        adViewWidthInPx: Int,
        adViewHeightInPx: Int,
        adViewWidthInDp: Float,
        adViewHeightInDp: Float,
        startAdContainer: ViewGroup,
        timeout: Int,
        onAdShowAction: () -> Unit,
        onAdClickAction: () -> Unit,
        callback: (isSuccess: Boolean) -> Unit,
    ) {
        val mTTVfNative = TTVfSdk.getVfManager().createVfNative(activity)

        val adSlot = VfSlot.Builder()
            .setCodeId(slotId)
            // 不区分渲染方式，要求开发者同时设置setImageAcceptedSize（单位：px）和setExpressViewAcceptedSize（单位：dp ）接口，不同时设置可能会导致展示异常。
            .setImageAcceptedSize(adViewWidthInPx, adViewHeightInPx)
            .setExpressViewAcceptedSize(adViewWidthInDp, adViewHeightInDp)
            .setAdLoadType(TTAdLoadType.LOAD)// 推荐使用，用于标注此次的广告请求用途为预加载（当做缓存）还是实时加载，方便后续为开发者优化相关策略
            .build()

        Utils.log(TAG, "请求开屏广告")

        if (!mIsInitialed) {
            Utils.log(TAG, "初始化未完成，不加载开屏动画")
            callback.invoke(false)
            return
        }

        mTTVfNative.loadSphVs(adSlot, object : TTVfNative.CSJSplashAdListener {
            override fun onSplashLoadSuccess(p0: CSJSplashAd?) {
                Utils.log(TAG, "开屏广告加载成功 $p0")
            }

            override fun onSplashLoadFail(p0: CSJAdError?) {
                Utils.log(TAG, "开屏广告加载失败")
                callback.invoke(false)
            }

            override fun onSplashRenderSuccess(p0: CSJSplashAd?) {
                Utils.log(TAG, "开屏广告渲染成功 $p0")
                if (p0 == null) {
                    callback.invoke(false)
                    return
                }
                if (!activity.isFinishing) {
                    startAdContainer.removeAllViews()
                    p0.hideSkipButton()
                    p0.setSplashAdListener(object : CSJSplashAd.SplashAdListener {
                        override fun onSplashAdShow(p0: CSJSplashAd?) {
                            Utils.log(TAG, "显示开屏广告")
                            onAdShowAction.invoke()
                        }

                        override fun onSplashAdClick(p0: CSJSplashAd?) {
                            Utils.log(TAG, "点击开屏广告")
                            onAdClickAction.invoke()
                        }

                        override fun onSplashAdClose(ad: CSJSplashAd?, closeType: Int) {
                            if (closeType == CSJSplashCloseType.CLICK_SKIP) {
                                Utils.log(TAG, "开屏广告点击跳过")
                            } else if (closeType == CSJSplashCloseType.COUNT_DOWN_OVER) {
                                Utils.log(TAG, "开屏广告点击倒计时结束")
                            } else if (closeType == CSJSplashCloseType.CLICK_JUMP) {
                                Utils.log(TAG, "点击跳转")
                            }
                            callback.invoke(true)
                        }
                    })
                    // 把SplashView 添加到ViewGroup中,注意开屏广告view：width =屏幕宽；height >=75%屏幕高
                    p0.showSplashView(startAdContainer)
                } else {
                    // 开发者处理跳转到APP主页面逻辑
                    callback.invoke(false)
                }
            }

            override fun onSplashRenderFail(p0: CSJSplashAd?, p1: CSJAdError?) {
                Utils.log(TAG, "开屏广告渲染失败 $p0")
                callback.invoke(false)
            }
        }, timeout)
    }

    fun requestFlowAd(
        fragment: Fragment,
        containerView: ViewGroup,
        slotId: String,
        expressViewAcceptedSize: Float,
        onAdShowAction: () -> Unit,
        onAdClickAction: () -> Unit,
        callback: (isSuccess: Boolean) -> Unit
    ) {
        val isBoundedActivityValid =
            fragment.isAdded && fragment.activity != null && !fragment.requireActivity().isFinishing

        if (!isBoundedActivityValid) {
            Utils.log(TAG, "requestFlowAd but activity is invalid.")
        }

        val boundedActivity = fragment.activity

        val mTTVfNative = TTVfSdk.getVfManager().createVfNative(boundedActivity)

        val adSlot = VfSlot.Builder()
            .setCodeId(slotId) // 广告位id
            .setSupportDeepLink(true)
            .setAdCount(1) // 请求广告数量为1到3条
            .setExpressViewAcceptedSize(expressViewAcceptedSize, 0F) // 期望模板广告view的size,宽度最低为375，单位dp
            .setAdLoadType(TTAdLoadType.LOAD) // 推荐使用，用于标注此次的广告请求用途为预加载（当做缓存）还是实时加载，方便后续为开发者优化相关策略
            .build()

        var activeAd: TTNtExpressObject? = null

        mTTVfNative.loadNtExpressVn(adSlot, object : TTVfNative.NtExpressVfListener {
            // 广告请求失败
            override fun onError(code: Int, message: String) {
                Utils.log(TAG, "requestFlowAd $code 广告请求失败 $message")
                callback.invoke(false)
            }

            // 广告请求成功
            override fun onNtExpressVnLoad(ads: List<TTNtExpressObject>) {
                activeAd = ads.firstOrNull()

                activeAd?.setExpressInteractionListener(object : TTNtExpressObject.ExpressNtInteractionListener {
                    // 广告点击回调
                    override fun onClicked(view: View, type: Int) {
                        Utils.log(TAG, "requestFlowAd 广告点击 $type")
                        onAdClickAction.invoke()
                    }

                    // 广告展示回调
                    override fun onShow(view: View, type: Int) {
                        Utils.log(TAG, "requestFlowAd 广告展示")
                        onAdShowAction.invoke()
                        callback.invoke(true)
                    }

                    // 广告渲染失败回调
                    override fun onRenderFail(view: View, msg: String, code: Int) {
                        Utils.log(TAG, "requestFlowAd 广告渲染失败 $code $msg")

                        callback.invoke(false)
                    }

                    // 广告渲染成功回调
                    override fun onRenderSuccess(view: View, width: Float, height: Float) {
                        Utils.log(TAG, "requestFlowAd 广告渲染成功 $width $height")
                        containerView.removeAllViews()
                        containerView.addView(view)
                    }
                })
                activeAd?.setDislikeCallback(boundedActivity, object: TTVfDislike.DislikeInteractionCallback {
                    override fun onShow() {
                        Utils.log(TAG, "requestFlowAd 用户点击关闭广告")
                    }

                    override fun onSelected(p0: Int, p1: String?, p2: Boolean) {
                        Utils.log(TAG, "requestFlowAd 用户不喜欢广告，理由是 $p1")
                        containerView.removeAllViews()
                    }

                    override fun onCancel() {
                        Utils.log(TAG, "requestFlowAd 取消不喜欢弹窗")
                    }
                })
                activeAd?.render()
            }
        })

        fragment.doOnFragmentDestroy {
            activeAd?.destroy()
        }
    }

    fun requestBannerAd(
        fragment: Fragment,
        containerView: ViewGroup,
        slotId: String,
        expressViewWidthInDp: Float,
        expressViewHeightInDp: Float,
        onAdShowAction: () -> Unit,
        onAdClickAction: () -> Unit,
        callback: (isSuccess: Boolean) -> Unit
    ) {

        // 创建TTVfNative对象，createAdNative(Context context) context需要传入Activity对象
        val mTTVfNative = TTVfSdk.getVfManager().createVfNative(fragment.activity)

        val isBoundedActivityValid =
            fragment.isAdded && fragment.activity != null && !fragment.requireActivity().isFinishing

        if (!isBoundedActivityValid) {
            Utils.log(TAG, "requestBannerAd but activity is invalid.")
            return
        }

        val adSlot = VfSlot.Builder()
            .setCodeId(slotId) // 广告位id
            .setSupportDeepLink(true)
            .setAdCount(1) // 请求广告数量为1
            .setExpressViewAcceptedSize(expressViewWidthInDp, expressViewHeightInDp) // 期望模板广告view的size,单位dp
            .setAdLoadType(TTAdLoadType.LOAD) // 推荐使用，用于标注此次的广告请求用途为预加载（当做缓存）还是实时加载，方便后续为开发者优化相关策略
            .build()

        mTTVfNative.loadBnExpressVb(adSlot, object : NtExpressVfListener {
            // 请求失败回调
            override fun onError(code: Int, message: String) {
                Utils.log(TAG, "banner $code 请求失败 $message")
                callback.invoke(false)
            }

            // 请求成功回调
            override fun onNtExpressVnLoad(ads: List<TTNtExpressObject>) {
                val ad = ads.firstOrNull()
                ad?.setExpressInteractionListener(object : TTNtExpressObject.ExpressNtInteractionListener {
                    // 广告点击回调
                    override fun onClicked(view: View, type: Int) {
                        Utils.log(TAG, "banner 广告点击 $type")
                        onAdClickAction.invoke()
                    }

                    // 广告展示回调
                    override fun onShow(view: View, type: Int) {
                        Utils.log(TAG, "banner 广告展示 $type")
                        onAdShowAction.invoke()
                    }

                    // 广告渲染失败回调
                    override fun onRenderFail(view: View, msg: String, code: Int) {
                        Utils.log(TAG, "banner 广告渲染失败 $code $msg")
                        callback.invoke(false)
                    }

                    // 广告渲染成功回调
                    override fun onRenderSuccess(view: View, width: Float, height: Float) {
                        Utils.log(TAG, "banner 广告渲染成功 $width $height")

                        containerView.removeAllViews()
                        containerView.addView(view)

                        callback.invoke(true)
                    }
                })
                ad?.setDislikeCallback(fragment.activity, object: TTVfDislike.DislikeInteractionCallback {
                    override fun onShow() {
                        Utils.log(TAG, "banner 用户点击关闭广告")
                    }

                    override fun onSelected(p0: Int, p1: String?, p2: Boolean) {
                        Utils.log(TAG, "banner 用户不喜欢广告，理由是 $p1")
                        containerView.removeAllViews()
                        callback.invoke(false)
                    }

                    override fun onCancel() {
                        Utils.log(TAG, "banner 取消不喜欢弹窗")
                    }
                })
                ad?.render()

                fragment.doOnFragmentDestroy {
                    ad?.destroy()
                }
            }
        })
    }

    fun requestFullScreenAd(
        fragment: Fragment,
        slotId: String,
        onAdShowAction: () -> Unit,
        onAdClickAction: () -> Unit,
        callback: (isSuccess: Boolean) -> Unit
    ) {
        // 创建TTVfNative对象，createAdNative(Context context) context需要传入Activity对象
        val mTTVfNative = TTVfSdk.getVfManager().createVfNative(fragment.activity)

        val isBoundedActivityValid =
            fragment.isAdded && fragment.activity != null && !fragment.requireActivity().isFinishing

        if (!isBoundedActivityValid) {
            Utils.log(TAG, "requestFullScreenAd but activity is invalid.")
            return
        }

        val adSlot = VfSlot.Builder()
            .setCodeId(slotId) // 广告位id
            .setSupportDeepLink(true)
            .setAdCount(1) // 请求广告数量为1
            .setAdLoadType(TTAdLoadType.LOAD) // 推荐使用，用于标注此次的广告请求用途为预加载（当做缓存）还是实时加载，方便后续为开发者优化相关策略
            .build()

        val fullVideoVsInteractionListener = object : FullVideoVsInteractionListener {
            override fun onShow() {
                Utils.log(TAG, "全屏/插屏 广告展示")
                onAdShowAction.invoke()
                callback.invoke(true)
            }

            override fun onVideoBarClick() {
                Utils.log(TAG, "全屏/插屏 广告下载bar点击")
                onAdClickAction.invoke()
            }

            override fun onClose() {
                Utils.log(TAG, "全屏/插屏 广告关闭")
            }

            override fun onVideoComplete() {
                Utils.log(TAG, "全屏/插屏 视频播放完成")
            }

            override fun onSkippedVideo() {
                Utils.log(TAG, "全屏/插屏 跳过视频播放")
            }
        }

        mTTVfNative.loadFullVideoVs(adSlot, object : FullScreenVideoAdListener {
            override fun onError(code: Int, message: String?) {
                Utils.log(TAG, "全屏/插屏 $code 请求广告失败 $message")
                callback.invoke(false)
            }

            override fun onFullVideoVsLoad(ad: TTFullVideoObject) {
                Utils.log(TAG, "全屏/插屏 广告物料加载完成 $ad")
            }

            override fun onFullVideoCached() {
                // 已废弃
            }

            override fun onFullVideoCached(ad: TTFullVideoObject) {
                Utils.log(TAG, "全屏/插屏 广告视频/图片加载完成 $ad")
                ad.setFullScreenVideoAdInteractionListener(fullVideoVsInteractionListener)
                ad.showFullVideoVs(fragment.activity)
            }
        })
    }
}