package com.gh.common.prioritychain

import android.annotation.SuppressLint
import android.app.Activity
import android.app.Application.ActivityLifecycleCallbacks
import android.os.Bundle
import android.preference.PreferenceManager
import android.text.TextUtils
import androidx.annotation.WorkerThread
import androidx.fragment.app.FragmentActivity
import com.gh.common.iinterface.ISuperiorChain
import com.gh.common.util.CheckLoginUtils
import com.gh.common.util.PackageUtils
import com.gh.download.DownloadManager
import com.gh.gamecenter.SplashAdActivity
import com.gh.gamecenter.SplashScreenActivity
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.SPUtils.getBoolean
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.entity.DialogEntity
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.ReserveOnlineEntity
import com.gh.gamecenter.feature.entity.WelcomeDialogEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.hud.PendingInstallHUDHandler
import com.gh.gamecenter.hud.ResumeDownloadHudHandler
import com.gh.gamecenter.login.entity.UserInfoEntity
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.schedulers.Schedulers

/**
 * 全局的 APP 优先级弹窗链管理器
 *
 * 弹窗的优先级为
 * 启动跳转(-101) > 更新弹窗(-100) > 隐私政策弹窗(-99) > 消息通知权限弹窗(0) > 预约弹窗(1) > 启动弹窗(2)
 */
object GlobalPriorityChainHelper : ISuperiorChain {

    private val api = RetrofitManager.getInstance().api
    private val newApi = RetrofitManager.getInstance().newApi
    private var inferiorChain: PriorityChain? = null
    private val mainChain: PriorityChain by lazy { PriorityChain { inferiorChain?.start() } }

    /**
     * 当前 activity 是否使用于应用全局弹窗的弹出
     * 排除启动页和其它非 FragmentActivity
     */
    fun isThisActivityValid(activity: Activity?): Boolean {
        return activity is FragmentActivity
                && !activity.isFinishing
                && activity !is SplashScreenActivity
                && activity !is SplashAdActivity
    }

    /**
     * 预启动所有的优先级弹窗管理链
     */
    fun preStart(withSpecialDelay: Boolean) {
        val launchRedirectHandler = LaunchRedirectHandler(-102)
        val membershipExpiredHandler = MembershipExpiredHandler(-101)
        val updateDialogHandler = UpdateDialogHandler(-100)
        val privacyPolicyDialogHandler = PrivacyPolicyDialogHandler(-99)
        val notificationPermissionDialogHandler = NotificationPermissionDialogHandler(0)
        val reserveDialogHandler = ReserveDialogHandler(1)
        val welcomeDialogHandler = WelcomeDialogHandler(2)
        val pendingInstallHandler = PendingInstallHUDHandler(3)
        val resumeDownloadHandler = ResumeDownloadHudHandler(4)

        mainChain.addHandler(launchRedirectHandler)
        mainChain.addHandler(membershipExpiredHandler)
        mainChain.addHandler(updateDialogHandler)
        mainChain.addHandler(privacyPolicyDialogHandler)
        mainChain.addHandler(welcomeDialogHandler)
        mainChain.addHandler(reserveDialogHandler)
        mainChain.addHandler(notificationPermissionDialogHandler)
        mainChain.addHandler(pendingInstallHandler)
        mainChain.addHandler(resumeDownloadHandler)

        launchRedirectHandler.doPreProcess()
        membershipExpiredHandler.doPreProcess()
        updateDialogHandler.doPreProcess()

        // 首次启动延迟 300ms，保证请求首次启动时已经获取到了 GID 、 OAID 等标记
        val requestDelay = if (withSpecialDelay) 300L else 0L
        AppExecutor.uiExecutor.executeWithDelay({
            requestOpeningDialogData(welcomeDialogHandler, privacyPolicyDialogHandler)
            requestReserveDialogData(reserveDialogHandler)
        }, requestDelay)
    }

    /**
     * 启动优先级弹窗管理链的执行
     */
    fun start() {
        if (mainChain.isHandlerQueueEmpty()) return

        mainChain.start()

        observeLifecycle()
    }

    private fun observeLifecycle() {
        HaloApp.getInstance().registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
            override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
                // do nothing
            }

            override fun onActivityStarted(activity: Activity) {
                // do nothing
            }

            override fun onActivityResumed(activity: Activity) {
                // 优先级弹窗管理链为空时取消注册，避免无用调用
                if (mainChain.isHandlerQueueEmpty()) {
                    HaloApp.getInstance().unregisterActivityLifecycleCallbacks(this)
                } else {
                    resume()
                }
            }

            override fun onActivityPaused(activity: Activity) {
                // do nothing
            }

            override fun onActivityStopped(activity: Activity) {
                // do nothing
            }

