package com.gh.gamecenter.setting.view

import android.annotation.SuppressLint
import android.app.Application
import android.app.Dialog
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.text.TextUtils
import android.view.View
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModelProvider
import com.therouter.TheRouter
import com.blankj.utilcode.util.LanguageUtils
import com.gh.gamecenter.common.BuildConfig
import com.gh.gamecenter.common.base.activity.BaseActivity
import com.gh.gamecenter.common.base.fragment.ToolbarFragment
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.entity.WechatConfigEntity
import com.gh.gamecenter.common.retrofit.ApiResponse
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.provider.*
import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.core.utils.EmptyCallback
import com.gh.gamecenter.core.utils.GsonUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.login.entity.UserInfoEntity
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.login.user.UserRepository
import com.gh.gamecenter.login.user.UserViewModel
import com.gh.gamecenter.login.utils.LoginUtils
import com.gh.gamecenter.setting.R
import com.gh.gamecenter.setting.databinding.FragmentSettingBinding
import com.gh.gamecenter.setting.view.security.SecurityActivity
import com.gh.gid.GidHelper
import com.lightgame.utils.Utils
import io.reactivex.Observable
import io.reactivex.ObservableEmitter
import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import java.io.File
import java.util.*

class SettingsFragment : ToolbarFragment() {

    private lateinit var mBinding: FragmentSettingBinding
    private var checkSizeIndex = 0
    private var mIsUpdate = false
    private var loadingDialog: Dialog? = null
    private var mUsageStatus = false

    private val mViewModel: SettingViewModel by lazy { viewModelProvider() }

    override fun getLayoutId() = 0

    override fun getInflatedLayout() = FragmentSettingBinding.inflate(layoutInflater).apply { mBinding = this }.root

    @SuppressLint("SetTextI18n")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        initView()
        if (arguments != null) {
            mIsUpdate = requireArguments().getBoolean(EntranceConsts.KEY_VERSION_UPDATE, false)
            if (mIsUpdate) {
                mBinding.aboutItem.newVersionTv.visibility = View.VISIBLE
            } else {
                mBinding.aboutItem.newVersionTv.visibility = View.GONE

                if (PackageFlavorHelper.IS_TEST_FLAVOR == true) {
                    var channel = SPUtils.getString(Constants.SP_TEST_FLAVOR_CHANNEL)
                    if (channel == null || TextUtils.isEmpty(channel)) {
                        val appProvider =
                            TheRouter.get(IAppProvider::class.java)
                        channel = appProvider?.getChannel() ?: ""
                    }
                    mBinding.aboutItem.contentTv.text = "($channel)"
                    mBinding.aboutItem.contentTv.visibility = View.VISIBLE
                }
            }
        }

        val factory = UserViewModel.Factory(requireActivity().application)
        val mUserViewModel = ViewModelProvider(this, factory).get(
            UserViewModel::class.java
        )

        mViewModel.cacheSizeLiveData.observe(this) {
            mBinding.cacheItem.contentTv.text = it
        }

        mViewModel.getCacheSize()

        mBinding.personalRecommendItem.switchLottie.setSwitchAnimation(
            SPUtils.getBoolean(
                Constants.SP_PERSONAL_RECOMMEND,
                true
            )
        )

        checkSizeIndex = SPUtils.getInt(Constants.SP_FONT_SIZE, 1)
        if (checkSizeIndex == 0) {
            checkSizeIndex = 1
        }

        mUserViewModel.loginObsUserinfo.observe(this) { response: ApiResponse<UserInfoEntity?>? ->
            if (response != null && response.data != null) {
                mViewModel.getWechatConfig()
            } else {
                mViewModel.updateWechatConfig(null)
            }
        }

        initLoginStatus()

