package com.aiwazian.messenger.api

import com.aiwazian.messenger.interfaces.ApiService
import com.aiwazian.messenger.services.TokenManager
import com.aiwazian.messenger.utils.Constants
import com.aiwazian.messenger.utils.DownloadManager
import com.aiwazian.messenger.utils.Route
import com.google.gson.GsonBuilder
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import com.google.gson.JsonPrimitive
import com.google.gson.JsonSerializationContext
import com.google.gson.JsonSerializer
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.lang.reflect.Type
import java.util.concurrent.TimeUnit

private object LongTypeAdapter : JsonDeserializer<Long>, JsonSerializer<Long> {
    override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Long {
        return when {
            json.isJsonPrimitive && json.asJsonPrimitive.isNumber -> json.asLong
            json.isJsonPrimitive -> json.asString.toLongOrNull() ?: 0L
            else -> 0L
        }
    }
    override fun serialize(src: Long, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
        return JsonPrimitive(src)
    }
}

object RetrofitInstance {

    private val gson = GsonBuilder()
        .registerTypeAdapter(Long::class.java, LongTypeAdapter)
        .registerTypeAdapter(Long::class.javaObjectType, LongTypeAdapter)
        .create()

    private val BASE_URL = Constants.SERVER_URL
    
    private val skipAuthPaths = listOf(
        Route.LOGIN,
        Route.REGISTER,
        Route.FIND_USER_BY_LOGIN
    )
    
    private val okHttpClient = OkHttpClient.Builder().connectTimeout(
        1,
        TimeUnit.MINUTES
    ).readTimeout(
        1,
        TimeUnit.MINUTES
    ).writeTimeout(
        1,
        TimeUnit.MINUTES
    ).addInterceptor(
        AuthInterceptor(
            getToken = {
                TokenManager.getToken()
            },
            shouldSkipAuth = { path ->
                skipAuthPaths.contains(path)
            },
            onUnauthorized = {
                TokenManager.getUnauthorizedCallback()?.invoke()
            })
    ).addNetworkInterceptor(
        ProgressInterceptor { url, progress ->
            DownloadManager.updateProgress(
                url,
                progress
            )
        }).build()
    
    val api: ApiService by lazy {
        Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .build()
            .create(ApiService::class.java)
    }
}
