package com.example.studyapp.update

import android.util.Log
import okhttp3.*
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.logging.HttpLoggingInterceptor
import java.io.IOException
import java.security.SecureRandom
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager


object HttpUtils {
    const val HOST: String = "https://openapi-hk.armcloud.net"
    private val client: OkHttpClient by lazy {
        val trustAllCerts: Array<TrustManager> = 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?>? {
                return arrayOf<X509Certificate?>()
            }
        }
        )

        val sslContext = SSLContext.getInstance("SSL")
        sslContext.init(null, trustAllCerts, SecureRandom())
        OkHttpClient.Builder()
            .connectTimeout(15, TimeUnit.SECONDS)
            .readTimeout(15, TimeUnit.SECONDS)
            .writeTimeout(15, TimeUnit.SECONDS)
            .addInterceptor(HttpLoggingInterceptor().apply {
                level = HttpLoggingInterceptor.Level.BODY
            })
            .sslSocketFactory(sslContext.socketFactory, trustAllCerts[0] as X509TrustManager)
            .hostnameVerifier(HostnameVerifier { _, _ -> true })
            .build()
    }

    // JSON媒体类型
    private val JSON_MEDIA_TYPE = "application/json; charset=utf-8".toMediaTypeOrNull()

    // 回调接口
    interface HttpCallback {
        fun onSuccess(response: String, code: Int)
        fun onFailure(error: String, code: Int?)
    }

    /**
     * GET 请求（异步）
     *
     * @param url 请求URL
     * @param params 查询参数（可选）
     * @param headers 请求头（可选）
     * @param callback 回调接口
     */
    fun getAsync(
        url: String,
        params: Map<String, String>? = null,
        callback: HttpCallback
    ) {
        val request = buildGetRequest(url, params)
        executeRequestAsync(request, callback)
    }

    /**
     * POST 请求（异步）
     *
     * @param url 请求URL
     * @param body 请求体（JSON格式）
     * @param headers 请求头（可选）
     * @param callback 回调接口
     */
    fun postAsync(
        url: String,
        body: String? = null,
        callback: HttpCallback
    ) {
        val request = buildPostRequest(url, body)
        executeRequestAsync(request, callback)
    }

    /**
     * GET 请求（同步）
     *
     * @param url 请求URL
     * @param params 查询参数（可选）
     * @param headers 请求头（可选）
     * @return Pair<响应内容, 状态码>
     */
    fun getSync(
        url: String,
        params: Map<String, String>? = null,
    ): Pair<String?, Int> {
        val request = buildGetRequest(url, params)
        return executeRequestSync(request)
    }

    /**
     * POST 请求（同步）
     *
     * @param url 请求URL
     * @param body 请求体（JSON格式）
     * @param headers 请求头（可选）
     * @return Pair<响应内容, 状态码>
     */
    fun postSync(
        url: String,
        body: String? = null
    ): Pair<String?, Int> {
        val request = buildPostRequest(url, body)
        return executeRequestSync(request)
    }

    /**
     * 取消所有请求
     */
    fun cancelAllRequests() {
        client.dispatcher.cancelAll()
    }

    // 内部方法 --------------------------------

    private fun buildGetRequest(
        path: String ,
        params: Map<String, String>?,
    ): Request {
        val url = "$HOST$path"
        val httpUrlBuilder = url.toHttpUrlOrNull()?.newBuilder()
            ?: throw IllegalArgumentException("Invalid URL: $url")

        var param = ""
        params?.forEach { (key, value) ->
            httpUrlBuilder.addQueryParameter(key, value)
            param += "&${key}=${value}"
        }
        if (param.isNotEmpty()){
            param = param.substring(1)
        }

        val requestBuilder = Request.Builder().url(httpUrlBuilder.build())

        val authver = "2.0"
        val timestamp = System.currentTimeMillis()
        val sign =
            ArmCloudSignatureV2.calculateSignature(timestamp.toString(), path, param)
        addHeaders(
            requestBuilder,
            mapOf(
                "authver" to authver,
                "x-ak" to ArmCloudSignatureV2.SECRET_KEY,
                "x-timestamp" to timestamp.toString(),
                "x-sign" to sign
            )
        )

        return requestBuilder.build()
    }

    private fun buildPostRequest(
        path: String,
        body: String? = null
    ): Request {
        val url = "$HOST$path"
        val bodyString = body?:""
        val requestBuilder = Request.Builder()
            .url(url)
            .post(bodyString.toRequestBody(JSON_MEDIA_TYPE))
        val authver = "2.0"
        val timestamp = System.currentTimeMillis()
        val sign =
            ArmCloudSignatureV2.calculateSignature(timestamp.toString(), path, body)
        addHeaders(
            requestBuilder,
            mapOf(
                "authver" to authver,
                "x-ak" to ArmCloudSignatureV2.SECRET_KEY,
                "x-timestamp" to timestamp.toString(),
                "x-sign" to sign
            )
        )

        return requestBuilder.build()
    }

    private fun addHeaders(
        builder: Request.Builder,
        headers: Map<String, String>
    ) {
        headers.forEach { (key, value) ->
            builder.addHeader(key, value)
        }
    }

    private fun buildFormBody(formData: Map<String, String>): RequestBody {
        val formBodyBuilder = FormBody.Builder()
        formData.forEach { (key, value) ->
            formBodyBuilder.add(key, value)
        }
        return formBodyBuilder.build()
    }

    private fun executeRequestAsync(
        request: Request,
        callback: HttpCallback
    ) {
        client.newCall(request).enqueue(object : Callback {
            override fun onResponse(call: Call, response: Response) {
                val responseBody = response.body?.string()
                val code = response.code

                if (response.isSuccessful && responseBody != null) {
                    callback.onSuccess(responseBody, code)
                } else {
                    callback.onFailure(
                        responseBody ?: "Empty response",
                        code
                    )
                }
            }

            override fun onFailure(call: Call, e: IOException) {
                callback.onFailure(e.message ?: "Unknown network error", null)
            }
        })
    }

    private fun executeRequestSync(request: Request): Pair<String?, Int> {
        return try {
            val response = client.newCall(request).execute()
            val responseBody = response.peekBody(Long.MAX_VALUE).string()
            val code = response.code
            Log.d("TAG", "executeRequestSync: $responseBody")
            if (response.isSuccessful && responseBody.isNotEmpty()) {
                Pair(responseBody, code)
            } else {
                Pair(null, -1)
            }
        } catch (e: IOException) {
            Pair(null, -1) // 网络错误状态码
        }
    }
}