        initUsageStats()
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        mViewModel.wechatConfig.observe(viewLifecycleOwner) {
            initWechatBindStatus(it)
        }
    }

    private fun initWechatBindStatus(wechatEntity: WechatConfigEntity?) {
        if (wechatEntity != null) {
            val notice = wechatEntity.notice
            mBinding.wechatRemindItem.textMoreTv.text =
                if (notice == true) getString(com.gh.gamecenter.core.R.string.opened) else getString(R.string.closed)
        } else {
            mBinding.wechatRemindItem.textMoreTv.text = ""
        }
    }

    private fun initLoginStatus() {
        val loginToken = UserManager.getInstance().loginTokenEntity
        if (loginToken != null) {
            mBinding.settingLogout.visibility = View.VISIBLE
        } else {
            mBinding.settingLogout.visibility = View.GONE
        }
    }

    private fun initUsageStats() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
            return
        }
        val usageStatsHelper = TheRouter.get(IUsageStatsHelperProvider::class.java)
        if (usageStatsHelper?.checkForPermission() == true && SPUtils.getBoolean(Constants.SP_USAGE_STATUS, true)) {
            mUsageStatus = true
        } else {
            mUsageStatus = false
        }
        mBinding.usageStatsItem.switchLottie.setSwitchAnimation(mUsageStatus)
    }

    private fun initView() {
        mBinding.securityItem.run {
            titleTv.text = getString(R.string.setting_security)
            textMoreTv.visibility = View.VISIBLE
            root.setOnClickListener {
                ifLogin("设置-账号与安全-请先登录") {
                    startActivityForResult(
                        SecurityActivity.getIntent(
                            requireContext(),
                            mEntrance,
                            false
                        ), INSERT_MOBILE_CODE
                    )
                }
            }
        }
        mBinding.systemDarkModeItem.run {
            val config = TheRouter.get(IConfigProvider::class.java)
            root.goneIf(!(config?.getNightModeSetting() ?: false)) {
                titleTv.text = getString(R.string.setting_system_dark_mode)
                switchLottie.visibility = View.VISIBLE
                switchLottie.setSwitchAnimation(DarkModeUtils.isFollowSystemDarkModeFromSp())
                root.setOnClickListener {
                    val status = DarkModeUtils.isFollowSystemDarkModeFromSp()
                    NewFlatLogUtils.logHaloSelfNightModeOsSwitch(!status)
                    switchLottie.setSwitchAnimation(status)
                    switchLottie.playAnimation()
                    DarkModeUtils.updateFollowSystemDarkModeToSp(!status)
                    DarkModeUtils.updateAppDarkModeStatusToSp(mIsDarkModeOn)
                    DarkModeUtils.initDarkMode()
                }
            }
        }

        mBinding.videoItem.run {
            titleTv.text = getString(R.string.setting_video)
            textMoreTv.visibility = View.VISIBLE
            root.setOnClickListener {
                startActivity(VideoSettingActivity.getIntent(requireContext(), "设置"))
            }
        }

        mBinding.languageItem.run {
            titleTv.text = getString(R.string.language)
            textMoreTv.visibility = View.VISIBLE
            // 港澳台APP显示语言设置
            root.visibility = if (EnvHelper.isGATApp) View.VISIBLE else View.GONE
            root.setOnClickListener {
                startActivity(LanguageSettingActivity.getIntent(requireContext()))
            }
        }

        mBinding.gameDownloadItem.run {
            titleTv.text = getString(R.string.setting_game_download)
            textMoreTv.visibility = View.VISIBLE
            root.setOnClickListener {
                startActivity(GameDownloadSettingActivity.getIntent(requireContext(), "设置"))
            }
        }
        mBinding.gameSubmissionItem.run {
            titleTv.text = getString(R.string.setting_game_submission)
            textMoreTv.visibility = View.VISIBLE
            root.setOnClickListener {
                ifLogin("设置-游戏投稿-请先登录") {
                    PermissionHelper.checkStoragePermissionBeforeAction(requireContext()) {
                        TheRouter.build(RouteConsts.activity.gameSubmissionActivity)
                            .withString(
                                EntranceConsts.KEY_ENTRANCE,
                                BaseActivity.mergeEntranceAndPath(mEntrance, "游戏上传")
                            )
                            .navigation(this@SettingsFragment)
                    }
                }
            }
        }
        mBinding.installMethodItem.run {
            titleTv.text = getString(R.string.setting_install_method)
            textMoreTv.visibility = View.VISIBLE
        }
        mBinding.usageStatsItem.run {
            titleTv.text = getString(R.string.setting_usage_stats)
            switchLottie.visibility = View.VISIBLE
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
                root.setOnClickListener {
                    val usageStatsHelper = TheRouter.get(IUsageStatsHelperProvider::class.java)
                    if (usageStatsHelper?.checkForPermission() == true) {
                        DialogHelper.showDialog(
                            requireContext(),
                            getString(com.gh.gamecenter.core.R.string.hint),
                            getString(R.string.close_game_time_statistics_dialog_content),
                            getString(com.gh.gamecenter.core.R.string.confirm_and_close),
                            getString(com.gh.gamecenter.core.R.string.not_close_yet),
                            {
                                usageStatsHelper.skipToUsageStats(
                                    requireContext(),
                                    USAGE_STATUS_REQUEST_CODE
                                )
                            }, {}, extraConfig = DialogHelper.Config(centerContent = true, centerTitle = true)
                        )
                    } else {
                        val dialogUtils = TheRouter.get(IDialogUtilsProvider::class.java)
                        dialogUtils?.showUsageStatsDialog(
                            requireContext(), {
                                usageStatsHelper?.skipToUsageStats(
                                    requireContext(),
                                    USAGE_STATUS_REQUEST_CODE
                                )
                            }, {}
                        )
                    }
                }
            }
        }
        mBinding.wechatRemindItem.run {
            titleTv.text = getString(R.string.setting_wechat_remind)
            textMoreTv.visibility = View.VISIBLE
            root.setOnClickListener {
                if (UserManager.getInstance().isLoggedIn) {
                    val json = SPUtils.getString(Constants.SP_WECHAT_CONFIG)
                    val entity = GsonUtils.fromJson(json, WechatConfigEntity::class.java)
                    if (entity != null) {
                        NewLogUtils.logWechatRemindConfigClick(entity.bind, entity.follow, entity.notice)
                    }
                    val webActivity = TheRouter.get(IWebProvider::class.java)
                    requireContext().startActivity(webActivity?.getBindWechatIntent(requireContext()))
                    SensorsBridge.trackEvent("AppointmenWechatRemindConfigPageShow", "source_entrance", "设置-微信提醒")
                } else {
                    ifLogin("我的光环_设置") {}
                }
            }
        }
        mBinding.notificationAuthorityItem.run {
            titleTv.text = getString(R.string.setting_notification_authority)
            tipsTv.text = getString(R.string.setting_notification_authority_hint)
            switchLottie.visibility = View.VISIBLE
            tipsTv.visibility = View.VISIBLE
            root.setOnClickListener {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    //这种方案适用于 API 26, 即8.0（含8.0）以上可以用
                    val notifyIntent = Intent()
                    notifyIntent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
                    val buildConfig = TheRouter.get(IBuildConfigProvider::class.java)
                    notifyIntent.putExtra(Settings.EXTRA_APP_PACKAGE, buildConfig?.getApplicationId())
                    startActivity(notifyIntent)
                } else {
                    PermissionHelper.toPermissionSetting(requireActivity())
                }
            }
        }
        mBinding.personalRecommendItem.run {
            titleTv.text = getString(R.string.setting_personal_recommend)
            tipsTv.text = getString(R.string.setting_personal_recommend_hint)
            tipsTv.visibility = View.VISIBLE
            switchLottie.visibility = View.VISIBLE
            root.setOnClickListener {
                if (switchLottie.isAnimating) return@setOnClickListener
                val status = SPUtils.getBoolean(Constants.SP_PERSONAL_RECOMMEND, true)
                switchLottie.setSwitchAnimation(status)
                switchLottie.playAnimation()
                SPUtils.setBoolean(Constants.SP_PERSONAL_RECOMMEND, !status)
            }
        }
        mBinding.aboutItem.run {
            titleTv.text = getString(R.string.setting_about)
            root.setOnClickListener {
                startActivity(AboutActivity.getIntent(requireContext(), mIsUpdate))
            }
            if (PackageFlavorHelper.IS_TEST_FLAVOR == true) {
                titleTv.text = getString(R.string.setting_about_channel)
                root.setOnLongClickListener({
                    EnvHelper.showChangeChannelDialog(requireContext(), true)
                    return@setOnLongClickListener true
                })
            }
        }
        mBinding.cacheItem.run {
            titleTv.text = getString(R.string.setting_clear_cache)
            contentTv.visibility = View.VISIBLE
            root.setOnClickListener {
                DialogHelper.showCenterWarningDialog(
                    requireContext(),
                    getString(R.string.clear_cache_dialog_title),
                    getString(R.string.clear_cache_dialog_content),
                    object : EmptyCallback {
                        override fun onCallback() {
                            val dialogUtils = TheRouter.get(IDialogUtilsProvider::class.java)
                            loadingDialog = dialogUtils?.showWaitDialog(
                                requireContext(),
                                getString(R.string.clearing_cache)
                            )
                            val historyHelper = TheRouter.get(IHistoryHelperProvider::class.java)
                            historyHelper?.emptyDatabase()
                            // 清除新游开测存储的游戏类型
                            SPUtils.remove(Constants.SP_GAME_SERVER_TEST_V2_CATEGORY_SET)
                            clearCache()
                        }
                    })
            }
            if (PackageFlavorHelper.IS_TEST_FLAVOR) {
                titleTv.text = getString(R.string.setting_clear_cache) + getString(R.string.long_click_to_clear_gid)
                root.setOnLongClickListener {
                    GidHelper.getInstance().clearSavedGid()
                    Utils.toast(context, getString(R.string.gid_cleared_toast))
                    return@setOnLongClickListener true
                }
            }
        }
        mBinding.networkDiagnosisItem.run {
            titleTv.text = getString(R.string.network_diagnostics)
            root.setOnClickListener {
                startActivity(Intent(requireContext(), NetworkDiagnosisActivity::class.java))
            }

            if (PackageFlavorHelper.IS_TEST_FLAVOR) {
                if (SPUtils.getString(Constants.SP_TEST_FLAVOR_IP).isNotEmpty()) {
                    titleTv.text = "网络诊断（当前的设置的 IP 为: ${SPUtils.getString(Constants.SP_TEST_FLAVOR_IP)}）"
                } else {
                    titleTv.text = "网络诊断（长按可切换 IP）"
                }

                root.setOnLongClickListener {
                    DialogHelper.showDialog(
                        context = requireContext(),
                        title = "切换 IP 地区",
                        content = "是否切换 IP 地区并重启助手",
                        confirmText = "是",
                        cancelText = "否",
                        confirmClickCallback = {
                            EnvHelper.showChangeIpDialog(requireContext())
                        })
                    return@setOnLongClickListener true
                }
            }
        }
        mBinding.settingLogout.setOnClickListener {
            val dialogUtils = TheRouter.get(IDialogUtilsProvider::class.java)
            DialogHelper.showDialog(
                requireContext(),
                R.string.logout_dialog_title.toResString(),
                R.string.logout_dialog_content.toResString(),
                R.string.logout_dialog_confirm.toResString(),
                com.gh.gamecenter.common.R.string.cancel.toResString(),
                {
                    loadingDialog = dialogUtils?.showWaitDialog(requireContext(), getString(R.string.logging_out))
                    LoginUtils.logout {
                        UserRepository.getInstance().logout()
                        if (loadingDialog != null) loadingDialog!!.dismiss()
                        if (activity != null) requireActivity().finish()
                        val qProvider = TheRouter.get(IQGameProvider::class.java)
                        qProvider?.stopAllMiniApp(true) // 关闭所有QQ小游戏进程
                        TheRouter.get(IMiniGameRecentlyPlayedProvider::class.java)
                            ?.clearMiniGameRecentlyPlayed(Constants.QQ_MINI_GAME)
                    }
                },
                extraConfig = DialogHelper.Config(
                    centerTitle = true,
                    centerContent = true
                ),
                uiModificationCallback = {
                    it.confirmTv.setTextColor(com.gh.gamecenter.common.R.color.secondary_red.toColor(requireContext()))
                }
            )
        }
    }

    // 清除缓存
    private fun clearCache() {
        Observable.create { emitter: ObservableEmitter<Any?> ->
            val start = System.currentTimeMillis()
            FileUtils.deleteFolder(requireContext().cacheDir)
            FileUtils.deleteFolder(requireContext().externalCacheDir)
            val time = System.currentTimeMillis() - start
            if (time < 1000) {
                try {
                    Thread.sleep(1000 - time)
                } catch (e: InterruptedException) {
                    e.printStackTrace()
                }
            }

//                Fresco.getImagePipeline().clearCaches(); // 清空图片缓存
            emitter.onComplete()
        }.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Observer<Any?> {
                override fun onComplete() {
                    if (loadingDialog != null) {
                        loadingDialog!!.dismiss()
                    }
                    mViewModel.getCacheSize()
                    Utils.toast(context, getString(R.string.clear_cache_successfully_toast))
                }

                override fun onError(e: Throwable) {}
                override fun onSubscribe(d: Disposable) {}
                override fun onNext(t: Any) {}
            })
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == USAGE_STATUS_REQUEST_CODE && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
            val usageStatsHelper = TheRouter.get(IUsageStatsHelperProvider::class.java)
            SPUtils.setBoolean(Constants.SP_USAGE_STATUS, usageStatsHelper?.checkForPermission() == true)
            initUsageStats()
        }

        // 当前登录方式为手机号登录，更换手机号后，回到该界面更新"退出账号"的手机号
        if (requestCode == INSERT_MOBILE_CODE) {
            initLoginStatus()
        }
    }

    override fun onPause() {
        super.onPause()
        saveCurrentSetting()
    }

    private fun saveCurrentSetting() = SPUtils.setInt(Constants.SP_FONT_SIZE, checkSizeIndex)

    override fun onResume() {
        super.onResume()
        setNavigationTitle(getString(R.string.title_settings))

        mBinding.notificationAuthorityItem.switchLottie.setSwitchAnimation(NotificationHelper.notificationIsEnable())

        val browserInstallHelper = TheRouter.get(IBrowserInstallHelperProvider::class.java)
        if (browserInstallHelper?.isUseBrowserToInstallEnabled() == true) {
            if (browserInstallHelper.shouldUseBrowserToInstall()) {
                mBinding.installMethodItem.textMoreTv.text = getString(R.string.browser_install)
            } else {
                mBinding.installMethodItem.textMoreTv.text = getString(R.string.assistant_install)
            }
            mBinding.installMethodContainer.visibility = View.VISIBLE
            mBinding.installMethodItem.root.setOnClickListener {
                val shellActivity = TheRouter.get(IShellProvider::class.java)
                val intent = shellActivity?.getSwitchInstallMethodIntent(requireContext(), null)
                requireContext().startActivity(intent)
                browserInstallHelper.logSwitchInstallSettingEvent()
            }
        }

        if (EnvHelper.isGATApp) {
            mBinding.languageItem.run {
                textMoreTv.text = if (LanguageUtils.isAppliedLanguage(Locale.TRADITIONAL_CHINESE)) {
                    getString(R.string.traditional_chinese)
                } else {
                    getString(R.string.simplified_chinese)
                }
            }
        }
    }

    override fun onStop() {
        saveCurrentSetting()
        super.onStop()
    }

    class SettingViewModel(application: Application) : AndroidViewModel(application) {
        val cacheSizeLiveData = MutableLiveData<String>()

        // 获取缓存大小
        fun getCacheSize() {
            runOnIoThread {
                val ecDir = getApplication<Application>().externalCacheDir
                var cacheLength: Long = getFolderSize(getApplication<Application>().cacheDir)
                if (ecDir != null) {
                    cacheLength += getFolderSize(ecDir)
                }
                cacheSizeLiveData.postValue(long2Size(cacheLength))
            }
        }

        private fun long2Size(length: Long): String {
            val m = length / 1024f / 1024f
            var str = m.toString()
            val index = str.lastIndexOf(".")
            if (index != -1 && str.length > index + 3) {
                str = str.substring(0, index + 3)
            }
            return str + "M"
        }

        private fun getFolderSize(folder: File): Long {
            var size: Long = 0
            //忽略视频缓存
            if (folder.name == "video-cache" || folder.name == "exo") return size
            size += folder.length()
            if (folder.isDirectory) {
                val files = folder.listFiles()
                if (files == null || files.isEmpty()) return size
                for (file in files) {
                    size += if (file.isDirectory) {
                        getFolderSize(file)
                    } else {
                        file.length()
                    }
                }
            }
            return size
        }

        private val _wechatConfig = MutableLiveData<WechatConfigEntity?>()
        val wechatConfig: LiveData<WechatConfigEntity?> = _wechatConfig
        fun updateWechatConfig(wechatEntity: WechatConfigEntity?) {
            _wechatConfig.value = wechatEntity
        }

        fun getWechatConfig() {
            val wechatBindHelper = TheRouter.get(IWechatBindHelperProvider::class.java)
            wechatBindHelper?.getWechatConfig(callback = {
                updateWechatConfig(it as? WechatConfigEntity)
            })
        }

    }

    override fun onDarkModeChanged() {
        super.onDarkModeChanged()
        mBinding.root.setBackgroundColor(com.gh.gamecenter.common.R.color.ui_background.toColor(requireContext()))
        mBinding.personalRecommendItem.switchLottie.setSwitchAnimation(
            SPUtils.getBoolean(
                Constants.SP_PERSONAL_RECOMMEND,
                true
            )
        )
        mBinding.usageStatsItem.switchLottie.setSwitchAnimation(mUsageStatus)
        mBinding.notificationAuthorityItem.switchLottie.setSwitchAnimation(NotificationHelper.notificationIsEnable())
    }

    companion object {
        const val INSERT_MOBILE_CODE = 411
        const val USAGE_STATUS_REQUEST_CODE = 233
    }
}