package com.gh.gamecenter.gamedetail.accelerator.dialog

import android.app.Dialog
import android.content.Context
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.viewModels
import com.gh.common.dialog.AccelerateExpirationDialogFragment
import com.gh.common.util.PackageLauncher
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.core.callback.AccelerateState
import com.gh.gamecenter.core.callback.OnAccelerateListener
import com.gh.gamecenter.core.provider.IAcceleratorProvider
import com.gh.gamecenter.core.utils.CurrentActivityHolder
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.databinding.DialogFragmentStartingAcceleratorBinding
import com.gh.gamecenter.feature.entity.AcctGameInfo
import com.gh.gamecenter.feature.entity.AcctRecord
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.VipEntity
import com.gh.gamecenter.gamedetail.StartingAcceleratorViewModel
import com.gh.gamecenter.gamedetail.accelerator.GameDetailAcceleratorUiHelper.Companion.DISTRICT_SERVER_HAVA
import com.gh.gamecenter.gamedetail.accelerator.GameDetailAcceleratorUiHelper.Companion.SOURCE_ENTRANCE_GAME_DETAIL
import com.gh.gamecenter.gamedetail.accelerator.dialog.AcceleratorDialogFragment.Companion.SPEED_ENABLE_VIP
import com.gh.gamecenter.gamedetail.accelerator.dialog.AcceleratorDialogFragment.Companion.SPEED_START_FAILURE
import com.gh.gamecenter.livedata.EventObserver
import com.halo.assistant.accelerator.repository.AcceleratorDataHolder
import com.therouter.TheRouter
import io.reactivex.disposables.CompositeDisposable
import java.util.*
import kotlin.math.ceil
import kotlin.math.max

class StartingAcceleratorDialogFragment : BaseDialogFragment() {

    private val viewModel by viewModels<StartingAcceleratorViewModel>()

    private lateinit var binding: DialogFragmentStartingAcceleratorBinding

    private lateinit var zoneInfo: AcctGameInfo.ZoneInfo
    private lateinit var game: GameEntity
    private var isNeedRecord: Boolean = false
    private var iAcceleratorProvider: IAcceleratorProvider? = null
    private var hasMultiZone = false
    private var sourceEntrance = SOURCE_ENTRANCE_GAME_DETAIL

    private val compositeDisposable = CompositeDisposable()
    private var _progress = 0
    private val handler = Handler(Looper.getMainLooper())

    private var refreshTokenCount = 0

    private val acceleratorDataHolder = AcceleratorDataHolder.instance

    private val accelerationListener = object : OnAccelerateListener {
        override fun onStateChanged(state: AccelerateState) {
            // 如果状态能成功回,则移除计时
            handler.removeCallbacksAndMessages(null)
            when (state) {
                is AccelerateState.Success -> {
                    ToastUtils.showToast("加速成功")
                    // 加速成功，启动游戏
                    PackageLauncher.launchApp(requireContext(), game, game.getUniquePackageName())
                    // 记录加速成功的游戏
                    viewModel.useCase.recordAcctGameInfo(game, zoneInfo, hasMultiZone)

                    trackNetworkAccelerationStartupResult("成功")
                    dismissAllowingStateLoss()
                }

                is AccelerateState.Failure -> {
                    // 有些错误需要额外处理，这里直接跳过错误提示(如：token失效，登录时token设置失败)
                    if ((state.isTokenInvalid) && refreshTokenCount < REFRESH_TOKEN_MAX_COUNT) {
                        // do nothing
                    } else {
                        if (!state.isSkipError) {
                            context?.let {
                                AcceleratorDialogFragment.show(
                                    SPEED_START_FAILURE,
                                    game.getUniquePackageName() ?: "",
                                    game.id,
                                    game.name ?: "",
                                    sourceEntrance,
                                    it
                                )
                                // 加速失败，上传奇游加速器log
                                unloadAcceleratorErrorLog(game)
                            }
                        } else {
                            // 由于每次加速前，都会检测加速会员权限，所以一般不会出现这种场景，这里只是为了兼容特殊情况，弹出相应提示
                            if (state.isPermissionExpired) {
                                //  加速会员过期 ,如果之前没有弹出过耗尽提醒，则弹出提示
                                val reminder =
                                    AccelerateExpirationDialogFragment.ExpirationReminder.TimeRunsOut(sourceEntrance)
                                AccelerateExpirationDialogFragment.checkDialogShown(requireContext(), reminder) {
                                    if (!it) {
                                        // 之前弹出过耗尽提醒弹窗，这里直接展示加速失败
                                        AcceleratorDialogFragment.show(
                                            SPEED_START_FAILURE,
                                            game.getUniquePackageName() ?: "",
                                            game.id,
                                            game.name ?: "",
                                            sourceEntrance,
                                            requireContext()
                                        )
                                    }
                                }

                                iAcceleratorProvider?.loadQyUserPermissionData()
                                // 加速失败，上传奇游加速器log
                                unloadAcceleratorErrorLog(game)
                            }
                        }

                        dismissAllowingStateLoss()
                        trackNetworkAccelerationStartupResult("失败(${state.code})")
                    }
                }

                is AccelerateState.Normal -> {

                    if (state.isTokenInvalid) {
                        // token过期/登录时token设置失败,在此获取token并重新启动加速(最多重试三次)
                        if (refreshTokenCount < REFRESH_TOKEN_MAX_COUNT) {
                            viewModel.loadAcceleratorToken()
                            refreshTokenCount++
                        }
                    }
                }

                else -> Unit
            }
        }

        override fun onProgress(progress: Int, curGamePkgName: String?, curGameZoneFlag: String?) {
            _progress = max(_progress, progress)
            binding.tvProgress.text = getString(R.string.accelerating_with_progress, "$progress")
        }

    }

