package com.iscs.bozzys.utils.network

import android.annotation.SuppressLint
import com.iscs.bozzys.utils.DateUtil.format
import com.iscs.bozzys.utils.LogUtil
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.logging.HttpLoggingInterceptor
import okio.Buffer
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.io.EOFException
import java.nio.charset.Charset
import java.nio.charset.StandardCharsets.UTF_8
import java.security.SecureRandom
import java.security.cert.X509Certificate
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager

/**
 * 基础请求封装层
 */
object Request {

    private const val TAG = "ApiRequest"

    // 网络请求的基地址
    // 外网IP "http://120.27.232.27:48080"
    // 本地IP "http://192.168.0.10:48080"
    private const val BASE_URL = "http://120.27.232.27:48080"

    // 构建请求客户端
    private val okClient = OkHttpClient.Builder()
//        .addInterceptor {
//            val start = System.currentTimeMillis()
//            // 请求拦截 处理一些需要处理的数据，或者打印
//            val request = it.request()
//            val response: okhttp3.Response
//            try {
//                response = it.proceed(request)
//                val end = System.currentTimeMillis()
//                printLog(request, response, null, start, end)
//            } catch (e: Exception) {
//                val end = System.currentTimeMillis()
//                printLog(request, null, e, start, end)
//                throw e
//            }
//            return@addInterceptor response
//        }
        .addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
        .sslSocketFactory(getSocketFactory(), createTrustManager())
        .hostnameVerifier { _, _ -> true }
        .build()

    // 构建接口请求工具
    private val retrofit = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .client(okClient)
        .addConverterFactory(GsonConverterFactory.create())
        .build()


    /**
     * 创建一个证书工厂
     */
    @SuppressLint("TrustAllX509TrustManager", "CustomX509TrustManager")
    private fun getSocketFactory(): SSLSocketFactory {
        // 创建一个不验证证书链的 TrustManager
        val trustAllCerts = arrayOf<TrustManager>(
            object : X509TrustManager {
                override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {}
                override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {}
                override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
            }
        )

        val sslContext = SSLContext.getInstance("SSL")
        sslContext.init(null, trustAllCerts, SecureRandom())

        return sslContext.socketFactory
    }

    /**
     * 创建一个不验证证书链的 TrustManager
     */
    @SuppressLint("TrustAllX509TrustManager", "CustomX509TrustManager")
    private fun createTrustManager(): X509TrustManager {
        val trustAllCerts = arrayOf<TrustManager>(
            object : X509TrustManager {
                override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {}
                override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {}
                override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
            }
        )
        return trustAllCerts[0] as X509TrustManager
    }

    fun getRetrofit(): Retrofit {
        return retrofit
    }

    private fun Buffer.isProbablyUtf8(): Boolean {
        try {
            val prefix = Buffer()
            val byteCount = size.coerceAtMost(64)
            copyTo(prefix, 0, byteCount)
            for (i in 0 until 16) {
                if (prefix.exhausted()) {
                    break
                }
                val codePoint = prefix.readUtf8CodePoint()
                if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) {
                    return false
                }
            }
            return true
        } catch (_: EOFException) {
            return false // Truncated UTF-8 sequence.
        }
    }

    private fun printLog(request: Request, response: okhttp3.Response?, e: Exception?, start: Long, end: Long) {
        val sb = StringBuffer("ㅤ\n")
        sb.append("👉 ${start.format("yyyy-MM-dd HH:mm:ss.SSS")}").append("\n")
        sb.append("${request.method} ${request.url}").append("\n")
        // 打印请求头
        val headers = request.headers
        for (header in headers) {
            sb.append("${header.first}: ${header.second}").append("\n")
        }
        // 打印请求体
        request.body?.let { body ->
            val buffer = Buffer()
            body.writeTo(buffer)

            val contentType = body.contentType()
            val charset: Charset = contentType?.charset(UTF_8) ?: UTF_8

            if (buffer.isProbablyUtf8()) {
                sb.append(buffer.readString(charset)).append("\n")
            }
        }

        if (e != null) {
            sb.append("\n")
            // 打印响应数据，因为异常了
            sb.append(e.message ?: "").append("\n")
            sb.append("👈 ${end.format("yyyy-MM-dd HH:mm:ss.SSS")} (${end - start}ms)")
            LogUtil.e(TAG, "$sb")
        } else {
            // 打印响应数据
            response?.let {
                val responseBody = it.body!!
                val contentLength = responseBody.contentLength()
                val source = responseBody.source()
                source.request(Long.MAX_VALUE)
                val buffer = source.buffer
                sb.append("\n")
                val contentType = responseBody.contentType()
                val charset: Charset = contentType?.charset(UTF_8) ?: UTF_8
                if (contentLength != 0L) {
                    sb.append(buffer.clone().readString(charset)).append("\n")
                }
                sb.append("👈 ${end.format("yyyy-MM-dd HH:mm:ss.SSS")} (${end - start}ms)")
            }
            LogUtil.i(TAG, "$sb")
        }
    }
}