package com.gh.vspace

import android.annotation.SuppressLint
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.gh.common.exposure.ExposureUtils
import com.gh.common.exposure.ExposureUtils.DownloadType.DOWNLOAD
import com.gh.common.exposure.ExposureUtils.DownloadType.UPDATE
import com.gh.common.util.*
import com.gh.common.util.NewFlatLogUtils
import com.gh.download.DownloadManager
import com.gh.download.PackageObserver
import com.gh.gamecenter.common.base.activity.BaseActivity
import com.gh.gamecenter.common.base.fragment.BaseDraggableDialogFragment
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.databinding.DialogVspaceBinding
import com.gh.gamecenter.entity.AppEntity
import com.gh.gamecenter.eventbus.EBPackage
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.view.DownloadButton
import com.halo.assistant.HaloApp
import com.lightgame.download.DataWatcher
import com.lightgame.download.DownloadConfig
import com.lightgame.download.DownloadEntity
import com.lightgame.download.DownloadStatus.*
import com.lightgame.utils.AppManager
import java.io.File

/**
 * 1. 单独的 64 位组件的下载和更新使用本 VSpaceDialogFragment
 * 2. 已经安装了 64 位组件，后续操作所调起的 32 位组件的首次下载使用亦 VSpace32DialogFragment
 * 3. 64 位组件已安装且 64 位组件无需更新时，32 位组件需要更新时，使用本 VSpaceDialogFragment
 * 4. 64 位组件已安装且 64，32 位都需要更新时，64 位更新使用本 VSpaceDialogFragment
 * （同时下载64位组件和32位组件，但是32位在64位安装完成之前不触发安装）， 32 位安装使用跳转 VSpaceUpdate32DialogFragment 进行
 */
class VSpaceDialogFragment : BaseDraggableDialogFragment() {

    private var mAppEntity64: AppEntity? = null
    private var mAppEntity32: AppEntity? = null
    private var mGameId: String = ""
    private var mGameName: String = ""
    private var mBit: String = "" // 畅玩游戏位数
    private var mIsUpdate = false
    private val mDownloadUrl64 by lazy { mAppEntity64?.url ?: "" }
    private val mDownloadUrl32 by lazy { mAppEntity32?.url ?: "" }
    private val mBinding by lazy { DialogVspaceBinding.inflate(layoutInflater) }
    private var mIsLogInstallShow = false
    private var mIsLogAutoInstallClick = false
    private var mIsClickDownloadThisTime = false // 是否本次弹出Dialog点击的下载按钮
    private val mDataWatcher = object : DataWatcher() {
        override fun onDataChanged(downloadEntity: DownloadEntity) {
            if (((mAppEntity64 != null && downloadEntity.url == mDownloadUrl64) || (mAppEntity64 == null && downloadEntity.url == mDownloadUrl32)) && isAdded) {
                updateDownloadButton(downloadEntity)
            }
        }

        override fun onDataInit(downloadEntity: DownloadEntity) {
            onDataChanged(downloadEntity)
        }
    }

    override fun getRootView(): View = mBinding.root
    override fun getDragCloseView(): View = mBinding.dragClose

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        mAppEntity64 = arguments?.get(KEY_APP_ENTITY_64) as? AppEntity
        mAppEntity32 = arguments?.get(KEY_APP_ENTITY_32) as? AppEntity
        mGameId = arguments?.getString(EntranceConsts.KEY_GAME_ID) ?: ""
        mGameName = arguments?.getString(EntranceConsts.KEY_GAME_NAME) ?: ""
        mBit = arguments?.getString(Constants.KEY_BIT) ?: ""
        mIsUpdate = arguments?.getBoolean(KEY_IS_UPDATE) == true
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        return mBinding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val mViewModel = viewModelProvider<VSpaceDialogViewModel>()
        mViewModel.packageLiveData.observe(this) {
            show32BitRelatedDialogIfNeeded()
            dismissDialogIfInstalled()
        }

        mBinding.downloadBtn.text = "下载畅玩助手服务组件"
        mBinding.downloadBtn.buttonStyle = DownloadButton.ButtonStyle.NORMAL
        mBinding.descTv.text = "《$mGameName》需先安装畅玩服务组件，安装后即可进入游戏体验新鲜功能~"
        mBinding.privacyPolicyTv.setOnClickListener {
            NewFlatLogUtils.logHaloFunEvent("halo_fun_download_dialog_privacy_click")
            DirectUtils.directToWebView(requireContext(), Constants.SMOOTH_GAME_PRIVACY_POLICY_ADDRESS)
        }

        val downloadSnapshot = DownloadManager.getInstance()
            .getDownloadEntitySnapshotByPackageName(if (mAppEntity64 != null) VHelper.DEFAULT_VSPACE_PACKAGENAME else VHelper.VSPACE_32BIT_PACKAGENAME)