    private fun unloadAcceleratorErrorLog(game: GameEntity) {
        viewModel.useCase.unloadAcceleratorErrorLog(game)
    }

    private fun trackNetworkAccelerationStartupResult(result: String) {
        SensorsBridge.trackNetworkAccelerationStartupResult(
            game.getUniquePackageName() ?: "",
            game.id,
            game.name ?: "",
            acceleratorDataHolder.memberType,
            if (hasMultiZone) zoneInfo.cnName ?: "" else DISTRICT_SERVER_HAVA,
            result,
            sourceEntrance
        )
    }

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        return super.onCreateDialog(savedInstanceState).apply {
            setCancelable(false)
            setCanceledOnTouchOutside(false)
            this@StartingAcceleratorDialogFragment.isCancelable = false
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        iAcceleratorProvider = TheRouter.get(IAcceleratorProvider::class.java)
        zoneInfo = arguments?.getParcelable(EntranceConsts.KEY_ACCT_ZONE_INFO)!!
        game = arguments?.getParcelable(EntranceConsts.KEY_GAME)!!
        isNeedRecord = arguments?.getBoolean(EntranceConsts.KEY_IS_NEED_RECORD) ?: false
        hasMultiZone = arguments?.getBoolean(EntranceConsts.KEY_HAS_MULTI_ZONE) ?: false
        sourceEntrance = arguments?.getString(EntranceConsts.KEY_SOURCE_ENTRANCE) ?: SOURCE_ENTRANCE_GAME_DETAIL
    }

    override fun onBack(): Boolean {
        return true
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        return DialogFragmentStartingAcceleratorBinding.inflate(inflater, container, false)
            .also {
                binding = it
            }.root
    }

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

        binding.tvProgress.text = getString(R.string.accelerating_with_progress, "0")
        iAcceleratorProvider?.bindAccRelatedListener("", accelerationListener)

        viewModel.restartingAcceleratorAction.observe(viewLifecycleOwner, EventObserver {
            startGameAccelerate()
        })

        viewModel.rechargeTrailResult.observe(viewLifecycleOwner, EventObserver {
            if (it) {
                startGameAccelerate()
            } else {
                // 充值失败
                AcceleratorDialogFragment.show(
                    SPEED_START_FAILURE,
                    game.getUniquePackageName() ?: "",
                    game.id,
                    game.name ?: "",
                    sourceEntrance,
                    requireContext()
                )
                dismissAllowingStateLoss()
            }

        })

