package com.aiosman.riderpro.data.api

import android.icu.text.SimpleDateFormat
import android.icu.util.TimeZone
import com.aiosman.riderpro.AppStore
import com.aiosman.riderpro.ConstVars
import com.auth0.android.jwt.JWT
import kotlinx.coroutines.runBlocking
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.security.cert.CertificateException
import java.util.Date
import java.util.Locale
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager

fun getUnsafeOkHttpClient(
    authInterceptor: AuthInterceptor? = null
): OkHttpClient {
    return try {
        // Create a trust manager that does not validate certificate chains
        val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
            @Throws(CertificateException::class)
            override fun checkClientTrusted(
                chain: Array<java.security.cert.X509Certificate>,
                authType: String
            ) {
            }

            @Throws(CertificateException::class)
            override fun checkServerTrusted(
                chain: Array<java.security.cert.X509Certificate>,
                authType: String
            ) {
            }

            override fun getAcceptedIssuers(): Array<java.security.cert.X509Certificate> = arrayOf()
        })

        // Install the all-trusting trust manager
        val sslContext = SSLContext.getInstance("SSL")
        sslContext.init(null, trustAllCerts, java.security.SecureRandom())
        // Create an ssl socket factory with our all-trusting manager
        val sslSocketFactory = sslContext.socketFactory

        OkHttpClient.Builder()
            .sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)
            .hostnameVerifier { _, _ -> true }
            .apply {
                authInterceptor?.let {
                    addInterceptor(it)
                }
            }
            .build()
    } catch (e: Exception) {
        throw RuntimeException(e)
    }
}

class AuthInterceptor() : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val requestBuilder = chain.request().newBuilder()
        val token = AppStore.token
        token?.let {
            val jwt = JWT(token)
            val expiresAt = jwt.expiresAt?.time?.minus(3000)
            val currentTime = System.currentTimeMillis()
            val isExpired = expiresAt != null && currentTime > expiresAt
            if (isExpired) {
                runBlocking {
                    val newToken = refreshToken()
                    if (newToken != null) {
                        AppStore.token = newToken
                    }
                }
            }
        }

        requestBuilder.addHeader("Authorization", "Bearer ${AppStore.token}")

        val response = chain.proceed(requestBuilder.build())
        return response
    }

    private suspend fun refreshToken(): String? {
        val client = Retrofit.Builder()
            .baseUrl(ApiClient.RETROFIT_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .client(getUnsafeOkHttpClient())
            .build()
            .create(RiderProAPI::class.java)

        val resp = client.refreshToken(AppStore.token ?: "")
        val newToken = resp.body()?.token
        if (newToken != null) {
            AppStore.token = newToken
        }
        return newToken
    }
}

object ApiClient {
    const val BASE_SERVER = ConstVars.BASE_SERVER
    const val BASE_API_URL = "${BASE_SERVER}/api/v1"
    const val RETROFIT_URL = "${BASE_API_URL}/"
    const val TIME_FORMAT = "yyyy-MM-dd HH:mm:ss"
    private val okHttpClient: OkHttpClient by lazy {
        getUnsafeOkHttpClient(authInterceptor = AuthInterceptor())
    }
    private val retrofit: Retrofit by lazy {
        Retrofit.Builder()
            .baseUrl(RETROFIT_URL)
            .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    }
    val api: RiderProAPI by lazy {
        retrofit.create(RiderProAPI::class.java)
    }

    fun formatTime(date: Date): String {
        val dateFormat = SimpleDateFormat(TIME_FORMAT, Locale.getDefault())
        return dateFormat.format(date)
    }

    fun dateFromApiString(apiString: String): Date {
        val timeFormat = TIME_FORMAT
        val simpleDateFormat = SimpleDateFormat(timeFormat, Locale.getDefault())
        simpleDateFormat.timeZone = TimeZone.getTimeZone("UTC")
        val date = simpleDateFormat.parse(apiString)

        simpleDateFormat.timeZone = TimeZone.getDefault()
        val localDateString = simpleDateFormat.format(date)
        return simpleDateFormat.parse(localDateString)
    }
}