package com.gh.common.util

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider
import com.gh.common.dialog.InstallPermissionDialogFragment
import com.gh.common.xapk.XapkInstaller
import com.gh.download.server.BrowserInstallHelper
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.utils.DialogHelper
import com.gh.gamecenter.common.utils.getExtension
import com.gh.gamecenter.common.utils.getMetaExtra
import com.gh.gamecenter.common.utils.toRequestBody
import com.gh.gamecenter.core.utils.CurrentActivityHolder
import com.gh.gamecenter.core.utils.MD5Utils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.vspace.VHelper
import com.halo.assistant.HaloApp
import com.lightgame.download.DownloadEntity
import com.lightgame.download.FileUtils
import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.ResponseBody
import retrofit2.HttpException
import java.io.File

object PackageInstaller {

    /**
     * 为了兼容java代码
     */
    @JvmStatic
    fun install(context: Context, downloadEntity: DownloadEntity?) {
        downloadEntity?.let { install(context, downloadEntity, true) }
    }

    /**
     * 启动安装应用程序并取消通知栏安装消息
     *
     * 兼容所有包安装(apk,xapk),后续可加上apks
     *
     * 主动点击安装如果是xapk则需要toast提示
     */
    @JvmStatic
    fun install(context: Context, downloadEntity: DownloadEntity, showUnzipToast: Boolean) {
        val pkgPath = downloadEntity.path
        val isXapk = XapkInstaller.XAPK_EXTENSION_NAME == pkgPath.getExtension()
        val isVGame = downloadEntity.getMetaExtra(Constants.SMOOTH_GAME) == "true"

        val currentActivity = CurrentActivityHolder.getCurrentActivity() ?: return

        if (isVGame) {
            VHelper.install(currentActivity, downloadEntity)
            return
        }

        // TODO 此处可能遇到 activity 是 WXEntryActivity
        // TODO 当 activity 全部出栈，但是应用还在下载游戏，下载完会唤不起安装!
        if (currentActivity is AppCompatActivity && !currentActivity.isFinishing) {
            InstallPermissionDialogFragment.show(currentActivity, downloadEntity) { isFromPermissionGrantedCallback ->
                // 取消状态栏下载完成的通知，若存在
                downloadEntity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION] = "YES"
                DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity)

                if (isFromPermissionGrantedCallback && Build.VERSION.SDK_INT >= 31) {
                    val pm = context.packageManager
                    val intent = pm.getLaunchIntentForPackage(context.packageName)
                    val mainIntent = Intent.makeRestartActivityTask(intent!!.component)
                    context.startActivity(mainIntent)
                    Runtime.getRuntime().exit(0)
                } else {
                    if (isXapk) {
                        XapkInstaller.install(context, downloadEntity, showUnzipToast)
                    } else {
                        install(context, downloadEntity.isPlugin, downloadEntity.path)
                    }
                }
            }
        }
    }

    /**
     * 启动安装应用程序
     *
     * 除非特殊情况,请勿使用此方法进行应用安装操作
     * 除非你已经确定该文件一定是Apk
     */
    @JvmStatic
    fun install(context: Context, isPluggin: Boolean = false, pkgPath: String?) {
        if (pkgPath.isNullOrEmpty()) {
            ToastUtils.toast("下载文件异常")
            return
        }

        try {
            // 判断是否需要使用浏览器来进行安装
            if (BrowserInstallHelper.isUseBrowserToInstallEnabled()
                && BrowserInstallHelper.shouldUseBrowserToInstall()
            ) {
                BrowserInstallHelper.downloadFile(pkgPath)
                return
            }

            if (PackageUtils.isCanLaunchSetup(context, pkgPath)) {
//                val app = HaloApp.getInstance()

                HaloApp.put(Constants.LAST_INSTALL_GAME, pkgPath)

//                val downloadEntity =
//                    DownloadManager.getInstance().allDownloadEntity.firstOrNull {
//                        it.path == pkgPath
//                    }
//                if (downloadEntity != null) {
//                    showCertificateDialogIfNeededBeforeInstall(app, downloadEntity, pkgPath)
//                } else {
                val installIntent = getInstallIntent(context, pkgPath)
                context.startActivity(installIntent)
//                }
            } else {
                if (isPluggin) {
                    DialogHelper.showPluginDialog(context) {
                        uninstall(context, pkgPath)
                    }
                } else {
                    // 非插件化的同包名不同签名冲突
                    DialogHelper.showSignatureConflictDialog(context) {
                        uninstall(context, pkgPath)
                    }
                }
            }
        } catch (e: Exception) {
            Utils.toast(context, e.message)
        }
    }

    @SuppressLint("CheckResult")
    fun showCertificateDialogIfNeededBeforeInstall(context: Context, downloadEntity: DownloadEntity, pkgPath: String) {
        val isOverwrite = LunchType.UPDATE.name == SPUtils.getString(Constants.SP_INSTALL_TYPE)
        val hashMap = hashMapOf(Pair("url", downloadEntity.url), Pair("overwrite", isOverwrite))
        RetrofitManager.getInstance().api.postCertificationCheck(hashMap.toRequestBody())
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : BiResponse<ResponseBody>() {
                override fun onSuccess(data: ResponseBody) {
                    val installIntent = getInstallIntent(context, pkgPath)
                    context.startActivity(installIntent)
                }

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

                    if (exception is HttpException) {
                        val resultString =
                            (exception as HttpException).response().errorBody()
                                ?.string()
                        // 未实名
                        when {
                            resultString?.contains("403117") == true -> {
                                RealNameHelper.showRealNameUncertificatedDialog(
                                    downloadEntity
                                )
                            }
                            resultString?.contains("403118") == true -> {
                                RealNameHelper.showRealNameUnqualifiedDialog(
                                    downloadEntity
                                )
                            }
                            resultString?.contains("400004") == true -> {
                                ToastUtils.toast("安装服务异常，缺少参数")
                            }
                        }
                    } else {
                        ToastUtils.toast("安装服务异常，${exception.localizedMessage}请稍候再试")
                    }
                }
            })
    }

    /**
     * 获取启动安装意图
     *
     * 除非特殊情况,请勿使用此方法进行应用安装操作
     * 除非你已经确定该文件一定是Apk且该次安装无需检查签名情况
     */
    @JvmStatic
    fun getInstallIntent(context: Context, path: String): Intent {
        var uri = Uri.fromFile(File(path))
        val installIntent =
            if (BrowserInstallHelper.isUseBrowserToInstallEnabledWithPackageMatched()) {
                Intent(Intent.ACTION_INSTALL_PACKAGE)
            } else {
                Intent(Intent.ACTION_VIEW)
            }
        if ("smartisan" == Build.MANUFACTURER) {
            installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID, File(path))
            installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            installIntent.setDataAndType(uri, "application/vnd.android.package-archive")
            installIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
        } else {
            // 应用内更新不加 FLAG_ACTIVITY_NEW_TASK 在模拟器上会出现安装完成后安装界面也一并消失的类似闪退的表现
            // Application 上下文就更不用说了
            val pkgName = PackageUtils.getPackageNameByPath(context, path)
            if (pkgName == context.packageName || context !is Activity) {
                installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            }
            installIntent.setDataAndType(uri, "application/vnd.android.package-archive")
        }
        InstallUtils.getInstance()
            .addInstall(PackageUtils.getPackageNameByPath(context, path))
        return installIntent
    }

    /**
     * 卸载应用
     */
    @JvmStatic
    fun uninstall(context: Context, path: String) {
        // TODO 根据 path 获取包名可能出现获取不到的情况，看能不能改成直接用包名！
        val packageName = PackageUtils.getPackageNameByPath(context, path)
        uninstallForPackageName(context, packageName)
    }

    /**
     * 根据包名卸载应用
     */
    @JvmStatic
    fun uninstallForPackageName(context: Context, pkn: String?) {
        if (pkn.isNullOrEmpty()) return

        val uninstallIntent = Intent()
        uninstallIntent.action = Intent.ACTION_DELETE
        uninstallIntent.addCategory(Intent.CATEGORY_DEFAULT)
        if (context !is Activity) {
            uninstallIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        }
        uninstallIntent.data = Uri.parse("package:$pkn")
        InstallUtils.getInstance().addUninstall(pkn)
        context.startActivity(uninstallIntent)
    }

    @JvmStatic
    fun getDownloadPathWithId(id: String, format: String?): String {
        return FileUtils.getDownloadPath(
            HaloApp.getInstance().application,
            id + "." + getFileSuffixByFormat(format)
        )
    }

    private fun getFileSuffixByFormat(format: String?): String {
        return if (format == XapkInstaller.XAPK_EXTENSION_NAME) {
            XapkInstaller.XAPK_EXTENSION_NAME
        } else {
            "apk"
        }
    }

    @JvmStatic
    fun createDownloadId(gameName: String?): String {
        return MD5Utils.getContentMD5(gameName + "_" + System.currentTimeMillis())
    }
}