package org.dueattendant149.bookshelf.data.remote.audiobookshelf

import android.util.Log
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import org.dueattendant149.bookshelf.domain.util.fixUriScheme
import retrofit2.Retrofit
import retrofit2.converter.kotlinx.serialization.asConverterFactory
import javax.inject.Inject
import javax.inject.Singleton

/**
 * Builds (and caches) a Retrofit-backed [AudiobookshelfApiService] for the configured
 * Audiobookshelf instance. All requests are authenticated with the provided bearer token.
 */
@Singleton
class AudiobookshelfApiClientFactory
    @Inject
    constructor(
        private val json: Json,
        private val okHttpClient: OkHttpClient,
    ) {
        private var cachedUrl: String? = null
        private var cachedToken: String? = null
        private var cachedClient: AudiobookshelfApiService? = null

        @Synchronized
        fun provideClient(
            url: String,
            token: String,
        ): AudiobookshelfApiService? {
            val fixedUrl = url.fixUriScheme()
            if (fixedUrl == cachedUrl && token == cachedToken && cachedClient != null) {
                return cachedClient
            }

            val authClient =
                okHttpClient
                    .newBuilder()
                    .addInterceptor { chain ->
                        val request =
                            chain
                                .request()
                                .newBuilder()
                                .header("Authorization", "Bearer $token")
                                .build()
                        chain.proceed(request)
                    }
                    .addInterceptor(HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BASIC })
                    .build()

            return runCatching {
                Retrofit
                    .Builder()
                    .client(authClient)
                    .baseUrl(fixedUrl)
                    .addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
                    .build()
                    .create(AudiobookshelfApiService::class.java)
            }.onFailure {
                Log.e("AudiobookshelfApiFactory", "Failed to create client for $fixedUrl", it)
            }.getOrNull().also {
                cachedUrl = fixedUrl
                cachedToken = token
                cachedClient = it
            }
        }

        fun clearCache() {
            cachedUrl = null
            cachedToken = null
            cachedClient = null
        }
    }