            override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
                // do nothing
            }

            override fun onActivityDestroyed(activity: Activity) {
                // do nothing
            }
        })
    }

    /**
     * 恢复链的处理
     */
    fun resume() {
        mainChain.resume()
    }

    /**
     * 添加新的 handler 到优先级弹窗管理链 (插队！)
     */
    fun queueNewHandler(handler: PriorityChainHandler) {
        if (mainChain.isHandlerQueueEmpty()) {
            observeLifecycle()
        }

        mainChain.addHandler(handler)
    }

    /**
     * 请求首页启动弹窗相关的数据并执行相关 handler 的 preProcess
     */
    @SuppressLint("CheckResult")
    private fun requestOpeningDialogData(
        welcomeDialogHandler: WelcomeDialogHandler,
        privacyPolicyDialogHandler: PrivacyPolicyDialogHandler
    ) {
        val sp = PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance())

        val lastId = SPUtils.getString(sp, Constants.SP_LAST_OPENING_ID, "")
        val lastTime = SPUtils.getLong(sp, Constants.SP_LAST_OPENING_TIME, 0)
        val openType = if (HaloApp.getInstance().isNewForThisVersion) "first" else "not_first_time"

        api.getOpeningDialog(HaloApp.getInstance().channel, lastId, lastTime, openType)
            .subscribeOn(Schedulers.io())
            .subscribe(object : BiResponse<DialogEntity>() {
                override fun onSuccess(data: DialogEntity) {
                    var welcomeDialogEntity: WelcomeDialogEntity? = null
                    var privacyPolicyDialogEntity: DialogEntity.PrivacyPolicyEntity? = null

                    // 全新安装忽略隐私弹窗
                    if (data.privacyPolicyDialog != null) {
                        val id = data.privacyPolicyDialog.id
                        val lastAcceptedId = SPUtils.getString(Constants.SP_LAST_ACCEPTED_PRIVACY_DIALOG_ID, "")
                        if (HaloApp.getInstance().isBrandNewInstall) {
                            SPUtils.setString(Constants.SP_LAST_ACCEPTED_PRIVACY_DIALOG_ID, id)
                        } else {
                            if (id != lastAcceptedId) {
                                privacyPolicyDialogEntity = data.privacyPolicyDialog
                            }
                        }
                    }

//                    debugOnly {
//                        privacyPolicyDialogEntity = DialogEntity.PrivacyPolicyEntity(
//                            "5f6f5f3d9d9b4e0001c3b3a5",
//                            "privacy_policy",
//                            "ONCE",
//                            "INFORM",
//                            "隐私政策",
//                            1601116800000)
//                    }

                    privacyPolicyDialogHandler.doPreProcess(privacyPolicyDialogEntity)

                    // 类型为游戏时判断是否本地已安装该游戏，已安装不弹弹窗
                    if (data.welcomeDialog != null) {
                        welcomeDialogEntity = data.welcomeDialog

                        if (data.welcomeDialog.type == "game") {
                            if (data.welcomeDialog.packages != null) {
                                for (packageName in data.welcomeDialog.packages!!) {
                                    if (PackageUtils.isInstalled(HaloApp.getInstance(), packageName)) {
                                        welcomeDialogEntity = null
                                        break
                                    }
                                }
                            }
                        }
                    }

                    welcomeDialogHandler.doPreProcess(welcomeDialogEntity)
                }

                override fun onFailure(exception: Exception) {
                    privacyPolicyDialogHandler.doPreProcess(null)
                    welcomeDialogHandler.doPreProcess(null)
                }
            })
    }

    /**
     * 请求预约弹窗相关的数据
     */

    private fun requestReserveDialogData(reserveDialogHandler: ReserveDialogHandler) {
//        debugOnly {
//            reserveDialogHandler.doPreProcess(arrayListOf(SimpleGameEntity(
//                "5f6f5f3d9d9b4e0001c3b3a5",
//                "5f6f5f3d9d9b4e0001c3b3a5",
//                "https://and-static.ghzs.com/image/game/icon/2022/11/18/63772b0d398daaa7c5067298.png",
//                "5f6f5f3d9d9b4e0001c3b3a5",
//            )))
//            return
//        }

        if (CheckLoginUtils.isLogin()) {
            val isTeenagerMode = getBoolean(Constants.SP_TEENAGER_MODE)
            loadReserveDialogOnlineData(isTeenagerMode, reserveDialogHandler)
        } else {
            reserveDialogHandler.doPreProcess(null)
        }
    }

    /**
     * 由于用户预约的游戏个数没有限制，为避免一次加载游戏过多，这里采用先加载第一页，显示出dialog,后续数据在第二页返回
     * 注意:当page = 2 时，后台会将后续所有数据一次性返回，所以递归到第三层时，就会结束
     * @param isTeenagerMode 青少年模式关闭时才需要启动自动下载，所以当 isTeenagerMode == true 时，不需要加载后续数据，也不需要启动自动下载
     */
    @SuppressLint("CheckResult")
    private fun loadReserveDialogOnlineData(isTeenagerMode: Boolean, handler: ReserveDialogHandler? = null) {
        newApi.getReserveDialog()
            .compose(singleToMain())
            .subscribe(object : BiResponse<ReserveOnlineEntity>() {
                override fun onSuccess(data: ReserveOnlineEntity) {
                    handler?.doPreProcess(data)
                    // 继续获取后续需要自动下载的游戏
                    runOnIoThread {
                        loadGamesWithAutoDownload(1, 20, isTeenagerMode)
                    }
                }

                override fun onFailure(exception: Exception) {
                    handler?.doPreProcess(null)
                }
            })
    }

    /**
     * 由于这个方法本身就是在子线程调用的，这里不需要另外在做线程切换
     */
    @SuppressLint("CheckResult")
    @WorkerThread
    private fun loadGamesWithAutoDownload(page: Int, pageSize: Int, isTeenagerMode: Boolean) {
        if (page >= 5) {
            // 为防止死循环，这里设置最多请求到第5页(正常情况下，第一页就是全部数据)
            return
        }
        val filter = "wifi_auto_download:true"
        newApi.loadGamesWithAutoDownload(page, pageSize, filter)
            .doOnSuccess(::trackAppointmentGameOnlineDialogShow)
            .subscribe(object : BiResponse<List<GameEntity>>() {

                override fun onSuccess(data: List<GameEntity>) {
                    // 请注意，这是在子线程中
                    if (data.isNotEmpty()) {
                        loadGamesWithAutoDownload(page + 1, pageSize, isTeenagerMode)
                        startAutoDownloadIfNeed(data, isTeenagerMode)
                    }

                }

            })
    }

    @SuppressLint("CheckResult")
    private fun startAutoDownloadIfNeed(games: List<GameEntity>, isTeenagerMode: Boolean) {
        val autoDownloadGameIds = mutableSetOf<String>()
        games.forEach {
            autoDownloadGameIds.add(it.id)
            if (it.wifiAutoDownload && !it.isLandPageAddressDialog() && !isTeenagerMode) {
                // 开启了 wifi 自动下载，并且不能为第三方落地页跳转
                val apk = when (it.getApk().size) {
                    0 -> null
                    1 -> it.getApk().first()
                    else -> {
                        // 自动下载，多版本默认：九游版
                        it.getApk().find { apk -> "9u" == apk.getPlatform() && apk.isActive }
                    }
                }
                if (apk != null) {
                    val updateEntities = PackageUtils.getUpdateData(it, false)
                    val isCanUpdate = if (updateEntities.size == 1) {
                        true
                    } else {
                        // 多版本只需要判断九游版是否需要更新
                        updateEntities.any { update -> "9u" == update.platform }
                    }
                    val isCanPluggable = PackageUtils.isCanPluggable(apk)
                    if ((!PackageUtils.isInstalled(HaloApp.getInstance(), apk.packageName)
                                || isCanUpdate
                                || isCanPluggable)
                        && DownloadManager.getInstance().getDownloadEntityByUrl(apk.url) == null
                    ) {
                        // 未下载/可更新/可插件化 且 之前没有下载记录
                        val msg = FileUtils.isCanDownload(HaloApp.getInstance(), apk.size ?: "")
                        if (msg.isNullOrBlank()) {
                            val isWifiOpen = NetworkUtils.isWifiConnected(HaloApp.getInstance())
                            val isSubscribe = !isWifiOpen
                            DownloadManager.createDownload(
                                HaloApp.getInstance(),
                                apk,
                                it,
                                false,
                                false,
                                "",
                                "",
                                isSubscribe,
                                ExposureEvent.createEvent(it, listOf(ExposureSource("预约上线弹窗-自动下载", "")))
                            )
                        } else {
                            // 存储空间不足，直接跳出循环，放弃后续的所有游戏
                            ToastUtils.showToast(msg)
                            return@forEach
                        }
                    }
                }
            }
        }
        if (autoDownloadGameIds.isNotEmpty()) {
            val body = hashMapOf(
                "game_ids" to autoDownloadGameIds,
                "type" to "wifi_auto_download"
            )
            newApi.logAutoDownload(body)
                .subscribe({}, {})
        }
    }

    private fun trackAppointmentGameOnlineDialogShow(games: List<GameEntity>) {
        if (games.isNotEmpty()) {
            val gameIds = arrayListOf<String>()
            val gameNames = arrayListOf<String>()
            val gameTypes = arrayListOf<String>()
            games.forEach { game ->
                gameIds.add(game.id)
                gameNames.add(game.name ?: "")
                gameTypes.add(game.categoryChinese)
            }
            val gameId = gameIds.joinToString()
            val gameName = gameNames.joinToString()
            val gameType = gameTypes.joinToString()
            SensorsBridge.trackAppointmentGameOnlineDialogShow(gameId, gameName, gameType)
        }
    }

    override fun registerInferiorChain(chain: PriorityChain) {
        inferiorChain = chain
        if (mainChain.isHandlerQueueEmpty()) {
            inferiorChain?.resume()
        }
    }

    override fun unregisterInferiorChain(chain: PriorityChain) {
        if (inferiorChain == chain) {
            inferiorChain = null
        }
    }

}