package com.gh.gamecenter.common.retrofit

import android.content.Context
import android.os.Build
import android.text.TextUtils
import com.alibaba.android.arouter.launcher.ARouter
import com.gh.gamecenter.common.HaloApp
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.exposure.meta.MetaUtil
import com.gh.gamecenter.common.utils.DeviceUtils
import com.gh.gamecenter.core.provider.IBuildConfigProvider
import com.gh.gamecenter.core.provider.IUserManagerProvider
import com.gh.gamecenter.core.utils.MtaHelper
import com.lightgame.config.CommonDebug
import okhttp3.*
import okhttp3.Response
import java.io.IOException

/**
 *
 * 重试connection，需要add as interceptor而不是network interceptor，可以多次执行proceed
 *
 * @author CsHeng
 * *
 * @Date 21/07/2017
 * *
 * @Time 3:22 PM
 */
class OkHttpRetryInterceptor constructor(context: Context, val maxRetryCount: Int = 2) : Interceptor {

    val mContext = context

    @Throws(IOException::class)
    override fun intercept(chain: Interceptor.Chain): Response {

//        if (CommonDebug.IS_DEBUG) {
//            CommonDebug.logMethodWithParams(this, chain.request().url());
//        }

        var request = chain.request()

        var response: Response? = doRequest(chain, request)

        var tryCount = 0
        val token = chain.request().header("token")
        val url = request.url().toString()
        while ((response == null || (token != null && response.code() == 401 && (!url.contains("refresh")))) // 排除刷新token接口，避免进入死循环
            && ++tryCount <= maxRetryCount
        ) {
            if (CommonDebug.IS_DEBUG) {
                CommonDebug.logMethodWithParams(this, "Retrying ${request.url()} for $tryCount")
            }

            if (url.contains("users:validate") && !TextUtils.isEmpty(request.header("retry"))
                || url.contains("/logout")
            ) { // 过滤在注销/当前类请求的 userinfo
                tryCount = maxRetryCount + 1
                break
            }

            if (response != null && token != null) { // TOKEN 过期处理
                val userManagerProvider =
                    ARouter.getInstance().build(RouteConsts.provider.userManager).navigation() as? IUserManagerProvider
                userManagerProvider?.refreshToken(token, {
                    val newBuilder = request.newBuilder()
                    newBuilder.header("TOKEN", userManagerProvider.getToken())
                    request = newBuilder.build()
                    response = doRequest(chain, request)
                }, { e ->
                    tryCount = maxRetryCount + 1 // 只要token刷新异常直接主动退出登录
                    if (e != null && e.isNotEmpty()) {
                        response =
                            response?.newBuilder()?.body(ResponseBody.create(MediaType.parse("application/json"), e))
                                ?.build()
                    }
                })
            } else { //　网络错误处理
                response = doRequest(chain, request)
            }
        }
        val buildConfig =
            ARouter.getInstance().build(RouteConsts.provider.buildConfig).navigation() as IBuildConfigProvider
        // 上报网络错误，过滤 404 以及非用户可感知的请求
        val api = pathSegmentsToString(request.url().pathSegments())
        if (tryCount == maxRetryCount + 1
            && (response == null || response?.code() != 404)
            && isUserAwareApi(api)
        ) {
            MtaHelper.onEvent(
                "网络错误",
                "访问接口", api,
                "网络状态", DeviceUtils.getNetwork(HaloApp.getInstance()),
                "光环版本", buildConfig.getVersionName(),
                "网络状态", DeviceUtils.getNetwork(HaloApp.getInstance()),
                "JNFJ", MetaUtil.getBase64EncodedIMEI(),
                "机型", Build.MODEL,
                "厂商", Build.MANUFACTURER,
                "Android版本", Build.VERSION.RELEASE
            )
        }

        // after retries still fail, so we throw IOException as expected
        if (response == null) {
            throw IOException("OkHttpRetryInterceptor response is null")
        }

        return response as Response
    }

    private fun doRequest(chain: Interceptor.Chain, request: Request): Response? {
        var response: Response? = null
        try {
            response = chain.proceed(request)
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return response
    }

    private fun pathSegmentsToString(pathSegments: List<String>? = null): String {
        if (pathSegments == null) return ""

        val out = StringBuilder()
        var i = 0
        val size = pathSegments.size
        while (i < size) {
            out.append('/')
            out.append(pathSegments[i])
            i++
        }
        return out.toString()
    }

    /**
     * 判断 API 是否与用户感知相关
     */
    private fun isUserAwareApi(apiPath: String?): Boolean {
        if (apiPath == null) return false

        return !(apiPath.contains("/collection/upload")
                || apiPath.contains("/api/v1d0/log")
                || apiPath.contains("/news/stat")
                || apiPath.contains("/time")
                || apiPath.contains("//"))
    }
}
