package com.halo.assistant.accelerator

import android.annotation.SuppressLint
import android.app.Activity
import android.os.Build
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.gh.gamecenter.common.entity.ErrorEntity
import com.gh.gamecenter.common.exposure.meta.MetaUtil
import com.gh.gamecenter.common.exposure.meta.MetaUtil.getBase64EncodedIMEI
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.utils.singleToMain
import com.gh.gamecenter.common.utils.toObject
import com.gh.gamecenter.common.utils.toRequestBody
import com.gh.gamecenter.common.utils.toResString
import com.gh.gamecenter.core.provider.IAppProvider
import com.gh.gamecenter.core.provider.IPackageUtilsProvider
import com.gh.gamecenter.eventbus.EBStartupAcceleration
import com.gh.gamecenter.feature.entity.*
import com.gh.gamecenter.feedback.R
import com.gh.gamecenter.gamedetail.accelerator.AccelerationDataBase
import com.gh.gamecenter.livedata.Event
import com.halo.assistant.accelerator.AccelerationUseCase.UserVerifyState.Companion.ERROR_CODE_MINORS
import com.halo.assistant.accelerator.AccelerationUseCase.UserVerifyState.Companion.ERROR_CODE_UNVERIFIED
import com.halo.assistant.accelerator.AccelerationUseCase.UserVerifyState.Companion.ERROR_CODE_VERIFYING
import com.halo.assistant.accelerator.repository.AccelerationRepository
import com.therouter.TheRouter
import io.reactivex.Single
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import org.greenrobot.eventbus.EventBus
import retrofit2.HttpException
import java.util.concurrent.TimeUnit

class AccelerationUseCase {

    private val compositeDisposable = CompositeDisposable()

    private val repository = AccelerationRepository.newInstance()

    private val _showUserVerifyDialog = MutableLiveData<Event<UserVerifyState>>()
    val showUserVerifyDialog: LiveData<Event<UserVerifyState>> = _showUserVerifyDialog

    private val _requestAlipayAction = MutableLiveData<Event<Pair<OrderEntity, AliPayEntity>>>()
    val requestAlipayAction: LiveData<Event<Pair<OrderEntity, AliPayEntity>>> = _requestAlipayAction

