package com.iscs.bozzys.api

import com.google.gson.Gson
import com.google.gson.JsonObject
import com.iscs.bozzys.utils.network.Request
import java.net.UnknownHostException

object ApiRequest {

    // 创建请求对象
    private val api: ApiService by lazy { Request.getRetrofit().create(ApiService::class.java) }

    /**
     * 处理请求头参数
     *
     * @param headers 用于自定义请求头参数
     * @return 默认请求头参数，如果用户携带请求头参数与默认一致，优先使用用户携带
     */
    private fun getUserHeaders(headers: Map<String, String>): Map<String, String> {
        val map = HashMap<String, String>()
        map.putAll(headers)
        return map
    }

    /**
     * 处理各种异常
     *
     * @param e 异常总类
     *
     * @return 封装对外出去的异常总响应
     */
    private fun <T : Response> dealException(e: Exception, rsp: T): Exception {
        if (rsp.code == 0) {
            rsp.code = 404
            rsp.msg = "Network error"
            when {
                e is UnknownHostException -> {
                    rsp.code = 500
                    rsp.msg = e.message ?: "Network error"
                }
            }
        }
        return Exception(Gson().toJson(rsp))
    }

    /**
     * 基础请求封装
     */
    private suspend fun <T : Response> requestApi(apiFun: suspend () -> T): Result<T> {
        return try {
            val rsp = apiFun()
            if (rsp.code == 200) {
                Result.success(rsp)
            } else {
                Result.failure(dealException(Exception(rsp.msg), rsp))
            }
        } catch (e: Exception) {
            Result.failure(dealException(e, Response()))
        }
    }

    /**
     * 获取响应数据结构
     */
    fun Throwable.getResponse(): Response {
        val msg = this.message ?: "{\"code\":404,\"msg\":\"Network error\"}"
        val json = if (msg.startsWith("{") && msg.endsWith("}")) msg else "{\"code\":404,\"msg\":\"Network error\"}"
        val t = Response()
        return Gson().fromJson(json, t::class.java)
    }

    /**
     * 登录
     *
     * @param username  用户名
     * @param pwd       密码
     */
    suspend fun login(username: String, pwd: String): Result<LoginRsp> {
        val params = JsonObject()
        params.addProperty("username", username)
        params.addProperty("password", pwd)
        return requestApi { api.login(getUserHeaders(emptyMap()), params) }
    }

}