package com.iscs.bozzys.api

import com.google.gson.Gson
import com.google.gson.JsonObject
import com.iscs.bozzys.api.ApiRequest.refreshToken
import com.iscs.bozzys.event.AuthEventBus
import com.iscs.bozzys.utils.Storage
import com.iscs.bozzys.utils.Storage.saveRefreshToken
import com.iscs.bozzys.utils.Storage.saveToken
import com.iscs.bozzys.utils.network.Request
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.MultipartBody
import okhttp3.RequestBody.Companion.asRequestBody
import java.io.File
import java.net.UnknownHostException

object ApiRequest {

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

    /**
     * 处理请求头参数
     *
     * @param headers 用于自定义请求头参数
     * @return 默认请求头参数，如果用户携带请求头参数与默认一致，优先使用用户携带
     */
    fun getUserHeaders(headers: Map<String, String> = emptyMap()): Map<String, String> {
        val map = HashMap<String, String>()
        map["Tenant-Id"] = Storage.readTenantId()
        map["Authorization"] = "Bearer ${Storage.readToken()}"
        map.putAll(headers)
        return map
    }

    /**
     * 处理各种异常
     *
     * @param e 异常总类
     *
     * @return 封装对外出去的异常总响应
     */
    private fun <T> dealException(e: Exception, rsp: Response<T>): Exception {
        rsp.msg = e.message?.ifEmpty { "Network error" } ?: "Network error"
        when {
            e is UnknownHostException -> {
                rsp.code = 500
                rsp.msg = "Network error"
            }
        }
        // 未登录/或者授权过期，这里要进行退出登录操作
        if (rsp.code == 401) {
            // 这里执行退出登录操作
            "".saveToken()
            Storage.saveLogin(false)
            AuthEventBus.onTokenExpired()
        }
        return Exception(Gson().toJson(rsp))
    }

    /**
     * 基础请求封装
     */
    private suspend fun <T> requestApi(retryCount: Int = 3, apiFun: suspend () -> Response<T>): Result<Response<T>> {
        return try {
            val rsp = apiFun()
            // 请求成功
            if (rsp.code.isCodeOk()) {
                Result.success(rsp)
            } else if (rsp.code == 401) {
                // 授权过期，需要重新授权
                val refreshRsp = refreshToken(Storage.readRefreshToken()).getOrNull()
                if ((refreshRsp?.code ?: -1).isCodeOk() && retryCount > 0) {
                    refreshRsp?.data?.accessToken.saveToken()
                    refreshRsp?.data?.refreshToken.saveRefreshToken()
                    // 刷新完成执行一次请求并返回数据
                    requestApi(retryCount - 1, apiFun)
                } else {
                    Result.failure(dealException(Exception(rsp.msg), rsp))
                }
            } else {
                Result.failure(dealException(Exception(rsp.msg), rsp))
            }
        } catch (e: Exception) {
            Result.failure(dealException(e, Response<T>()))
        }
    }

    /**
     * 响应码是否有效
     */
    fun Int.isCodeOk(): Boolean {
        return listOf(0, 200).contains(this)
    }

    /**
     * 获取响应数据结构
     */
    fun <T> Throwable.getResponse(): Response<T> {
        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<T>()
        return Gson().fromJson(json, t::class.java)
    }

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

    /**
     * 退出登录操作
     */
    suspend fun logout(): Result<Response<Boolean>> {
        return requestApi { api.logout() }
    }

    /**
     * 刷新Token操作
     *
     * @param refreshToken
     */
    suspend fun refreshToken(refreshToken: String): Result<Response<ResponseLogin>> {
        return requestApi { api.refreshToken(refreshToken) }
    }

    /**
     * 获取用户权限信息
     */
    suspend fun getUserPermission(): Result<Response<ResponsePermission>> {
        return requestApi { api.getUserPermission() }
    }

    /**
     * 查询作业列表数据
     *
     * @param params
     */
    suspend fun getJobs(params: MutableMap<String, Any>): Result<Response<ResponsePage<Job>>> {
        return requestApi { api.getJobs(params) }
    }

    /**
     * 查询作业列表数据
     *
     * @param params
     */
    suspend fun getTasks(params: MutableMap<String, Any>): Result<Response<ResponsePage<Task>>> {
        return requestApi { api.getTasks(params) }
    }

    /**
     * 查询首页任务统计
     */
    suspend fun getTaskStatistics(): Result<Response<TaskStatistics>> {
        return requestApi { api.getTaskStatistics() }
    }

    /**
     * 通过节点Id获取任务信息
     *
     * @param nodeId    节点Id
     */
    suspend fun getTaskInfoByNodeId(nodeId: Int): Result<Response<Node>> {
        return requestApi { api.getTaskInfo(mutableMapOf("nodeId" to nodeId)) }
    }

    /**
     * 获取任务表单信息
     *
     * @param formId    表单id
     */
    suspend fun getTaskFormInfoByFormId(formId: Int): Result<Response<TaskFormInfo>> {
        return requestApi { api.getTaskFormInfo(mutableMapOf("id" to formId)) }
    }