    fun preOrderWithAlipay(order: OrderEntity) {
        repository.preOrderWithAli(order)
            .compose(singleToMain())
            .subscribe(object : BiResponse<AliPayEntity>() {
                override fun onSuccess(data: AliPayEntity) {
                    _requestAlipayAction.value = Event(order to data)
                }

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

                }
            }).let(compositeDisposable::add)
    }


    fun sendAlipayRequest(activity: Activity, order: OrderEntity, payEntity: AliPayEntity) {
        repository.payWithAli(order, payEntity, activity)
    }

    private val _requestWechatPayAction = MutableLiveData<Event<Pair<OrderEntity, WechatPayEntity>>>()
    val requestWechatPayAction: LiveData<Event<Pair<OrderEntity, WechatPayEntity>>> = _requestWechatPayAction
    fun preOrderWithWechat(order: OrderEntity) {
        repository.preOrderWithWechat(order)
            .compose(singleToMain())
            .subscribe(object : BiResponse<BaseEntity<WechatPayEntity>>() {
                override fun onSuccess(data: BaseEntity<WechatPayEntity>) {
                    val payEntity = data.data
                    if (payEntity != null) {
                        _requestWechatPayAction.value = Event(order to payEntity)
                    }
                }

                override fun onFailure(exception: Exception) {
                    super.onFailure(exception)
                    handlePreOrderError(exception)
                }
            }).let(compositeDisposable::add)
    }

    fun sendWechatPayRequest(order: OrderEntity, payEntity: WechatPayEntity) {
        repository.sendWechatPayRequest(order, payEntity)
    }

    private fun handlePreOrderError(exception: Exception) {
        if (exception is HttpException) {
            val errorEntity = exception.response().errorBody()?.string()?.toObject<ErrorEntity>()
            val code = errorEntity?.code ?: 0
            val toast = errorEntity?.toast
            when (code) {
                ERROR_CODE_UNVERIFIED -> UserVerifyState.UnVerified(toast)
                ERROR_CODE_MINORS -> UserVerifyState.Minors(toast)
                ERROR_CODE_VERIFYING -> UserVerifyState.Verifying(toast)
                else -> null
            }?.let {
                _showUserVerifyDialog.value = Event(it)
            }
        }
    }

    @SuppressLint("CheckResult")
    fun insertAcctGameInfo(acctGameInfo: AcctGameInfo) {
        if (acctGameInfo.zoneInfo.id == -1 && acctGameInfo.zoneInfo.cnName.isNullOrBlank()) {
            // 避免数据库存入无效数据
            return
        }
        EventBus.getDefault().post(EBStartupAcceleration(acctGameInfo))
        AccelerationDataBase.instance.accelerationDao()
            .upsertAcctGameInfo(acctGameInfo)
            .subscribeOn(Schedulers.io())
            .subscribe({}, {})
    }

    fun recordAcctGameInfo(game: GameEntity, zoneInfo: AcctGameInfo.ZoneInfo, hasMultiZone: Boolean) {
        // 将加速记录提交到服务端(我的资产页面需要显示)
        repository.recordAcctGameInfo(game.id, zoneInfo, hasMultiZone)
        // 将加速记录保存在本地(最近在玩需要使用)
        repository.saveAcctRecordToLocal(game, zoneInfo, hasMultiZone)
    }

    fun rechargeTrial(userId: String): Single<BaseEntity<TrialEntity>> = repository.rechargeTrial(userId)

    /**
     * 上传奇游错误日志
     * 由于错误日志可能没那么快生成，这里等待3s之后，在上报
     */
    @SuppressLint("CheckResult")
    fun unloadAcceleratorErrorLog(game: GameEntity) {
        Single.just(Unit)
            .delay(3, TimeUnit.SECONDS)
            .flatMap {
                repository.getAcceleratorErrorLog()
            }.flatMap {
                val packageUtilsConfig = TheRouter.get(IPackageUtilsProvider::class.java)
                val appProvider = TheRouter.get(IAppProvider::class.java)

                val body = hashMapOf(
                    "ghversion" to packageUtilsConfig?.getGhVersionName(),
                    "channel" to appProvider?.getChannel(),
                    "type" to Build.MODEL,
                    "sdk" to Build.VERSION.SDK_INT.toString(),
                    "version" to Build.VERSION.RELEASE,
                    "source" to R.string.app_name.toResString(),
                    "jnfj" to getBase64EncodedIMEI(),
                    "from" to "",
                    "game_id" to game.id,
                    "manufacturer" to Build.MANUFACTURER,
                    "rom" to MetaUtil.getRom().name + " " + MetaUtil.getRom().versionName,
                    "suggestion_type" to "加速器失败",
                    "message" to "加速失败, 游戏ID: ${game.id}, 游戏名: ${game.name ?: ""}",
                    "log" to it
                ).toRequestBody()

                repository.uploadAcceleratorErrorLog(body)
            }.subscribe({}, {})
    }

    fun loadVipStatus() = repository.loadVipStatus()


    fun onClear() {
        compositeDisposable.clear()
    }

    sealed class UserVerifyState(val toast: String?) {

        class UnVerified(toast: String?) : UserVerifyState(toast)

        class Minors(toast: String?) : UserVerifyState(toast)

        class Verifying(toast: String?) : UserVerifyState(toast)

        companion object {
            const val ERROR_CODE_UNVERIFIED = 403129
            const val ERROR_CODE_MINORS = 403128
            const val ERROR_CODE_VERIFYING = 403130
        }
    }
}