        mBinding.downloadBtn.setOnClickListener {
            // 确定下载类型
            val downloadType = if (mIsUpdate) UPDATE else DOWNLOAD
            var downloadEntity64: DownloadEntity? = null
            var downloadEntity32: DownloadEntity? = null

            if (mAppEntity64 != null) {
                downloadEntity64 = getDownloadEntity(true)

                val gameEntity64 = GameEntity(downloadEntity64.gameId, downloadEntity64.name)
                gameEntity64.gameVersion = mAppEntity64?.version ?: ""

                downloadEntity64.exposureTrace = ExposureUtils.logADownloadExposureEvent(
                    gameEntity64,
                    downloadEntity64.platform,
                    null,
                    downloadType
                ).toJson()

                // 收集下载数据
                DataCollectionUtils.uploadDownload(HaloApp.getInstance(), downloadEntity64, "开始")
            }

            val is32VSpaceInstalled = PackageUtils.isInstalledFromAllPackage(context, VHelper.VSPACE_32BIT_PACKAGENAME)
            if (mBit == "32" && mAppEntity32 != null && !(is32VSpaceInstalled && !mIsUpdate)) {
                downloadEntity32 = getDownloadEntity(false)

                // 非32位单独下载时下载完成不弹出安装界面
                if (mAppEntity64 != null) {
                    downloadEntity32.addMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE, Constants.VSPACE_32_DOWNLOAD_ONLY)
                }

                val gameEntity32 = GameEntity(downloadEntity32.gameId, downloadEntity32.name)
                gameEntity32.gameVersion = mAppEntity32?.version ?: ""

                downloadEntity32.exposureTrace = ExposureUtils.logADownloadExposureEvent(
                    gameEntity32,
                    downloadEntity32.platform,
                    null,
                    downloadType
                ).toJson()

                DataCollectionUtils.uploadDownload(HaloApp.getInstance(), downloadEntity32, "开始")
            }

            mIsClickDownloadThisTime = true
            AppExecutor.uiExecutor.executeWithDelay({
                if (downloadEntity64 != null) {
                    DownloadManager.getInstance().cancel(mDownloadUrl64)
                    DownloadManager.getInstance().add(downloadEntity64)
                }
                if (downloadEntity32 != null) {
                    DownloadManager.getInstance().cancel(mDownloadUrl32)
                    DownloadManager.getInstance().add(downloadEntity32)
                }
            }, 200)

