package com.yidian.bcommon.http

import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.yidian.bcommon.app.YdBaseApplication
import com.yidian.bcommon.constant.AppConfig
import com.yidian.bcommon.constant.RunConfig
import com.yidian.bcommon.sdk.BCommonManager
import com.yidian.bcommon.utils.NetWorkUtils
import com.yidian.yac.ftdevicefinger.core.FtDeviceFingerManager
import timber.log.Timber
import java.lang.reflect.Type

class HttpParamsUtils {
  companion object {

    private val gson by lazy { Gson() }

    fun getPublicParamsMap(timeStamp: Long): HashMap<String, String> {
      val paramsMap = hashMapOf(
        "appid" to BCommonManager.getAppId(),
        "cv" to AppConfig.cv,
        "version" to RunConfig.SERVICE_VERSION,
        "distribution" to AppConfig.distribution,
        "net" to NetWorkUtils.getNetWorkType(YdBaseApplication.context),
        "platform" to AppConfig.platform,
        "device_finger" to getDeviceFinger(),
        "reqid" to getRequestId(timeStamp)
      )
      Timber.tag(BCommonManager.TAG_HTTP).d("request public params: ${gson.toJson(paramsMap)}")
      return paramsMap
    }

    fun getPrivateParamsMap(paramsMap: HashMap<String, String?>, timeStamp: Long): HashMap<String, String?> {
      return if (RunConfig.IS_ENCRYPT) {
        paramsMap["secret"] = getSignString(getRequestId(timeStamp), timeStamp)
        paramsMap["ts"] = timeStamp.toString()
        // C端身份请求加uid
        BCommonManager.getUid()?.let { paramsMap["user_id"] = it }
        Timber.tag(BCommonManager.TAG_HTTP).d("request private params: ${gson.toJson(paramsMap)}")
        hashMapOf("tok" to BCommonManager.getEncryptIml().rsaEncrypt(gson.toJson(paramsMap)))
      } else {
        // C端身份请求加uid
        BCommonManager.getUid()?.let { paramsMap["user_id"] = it }
        Timber.tag(BCommonManager.TAG_HTTP).d("request private params: ${gson.toJson(paramsMap)}")
        paramsMap
      }
    }

    fun <T> rsaDecryptResult(res: HttpResult<Any?>, type: Type): HttpResult<T> {
      val rsaResult = res.result
      val decodeResult = HttpResult<T>()
      decodeResult.code = res.code
      decodeResult.reason = res.reason
      decodeResult.status = res.status
      if (rsaResult != null) {
        try {// 捕获数据解析异常, 防止T内部的字端解析失败
          if (RunConfig.IS_ENCRYPT) {
            val result = BCommonManager.getEncryptIml().rsaDecrypt(rsaResult as String)
            Timber.tag(BCommonManager.TAG_HTTP).d("response result: $result")
            val decryptResult = gson.fromJson<HttpDecryptResult<T>>(result, object : TypeToken<HttpDecryptResult<T>>() {}.type)
            val verify = BCommonManager.getEncryptIml().verifySign(decryptResult.reqid + decryptResult.ts, decryptResult.secret)
            return if (verify) {
              Timber.tag(BCommonManager.TAG_HTTP).d("verify success")
              val resultJson = gson.toJson(decryptResult.data)
              decodeResult.result = gson.fromJson<T>(resultJson, type)
              decodeResult
            } else {
              Timber.tag(BCommonManager.TAG_HTTP).d("verify failure")
              decodeResult
            }
          } else {
            val resultJson = gson.toJson(rsaResult)
            Timber.tag(BCommonManager.TAG_HTTP).d("response result: $resultJson")
            decodeResult.result = gson.fromJson<T>(resultJson, type)
            return decodeResult
          }
        } catch (e: Exception) {
          e.printStackTrace()
        }
      }
      return decodeResult
    }

    private fun getDeviceFinger(): String {
      return FtDeviceFingerManager.getDeviceFinger() ?: ""
    }

    private fun getRequestId(timeStamp: Long): String {
      return StringBuilder().append(BCommonManager.getAppId()).append('_').append(getDeviceFinger()).append('_').append(timeStamp)
        .toString()
    }

    private fun getSignString(reqId: String, timeStamp: Long): String {
      return BCommonManager.getEncryptIml().sign(StringBuilder().append(reqId).append(timeStamp).toString())
    }
  }
}