        viewModel.vipEntity.observe(viewLifecycleOwner, EventObserver {
            if (it == null) {
                // 获取用户vip数据失败，直接弹出加速失败
                AcceleratorDialogFragment.show(
                    SPEED_START_FAILURE,
                    game.getUniquePackageName() ?: "",
                    game.id,
                    game.name ?: "",
                    sourceEntrance,
                    requireContext()
                )
                dismissAllowingStateLoss()
                trackNetworkAccelerationStartupResult("失败(获取vip数据失败)")
            } else {
                // 获取用户vip数据成功
                canUserEnableAcceleration(it) {
                    startGameAccelerate()
                }
            }
        })

        viewModel.loadVipStatus()
    }

    private fun canUserEnableAcceleration(vipEntity: VipEntity, callback: () -> Unit) {
        if (vipEntity.isNewUser) {
            // 如果是新用户，下单试用套餐
            viewModel.rechargeTrial()
            return
        }

        val serviceTime = vipEntity.timestamp
        val userRemainingDays = calculateCalendarDaysDiff(vipEntity.vipExpireTime, serviceTime)

        //如果是试用会员 或者是 包月会员，并且还没有临期: 直接启动。
        if (vipEntity.isTryVip || (vipEntity.vipStatus && userRemainingDays > 3)) {
            callback()
            return
        }

        // 包月会员不足三天
        if (vipEntity.isMonthVip && userRemainingDays in 1..3) {
            val reminder = AccelerateExpirationDialogFragment.ExpirationReminder.UserExpired(
                userRemainingDays, game.id, game.name ?: "", game.getUniquePackageName() ?: "", sourceEntrance
            )
            AccelerateExpirationDialogFragment.checkDialogShown(requireContext(), reminder) {
                if (it) {
                    dismissAllowingStateLoss()
                } else {
                    callback()
                }
            }
            return
        }

        // 检查时长套餐是否快要耗尽
        val durationRemainingMinute = vipEntity.durationExpiredTime
        if (vipEntity.isDurationVip && durationRemainingMinute < 0) {
            // 用户是时长会员，但是剩余时长为 -1 ，说明后端拉取奇游剩余时长失败，此时无法判断用户的时长会员是否到期，直接开启加速
            callback()
            return
        }

        // 用户是时长会员，并且将要消耗完毕
        val durationRemainingHours = ceil(durationRemainingMinute / 60.0).toLong()
        if (vipEntity.isDurationVip && durationRemainingHours in 1..3) {
            val reminder = AccelerateExpirationDialogFragment.ExpirationReminder.InsufficientDuration(
                durationRemainingHours, game.id, game.name ?: "", game.getUniquePackageName() ?: "", sourceEntrance
            )
            AccelerateExpirationDialogFragment.checkDialogShown(requireContext(), reminder) {
                if (it) {
                    dismissAllowingStateLoss()
                } else {
                    callback()
                }
            }
            return
        }

        // 检查时长套餐是否快要过期
        val durationRemainingDays = calculateCalendarDaysDiff(vipEntity.durationVipExpiredTime, serviceTime)
        if (vipEntity.isDurationVip && durationRemainingDays in 1..3) {
            val reminder = AccelerateExpirationDialogFragment.ExpirationReminder.DurationExpired(
                durationRemainingDays, game.id, game.name ?: "", game.getUniquePackageName() ?: "", sourceEntrance
            )
            AccelerateExpirationDialogFragment.checkDialogShown(requireContext(), reminder) {
                if (it) {
                    dismissAllowingStateLoss()
                } else {
                    callback()
                }
            }
            return
        }

        // 检查会员是否到期
        val hasShow = SPUtils.getBoolean(Constants.SP_ACCELERATOR_MEMBERSHIP_EXPIRED)
        val showExpiredDialog = !vipEntity.vipStatus &&
                !vipEntity.isNewUser &&
                !vipEntity.isVipRefundUser &&
                !vipEntity.isDurationRefundUser &&
                !hasShow
        if (showExpiredDialog) {
            val reminder = AccelerateExpirationDialogFragment.ExpirationReminder.TimeRunsOut(sourceEntrance)
            AccelerateExpirationDialogFragment.checkDialogShown(requireContext(), reminder) {
                if (it) {
                    dismissAllowingStateLoss()
                } else {
                    callback()
                }
            }
            return
        }

        // 检查是否是会员
        if (vipEntity.vipStatus) {
            callback()
        } else {
            // 弹出去充值弹窗
            AcceleratorDialogFragment.show(
                SPEED_ENABLE_VIP,
                game.getUniquePackageName() ?: "",
                game.id,
                game.name ?: "",
                sourceEntrance,
                requireContext()
            )
            dismissAllowingStateLoss()
        }
    }

    private fun calculateCalendarDaysDiff(timeSeconds1: Long, timeSeconds2: Long): Long {
        // 转换秒为毫秒
        val millis1 = timeSeconds1 * 1000
        val millis2 = timeSeconds2 * 1000

        val calendar1 = Calendar.getInstance().apply {
            timeInMillis = millis1
            set(Calendar.HOUR_OF_DAY, 0)
            set(Calendar.MINUTE, 0)
            set(Calendar.SECOND, 0)
            set(Calendar.MILLISECOND, 0)
        }
        val calendar2 = Calendar.getInstance().apply {
            timeInMillis = millis2
            set(Calendar.HOUR_OF_DAY, 0)
            set(Calendar.MINUTE, 0)
            set(Calendar.SECOND, 0)
            set(Calendar.MILLISECOND, 0)
        }

        // 计算两个日期零点之间的差值（毫秒），再转换为天数
        val diff = (calendar1.timeInMillis - calendar2.timeInMillis) / (1000 * 60 * 60 * 24)
        // 当diff == 0 时，当天过期，此时剩余天数为 1 天
        return if (diff >= 0) diff + 1 else -1
    }


    private fun startGameAccelerate() {
        handler.removeCallbacksAndMessages(null)
        handler.postDelayed({
            // 15s以后，不管成功还是失败，都要关闭当前页面
            dismissAllowingStateLoss()
        }, TIME_OUT)
        AcceleratorDataHolder.instance.acctGameRecord = AcctRecord(game.id, game, zoneInfo, hasMultiZone, 0)
        iAcceleratorProvider?.startQyGameAccelerate(game.id, game.getUniquePackageName() ?: "", zoneInfo)
        if (isNeedRecord) {
            viewModel.useCase.insertAcctGameInfo(
                AcctGameInfo(game.id, game.getUniquePackageName() ?: "", zoneInfo)
            )
        }
        if (refreshTokenCount == 0) {

            SensorsBridge.trackNetworkAccelerationStartup(
                game.getUniquePackageName() ?: "",
                game.id,
                game.name ?: "",
                acceleratorDataHolder.memberType,
                if (hasMultiZone) zoneInfo.cnName ?: "" else DISTRICT_SERVER_HAVA,
                sourceEntrance
            )
        }

    }

    override fun onDestroyView() {
        handler.removeCallbacksAndMessages(null)
        iAcceleratorProvider?.unBindAccRelatedListener(accelerationListener)
        super.onDestroyView()
        compositeDisposable.clear()

    }

    companion object {
        private const val TIME_OUT = 1000 * 15L
        private const val REFRESH_TOKEN_MAX_COUNT = 3

        fun show(
            context: Context,
            zoneInfo: AcctGameInfo.ZoneInfo,
            game: GameEntity,
            isNeedRecord: Boolean,
            hasMultiZone: Boolean,
            sourceEntrance: String
        ) {
            if (context is AppCompatActivity) {
                context.supportFragmentManager
            } else {
                (CurrentActivityHolder.getCurrentActivity() as? AppCompatActivity)?.supportFragmentManager
            }?.let {
                val fragment = StartingAcceleratorDialogFragment().apply {
                    arguments = Bundle().apply {
                        putParcelable(EntranceConsts.KEY_ACCT_ZONE_INFO, zoneInfo)
                        putParcelable(EntranceConsts.KEY_GAME, game)
                        putBoolean(EntranceConsts.KEY_IS_NEED_RECORD, isNeedRecord)
                        putBoolean(EntranceConsts.KEY_HAS_MULTI_ZONE, hasMultiZone)
                        putString(EntranceConsts.KEY_SOURCE_ENTRANCE, sourceEntrance)
                    }
                }
                fragment.show(it, fragment::class.java.simpleName)
            }
        }
    }
}