            val architecture =
                if (downloadEntity64 != null && downloadEntity32 != null) "32位&64位" else if (downloadEntity64 != null) "64位" else "32位"
            NewFlatLogUtils.logHaloFunDownloadDialogDownloadClick(architecture)
            SensorsBridge.trackEvent(
                "HaloFunDownloadDialogDownloadClick",
                "game_id",
                mGameId,
                "game_name",
                mGameName,
                "space_schema_type",
                architecture,
                "game_schema_type",
                if (mBit == "32") "32位" else "64位"
            )
        }

        if (arguments?.getBoolean(KEY_AUTO_DOWNLOAD) == true && downloadSnapshot == null) {
            mBinding.downloadBtn.performClick()
        }
    }

    private fun getDownloadEntity(is64Bit: Boolean) = DownloadEntity().apply {
        url = if (is64Bit) mDownloadUrl64 else mDownloadUrl32
        name =
            "畅玩助手V" + (if (is64Bit) mAppEntity64?.version else mAppEntity32?.version) + "(${if (is64Bit) 64 else 32}位)"
        platform = "官方版"
        gameId = "62bd412bbbf04747cd3de539"
        path = PackageInstaller.getDownloadPathWithId(PackageInstaller.createDownloadId(name), "apk")
        packageName = if (is64Bit) VHelper.DEFAULT_VSPACE_PACKAGENAME else VHelper.VSPACE_32BIT_PACKAGENAME
        addMetaExtra(DownloadConfig.KEY_PROGRESS_CALLBACK_INTERVAL, "200")
    }

    override fun onStart() {
        super.onStart()
        DownloadManager.getInstance().addObserver(mDataWatcher)

        show32BitRelatedDialogIfNeeded()

        // 检查安装状态，避免出现已安装但是没有 dismiss 弹窗的问题
        dismissDialogIfInstalled()
    }

    // 弹下载/更新 32 位组件，前提是 64 位组件已经安装并安装了指定的版本
    private fun show32BitRelatedDialogIfNeeded() {
        if (PackageUtils.isInstalledFromAllPackage(requireContext(), VHelper.DEFAULT_VSPACE_PACKAGENAME)
            && mAppEntity64?.version == PackageUtils.getVersionNameByPackageName(VHelper.DEFAULT_VSPACE_PACKAGENAME)) {
            // 该游戏需要 32 位组件，且后台配置的 32 位组件不为空
            if (mBit == "32" && mAppEntity32 != null && !mAppEntity32?.url.isNullOrEmpty()) {
                if (mIsUpdate) {
                    showVSpace32UpdateDialog()
                } else {
                    showVSpace32DownloadDialogIfNeeded()
                }
            }
        }
    }

    /**
     * dismiss 当前 VSpaceDialogFragment (如果满足入参条件的话)
     */
    private fun dismissDialogIfInstalled() {
        // 需要下载的 64 位组件是否与已安装的 64 位组件版本一致
        val is64BitVersionMatched =
            mAppEntity64 == null
                    || mAppEntity64?.version == PackageUtils.getVersionNameByPackageName(VHelper.DEFAULT_VSPACE_PACKAGENAME)

        // 需要下载的 32 位组件是否与已安装的 32 位组件版本一致
        val is32BitVersionMatched =
            (mAppEntity32 == null || mBit != "32")
                    || mAppEntity32?.version == PackageUtils.getVersionNameByPackageName(VHelper.VSPACE_32BIT_PACKAGENAME)

        if (is64BitVersionMatched && is32BitVersionMatched) {
            dismissAllowingStateLoss()
        }
    }

    private fun showVSpace32DownloadDialogIfNeeded() {
        val is32VSpaceInstalled =
            PackageUtils.isInstalledFromAllPackage(requireContext(), VHelper.VSPACE_32BIT_PACKAGENAME)
        if (!is32VSpaceInstalled) {
            VSpace32DialogFragment.showDownloadDialog(
                requireContext(),
                mAppEntity32!!,
                gameId = mGameId,
                gameName = mGameName
            )
        }
    }

    private fun showVSpace32UpdateDialog() {
        VSpaceUpdate32DialogFragment.showDownloadDialog(
            requireContext(),
            mAppEntity32!!,
            gameId = mGameId,
            gameName = mGameName
        )
    }

    override fun onStop() {
        super.onStop()
        DownloadManager.getInstance().removeObserver(mDataWatcher)
    }

    private fun updateDownloadButton(downloadEntity: DownloadEntity) {
        val downloadBtn = mBinding.downloadBtn
        downloadBtn.progress = (downloadEntity.progress * 10).toInt()
        when (downloadEntity.status) {
            downloading -> {
                downloadBtn.setText(com.gh.gamecenter.feature.R.string.pause)
                downloadBtn.progress = (downloadEntity.percent * 10).toInt()
                downloadBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_NORMAL
                downloadBtn.setOnClickListener {
                    DownloadManager.getInstance().pause(downloadEntity.url)
                }
            }

            pause -> {
                downloadBtn.setText(com.gh.gamecenter.feature.R.string.resume)
                downloadBtn.setOnClickListener {
                    DownloadManager.getInstance().resume(downloadEntity, false)
                }
            }

            overflow,
            timeout,
            neterror,
            diskioerror,
            diskisfull,
            waiting,
            subscribe -> {
                downloadBtn.setText(com.gh.gamecenter.feature.R.string.waiting)
                downloadBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_NORMAL
                downloadBtn.setOnClickListener {
                    DownloadManager.getInstance().resume(downloadEntity, false)
                }
            }

            done -> {
                downloadBtn.setText(com.gh.gamecenter.feature.R.string.install)
                downloadBtn.buttonStyle = DownloadButton.ButtonStyle.INSTALL_NORMAL

                val vSpaceType = if (downloadEntity.url == mDownloadUrl64) "64位" else "32位"
                if (!mIsLogInstallShow) {
                    NewFlatLogUtils.logHaloFunInstallTipDialogShow(vSpaceType)
                    SensorsBridge.trackEvent("HaloFunInstallDialogShow", "space_schema_type", vSpaceType)
                    mIsLogInstallShow = true
                }

                if (SPUtils.getBoolean(
                        Constants.SP_AUTO_INSTALL,
                        true
                    ) && !mIsLogAutoInstallClick && mIsClickDownloadThisTime
                ) {
                    downloadBtn.postDelayed({
                        SensorsBridge.trackEvent("HaloFunInstallButtonClick", "space_schema_type", vSpaceType)
                    }, SENSORS_LOG_DELAY)
                    mIsLogAutoInstallClick = true
                }

                downloadBtn.setOnClickListener {
                    if (!File(downloadEntity.path).exists()) {
                        ToastUtils.toast("畅玩组件已损坏，即将重新下载")
                        DownloadManager.getInstance().cancel(downloadEntity.url)
                        DownloadManager.getInstance().add(downloadEntity)
                    } else {
                        PackageInstaller.install(requireContext(), downloadEntity)
                        SensorsBridge.trackEvent("HaloFunInstallButtonClick", "space_schema_type", vSpaceType)
                    }
                }
            }

            cancel,
            hijack,
            notfound,
            uncertificated,
            unqualified -> {
                downloadBtn.text = "下载畅玩助手服务组件"
                downloadBtn.buttonStyle = DownloadButton.ButtonStyle.NORMAL
                downloadBtn.setOnClickListener {
                    DownloadManager.getInstance().resume(downloadEntity, false)
                }
            }

            else -> {
                // do nothing
            }
        }
    }

    companion object {
        const val KEY_APP_ENTITY_64 = "app_entity_64"
        const val KEY_APP_ENTITY_32 = "app_entity_32"
        const val KEY_AUTO_DOWNLOAD = "auto_download"
        const val KEY_IS_UPDATE = "is_update"

        const val SENSORS_LOG_DELAY = 1000L

        @JvmStatic
        fun showDownloadDialog(
            context: Context?,
            appEntity64: AppEntity?,
            appEntity32: AppEntity?,
            autoDownload: Boolean = false,
            isUpdate: Boolean = false,
            gameId: String = "",
            gameName: String = "",
            gameType: String = "",
            bit: String = ""
        ) {
            val fragmentActivity: FragmentActivity = if (context is FragmentActivity) {
                context
            } else {
                val currentActivity = AppManager.getInstance().currentActivity()
                if (currentActivity is FragmentActivity) {
                    currentActivity
                } else {
                    throw IllegalStateException("current activity context must be FragmentActivity")
                }
            }

            // 防止重复弹出
            if (hasDialogDisplayedInCurrentActivity(fragmentActivity)) return

            NewFlatLogUtils.logHaloFunDownloadDialogShow(gameId, gameName, if (bit == "32") "32位" else "64位")

            if (context is BaseActivity) {
                SensorsBridge.trackEvent(
                    "HaloFunDownloadDialogShow",
                    "game_id", gameId,
                    "game_name", gameName,
                    "game_type", gameType,
                    "game_schema_type", if (bit == "32") "32位" else "64位",
                    "last_page_name", context::class.java.simpleName,
                    "last_page_name", context::class.java.simpleName,
                    "last_page_id", context.getUniqueId(),
                    "last_page_business_id", context.getBusinessId().first,
                )
            }

            val downloadDialog = VSpaceDialogFragment().apply {
                arguments = Bundle().apply {
                    if (appEntity64 != null) putParcelable(KEY_APP_ENTITY_64, appEntity64)
                    if (appEntity32 != null) putParcelable(KEY_APP_ENTITY_32, appEntity32)
                    putString(EntranceConsts.KEY_GAME_ID, gameId)
                    putString(EntranceConsts.KEY_GAME_NAME, gameName)
                    putString(Constants.KEY_BIT, bit)
                    putBoolean(KEY_AUTO_DOWNLOAD, autoDownload)
                    putBoolean(KEY_IS_UPDATE, isUpdate)
                }
            }
            downloadDialog.show(
                fragmentActivity.supportFragmentManager,
                VSpaceDialogFragment::class.java.name
            )
        }

        /**
         * 显示下载弹窗
         * @param appEntity64 需要下载的 64 位组件实体，不为空即代表需要下载
         * @param appEntity32 需要下载的 32 位组件实体，不为空即代表需要下载
         * @param gameEntity 游戏相关的实体
         * @param autoDownload 是否需要显示弹窗即进行下载
         * @param isUpdate 是否为更新
         */
        @JvmStatic
        fun showDownloadDialog(
            context: Context?,
            appEntity64: AppEntity?,
            appEntity32: AppEntity?,
            gameEntity: GameEntity?,
            autoDownload: Boolean = false,
            isUpdate: Boolean = false
        ) {
            showDownloadDialog(
                context,
                appEntity64,
                appEntity32,
                autoDownload,
                isUpdate,
                gameEntity?.id ?: "",
                gameEntity?.name ?: "",
                gameEntity?.categoryChinese ?: "",
                gameEntity?.gameBit ?: ""
            )
        }

        private fun hasDialogDisplayedInCurrentActivity(fragmentActivity: FragmentActivity): Boolean {
            val fragments: List<Fragment> = fragmentActivity.supportFragmentManager.fragments
            fragments.forEach { fragment ->
                if (fragment is VSpaceDialogFragment) return true
            }
            return false
        }
    }

    internal class VSpaceDialogViewModel : ViewModel() {
        val packageLiveData = MutableLiveData<EBPackage>()
        private val mPackageChangedListener by lazy {
            PackageObserver.PackageChangeListener {
                packageLiveData.postValue(it)
            }
        }

        init {
            PackageObserver.registerPackageChangeChangeListener(mPackageChangedListener)
        }

        override fun onCleared() {
            super.onCleared()

            PackageObserver.unregisterPackageChangeChangeListener(mPackageChangedListener)
        }
    }

}