package org.dueattendant149.bookshelf.data.remote.bookshelfapi

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

/**
 * Builds (and caches) a Retrofit-backed [BookshelfApiService] for the configured
 * bookshelf-api instance.
 */
@Singleton
class BookshelfApiClientFactory
    @Inject
    constructor(
        private val json: Json,
        private val okHttpClient: OkHttpClient,
    ) {
        private var cachedUrl: String? = null
        private var cachedClient: BookshelfApiService? = null

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

            return runCatching {
                Retrofit
                    .Builder()
                    .client(
                        okHttpClient
                            .newBuilder()
                            .addInterceptor(HttpLoggingInterceptor().apply {
                                level = HttpLoggingInterceptor.Level.BASIC
                            })
                            .build(),
                    )
                    .baseUrl(fixedUrl)
                    .addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
                    .build()
                    .create(BookshelfApiService::class.java)
            }.onFailure {
                Log.e("BookshelfApiClientFactory", "Failed to create BookshelfApiService for $fixedUrl", it)
            }.getOrNull().also {
                cachedUrl = fixedUrl
                cachedClient = it
            }
        }

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