package com.halo.assistant.accelerator.repository

import android.annotation.SuppressLint
import android.app.Activity
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.singleToMain
import com.gh.gamecenter.common.utils.toRequestBody
import com.gh.gamecenter.core.provider.IAcceleratorProvider
import com.gh.gamecenter.core.provider.IAliPayProvider
import com.gh.gamecenter.core.provider.IWechatPayProvider
import com.gh.gamecenter.feature.entity.*
import com.gh.gamecenter.feature.eventbus.EBPayState
import com.gh.gamecenter.gamedetail.accelerator.AccelerationDao
import com.gh.gamecenter.gamedetail.accelerator.AccelerationDataBase
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.retrofit.service.ApiService
import com.halo.assistant.accelerator.AccelerationUseCase
import com.therouter.TheRouter
import io.reactivex.Flowable
import io.reactivex.Observable
import io.reactivex.Single
import io.reactivex.schedulers.Schedulers
import okhttp3.RequestBody
import okhttp3.ResponseBody
import org.greenrobot.eventbus.EventBus
import java.util.concurrent.TimeUnit

/**
 * 加速器相关的操作，统一放在这里
 */
class AccelerationRepository private constructor(
    private val newApi: ApiService,
    private val api: ApiService,
    private val accelerationDao: AccelerationDao,
) {

    fun preOrderWithAli(order: OrderEntity): Single<AliPayEntity> {
        val userId = UserManager.getInstance().userId
        return newApi.preOrderWithAli(order.goodId, userId, order.type)
            .map {
                it.data
            }
    }

    @SuppressLint("CheckResult")
    fun payWithAli(order: OrderEntity, payEntity: AliPayEntity, activity: Activity) {
        TheRouter.get(IAliPayProvider::class.java)
            ?.sendRequest(activity, payEntity.orderStr)
            ?.flatMap {
                if (it == 0) {
                    // 需要后端确认支付结果
                    getAlipayResult(payEntity.orderNo, order.type)
                } else {
                    Single.just(it)
                }
            }
            ?.compose(singleToMain())
            ?.subscribe({
                val (payState, result) = when (it) {
                    0 -> EBPayState.PaySuccess to RECHARGE_RESULT_SUCCESS
                    1 -> EBPayState.PayCancel to RECHARGE_RESULT_CANCEL
                    else -> EBPayState.PayFail to RECHARGE_RESULT_FAILURE
                }
                if (payState is EBPayState.PaySuccess) {
                    AcceleratorDataHolder.instance.handleUserRechargeSuccess(order)
                }
                SensorsBridge.trackMemberRechargeResult(
                    PAYMENT_TYPE_ALIPAY,
                    order.setMenuName,
                    order.paymentAmount,
                    result
                )
                EventBus.getDefault().post(payState)
            }, {
                // 支付失败
                EventBus.getDefault().post(EBPayState.PayFail)
            })
    }

    private fun getAlipayResult(orderNo: String, type: String): Single<Int> {
        val userId = UserManager.getInstance().userId
        return RetrofitManager.getInstance().newApi
            .getAliPayResult(orderNo, userId, type)
            .retryWhen { errors ->
                errors.zipWith(Flowable.range(1, 3)) { error, attempt ->
                    if (attempt <= 3) {
                        attempt
                    } else {
                        throw error
                    }
                }.flatMap {
                    Flowable.timer(1, TimeUnit.SECONDS)
                }
            }.map {
                if (it.data != null) 0 else 2
            }
    }

    fun preOrderWithWechat(order: OrderEntity): Single<BaseEntity<WechatPayEntity>> {
        val userId = UserManager.getInstance().userId
        return newApi.preOrderWithWechat(order.goodId, userId, order.type)
    }

    fun sendWechatPayRequest(order: OrderEntity, payEntity: WechatPayEntity) {
        TheRouter.get(IWechatPayProvider::class.java)?.payRequest(order, payEntity)
    }

    fun getWechatPayResult(orderNo: String): Single<Boolean> {
        val userId = UserManager.getInstance().userId
        return RetrofitManager.getInstance().newApi
            .getWechatPayResult(orderNo, userId, VIP_TYPE)
            .retryWhen { errors ->
                errors.zipWith(Flowable.range(1, 3)) { error, attempt ->
                    if (attempt <= 3) {
                        attempt
                    } else {
                        throw error
                    }
                }.flatMap {
                    Flowable.timer(1, TimeUnit.SECONDS)
                }
            }.map {
                it.data != null
            }
    }

    @SuppressLint("CheckResult")
    fun recordAcctGameInfo(gameId: String, zoneInfo: AcctGameInfo.ZoneInfo, hasMultiZone: Boolean) {
        val userId = UserManager.getInstance().userId
        val body =
            hashMapOf(
                "game_id" to gameId,
                "service_area_id" to zoneInfo.id,
                "service_area" to zoneInfo.cnName,
                "is_more_service_area" to hasMultiZone
            ).toRequestBody()
        RetrofitManager.getInstance().newApi
            .recordAcctGameInfo(userId, VIP_TYPE, body)
            .subscribeOn(Schedulers.io())
            .subscribe({}, {})
    }

    @SuppressLint("CheckResult")
    fun saveAcctRecordToLocal(game: GameEntity, zoneInfo: AcctGameInfo.ZoneInfo, hasMultiZone: Boolean) {
        val record =
            AcctRecord(game.id, game, zoneInfo, hasMultiZone, System.currentTimeMillis())
        accelerationDao.upsertAcctRecord(record)
            .subscribeOn(Schedulers.io())
            .subscribe({}, {})

    }

    fun rechargeTrial(userId: String): Single<BaseEntity<TrialEntity>> =
        newApi.rechargeTrial(userId, VIP_TYPE)

    fun getAcceleratorErrorLog(): Single<String> = Single.create { emitter ->
        val logFileStorageList = TheRouter.get(IAcceleratorProvider::class.java)?.getAccLogFileStorageList()
        val content = buildString {
            logFileStorageList?.forEachIndexed { index, file ->
                if (index > 0) {
                    append("\n")
                }
                when {
                    !file.exists() -> {
                        appendLine("\n---------------\n")
                    }

                    !file.canRead() -> {
                        appendLine("文件无法读取")
                    }

                    else -> {
                        file.bufferedReader().use { reader ->
                            reader.lineSequence().forEach { line ->
                                appendLine(line)
                            }
                        }
                    }
                }
            }
        }
        if (content.isBlank()) {
            emitter.onSuccess("log is empty")
        } else {
            emitter.onSuccess(content)
        }
    }

    fun uploadAcceleratorErrorLog(body: RequestBody): Single<ResponseBody> =
        api.uploadAcceleratorErrorLog(body)

    fun getLastAcctGameInfoObservable(gameId: String): Observable<List<AcctGameInfo>> =
        accelerationDao.getAcctGameInfoByGameIdObservable(gameId)


    fun getHasAnyAcctRecordObservable() = accelerationDao.getAnyAcctRecordObservable()

    fun loadVipStatus(): Single<BaseEntity<VipEntity>> =
        com.gh.gamecenter.login.retrofit.RetrofitManager.getInstance().newApi.getVipStatus(
            UserManager.getInstance().userId,
            "gjonline_vip",
            true
        )

    companion object {
        private const val VIP_TYPE = "gjonline_vip"
        const val RECHARGE_RESULT_SUCCESS = "充值成功"
        private const val RECHARGE_RESULT_CANCEL = "充值取消"
        const val RECHARGE_RESULT_FAILURE = "充值失败"
        const val PAYMENT_TYPE_ALIPAY = "支付宝"
        const val PAYMENT_TYPE_WECHAT = "微信"

        fun newInstance() = AccelerationRepository(
            RetrofitManager.getInstance().newApi,
            RetrofitManager.getInstance().api,
            AccelerationDataBase.instance.accelerationDao()
        )
    }
}