package com.example.defenseapplication.utils

import android.annotation.SuppressLint
import android.util.Log
import com.example.defenseapplication.bean.BaseInfo
import com.google.gson.Gson
import com.google.gson.JsonParser
import okhttp3.Interceptor
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.Protocol
import okhttp3.Request
import okhttp3.Response
import okhttp3.ResponseBody.Companion.toResponseBody
import okhttp3.logging.HttpLoggingInterceptor
import java.nio.charset.Charset

/**
 * 网络配置与拦截器
 */
object ApiConfig {

    private const val TAG = "ApiConfig"
    private val gson = Gson()
    @Volatile
    public var authToken: String = ""

    fun updateAuthToken(token: String) {
        authToken = token
    }

    fun hasAuthToken(): Boolean {
        return authToken.isNotBlank()
    }

    /**
     * 获取日志拦截器
     * 完善：针对上传文件等二进制流时，降低日志级别为 HEADERS，避免输出大量字节数据
     */
    fun getLoggingInterceptor(): Interceptor {
        val logger = HttpLoggingInterceptor.Logger { message ->
            Log.d(TAG, message)
        }

        return Interceptor { chain ->
            val request = chain.request()
            if (/*!BuildConfig.DEBUG*/false) {
                return@Interceptor chain.proceed(request)
            }

            // 1. 判断请求是否为二进制或多部分表单上传
            val requestBody = request.body
            val requestContentType = requestBody?.contentType()?.toString()?.lowercase() ?: ""
            val isBinaryRequest = requestContentType.contains("multipart") ||
                    requestContentType.contains("octet-stream") ||
                    requestContentType.contains("image") ||
                    requestContentType.contains("video") ||
                    requestContentType.contains("audio")

            // 2. 动态设置日志级别
            val loggingInterceptor = HttpLoggingInterceptor(logger).apply {
                level = if (isBinaryRequest) {
                    // 二进制上传只打印 Header，防止 Body 字节码干扰
                    HttpLoggingInterceptor.Level.HEADERS
                } else {
                    HttpLoggingInterceptor.Level.BODY
                }
            }

            loggingInterceptor.intercept(chain)
        }
    }

    /**
     * 统一拦截器：处理异常、Token失效、数据格式化
     */
    @SuppressLint("CheckResult")
    fun getUnifiedInterceptor() = Interceptor { chain ->
        val request = chain.request()

        // --- 1. 发起请求并捕获底层网络异常 (无网络、超时等) ---
        val response = try {
            chain.proceed(request)
        } catch (e: Exception) {
            Log.e(TAG, "Network Error: ", e)
            return@Interceptor buildFakeErrorResponse(request, getErrorMessage(e))
        }

        // --- 2. 检查响应是否为大文件或二进制流 (直接放行，避免 OOM 和日志污染) ---
        val responseBody = response.body ?: return@Interceptor response
        val contentType = responseBody.contentType()?.toString()?.lowercase() ?: ""
        if (contentType.contains("octet-stream") || contentType.contains("video") ||
            contentType.contains("audio") || contentType.contains("image") ||
            responseBody.contentLength() > 1024 * 1024
        ) {
            return@Interceptor response
        }

        // --- 3. 读取 JSON 数据进行统一处理 ---
        try {
            val source = responseBody.source()
            source.request(Long.MAX_VALUE)
            val responseString = source.buffer.clone().readString(Charset.defaultCharset())

            if (!responseString.trim().startsWith("{")) {
                if (response.code == 500) {
                    return@Interceptor buildFakeErrorResponse(request, "服务器内部错误")
                }
                return@Interceptor response
            }

            val jsonElement = JsonParser().parse(responseString)
            val jsonObject = jsonElement.asJsonObject


            val httpCode = response.code
            val businessCode = if (jsonObject.has("code")) jsonObject.get("code").asInt else 0

            if (httpCode == 401 || httpCode == 424 || businessCode == 401) {
                clearUserLoginInfo()
                val msg = if (jsonObject.has("msg")) jsonObject.get("msg").asString else "登录已过期，请重新登录"
                return@Interceptor buildFakeErrorResponse(request, msg, code = if (businessCode != 0) businessCode else httpCode)
            }

            if (httpCode == 500) {
                return@Interceptor buildFakeErrorResponse(request, "服务器内部错误(500)")
            }

            return@Interceptor response

        } catch (e: Exception) {
            Log.e(TAG, "JSON Parse Error: ", e)
            return@Interceptor response
        }
    }

    /**
     * 构建一个伪装成 HTTP 200 的统一错误响应体
     */
    private fun buildFakeErrorResponse(request: Request, msg: String, code: Int = 1): Response {
        val baseInfo = BaseInfo(
            message = msg,
            code = code,
            data = null,
        )
        val json = gson.toJson(baseInfo)
        val responseBody = json.toResponseBody("application/json; charset=utf-8".toMediaTypeOrNull())

        return Response.Builder()
            .request(request)
            .protocol(Protocol.HTTP_1_1)
            .code(200)
            .message("OK")
            .body(responseBody)
            .build()
    }

    private fun getErrorMessage(e: Exception): String {
        return "网络请求失败，请检查网络设置"
    }

    // 统一请求头拦截器
    fun createHeadersInterceptor() = Interceptor { chain ->
        val requestBuilder = chain.request().newBuilder()
        val token = authToken
        
        // 添加必要的请求头
        requestBuilder.header("clientid", "428a8310cd442757ae699df5d894f051")
        requestBuilder.header("content-language", LanguageUtil.getLanguageHeaderValue())
        
        // 如果有 token，添加 Authorization 头
        if (token.isNotBlank()) {
            Log.d("ApiConfig", buildAuthorizationValue(token))
            requestBuilder.header("Authorization", buildAuthorizationValue(token))
        }

        chain.proceed(requestBuilder.build())
    }

    private fun buildAuthorizationValue(token: String): String {
        return if (token.startsWith("Bearer ")) token else "Bearer $token"
    }

    private fun clearUserLoginInfo() {
        try {
            authToken = ""
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}