    /**
     * 获取字典数据
     *
     * @param params 请求数据
     */
    suspend fun getDictData(params: MutableMap<String, Any>): Result<Response<ResponsePage<Dict>>> {
        return requestApi { api.getDictData(params) }
    }

    /**
     * 获取sop流程模板列表
     *
     * @param params
     */
    suspend fun getSopList(params: MutableMap<String, Any>): Result<Response<ResponsePage<Sop>>> {
        return requestApi { api.getSopList(params) }
    }

    /**
     * 创建或编辑作业
     *
     * @param params 请求参数
     */
    suspend fun createOrEditJob(id: Int, params: MutableMap<String, Any>): Result<Response<Any>> {
        return requestApi { if (id <= 0) api.createJob(params) else api.editJob(params.apply { put("id", id) }) }
    }

    /**
     * 发布作业
     *
     * @param params 请求参数
     */
    suspend fun pushJob(params: MutableMap<String, Any>): Result<Response<Boolean>> {
        return requestApi { api.pushJob(params) }
    }

    /**
     * 查询作业详情
     *
     * @param id    作业详情
     */
    suspend fun getJobById(id: Int): Result<Response<Job>> {
        return requestApi { api.getJobById(id) }
    }

    /**
     * 更新节点信息
     *
     * @param params
     */
    suspend fun updateJobNodeInfo(params: MutableMap<String, Any?>): Result<Response<Boolean>> {
        return requestApi { api.updateJobNodeInfo(params) }
    }

    /**
     * 更新节点完成情况
     *
     * @param params
     */
    suspend fun updateJobNodeApproval(params: MutableMap<String, Any>): Result<Response<Boolean>> {
        return requestApi { api.updateJobNodeApproval(params) }
    }

    /**
     * 获取用户列表，通过角色类型
     *
     * @param roleCode 角色类型
     */
    suspend fun getUsersByRoleCode(roleCode: String): Result<Response<List<User>>> {
        return requestApi { api.getUsersByRoleCode(roleCode) }
    }

    /**
     * 获取管理表单列表
     */
    suspend fun getBpmFormList(params: MutableMap<String, Any>): Result<Response<ResponsePage<TaskFormInfo>>> {
        return requestApi { api.getBpmFormList(params) }
    }

    /**
     * 获取点位列表
     */
    suspend fun getIsolationPointList(params: MutableMap<String, Any>): Result<Response<ResponsePage<IsolationPoint>>> {
        return requestApi { api.getIsolationPointList(params) }
    }

    /**
     * 获取所有消息
     */
    suspend fun getMessages(params: MutableMap<String, Any>): Result<Response<ResponsePage<Message>>> {
        return requestApi { api.getMessages(params) }
    }

    /**
     * 获取未读消息数量
     */
    suspend fun getMessagesUnread(): Result<Response<Int>> {
        return requestApi { api.getMessagesUnread() }
    }

    /**
     * 更新消息为已读
     *
     * @param params 请求参数 如果什么参数都不传，默认标记所有消息为已读
     */
    suspend fun updateMessageRead(params: MutableMap<String, Any>): Result<Response<Boolean>> {
        return requestApi { if (params.isNotEmpty()) api.updateMessageRead(params) else api.updateMessageAllRead() }
    }

    /**
     * 上传文件
     *
     * @param file  上传的文件
     * @param type  文件类型
     */
    suspend fun uploadFile(file: File, type: String = "image/*"): Result<Response<String>> {
        val part = MultipartBody.Part.createFormData("file", file.name, file.asRequestBody(type.toMediaType()))
        return requestApi { api.uploadFile(part) }
    }

    /**
     * 更新用户信息
     *
     * @param params
     */
    suspend fun updateUserProfile(params: MutableMap<String, Any>): Result<Response<Boolean>> {
        return requestApi { api.updateUserProfile(params) }
    }

    /**
     * 更新消息推送状态
     *
     * @param deviceId  消息推送当前设备id
     * @param isRemove  是否移除消息推送
     */
    suspend fun updateMessagePushStatus(deviceId: String, isRemove: Boolean): Result<Response<Boolean>> {
        return requestApi { api.updateMessagePushStatus(mutableMapOf("type" to (if (isRemove) 1 else 0), "deviceId" to deviceId)) }
    }

    /**
     * 获取用户人脸数据
     *
     * @param params
     */
    suspend fun getUserCharacteristicList(params: MutableMap<String, Any>): Result<Response<ResponsePage<UserCharacteristic>>> {
        return requestApi { api.getUserCharacteristicList(params) }
    }

    /**
     * 删除用户特征数据
     *
     * @param params ids=
     */
    suspend fun deleteUserCharacteristic(params: MutableMap<String, Any>): Result<Response<Boolean>> {
        return requestApi { api.deleteUserCharacteristic(params) }
    }

    /**
     * 上传用户人像信息
     *
     * @param username  用户名
     * @param file      上传的文件
     * @param type      上传的数据类型
     */
    suspend fun uploadUserFace(username: String, file: File, type: String = "image"): Result<Response<UserCharacteristic>> {
        val part = MultipartBody.Part.createFormData("file", file.name, file.asRequestBody("$type/*".toMediaType()))
        return requestApi { api.uploadUserFace(username, part) }
    }

}