package ru.forbion.f7cloud.core.network

import android.content.Context
import okhttp3.Cache
import okhttp3.OkHttpClient
import java.io.File
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.TimeUnit

/**
 * Фабрика HTTP-клиентов. Раньше создавала НОВЫЙ OkHttpClient на КАЖДЫЙ запрос (~32 места) →
 * TLS-handshake и новый пул/диспатчер на запрос, утечка ExecutorService. Теперь:
 *  - один базовый клиент (общий ConnectionPool + Dispatcher + диск-кэш);
 *  - авторизованные варианты — через `base.newBuilder()` (шарят пул/диспатчер/кэш);
 *  - экземпляры кэшируются по кредам+таймаутам → переиспользуются, соединения живут.
 *
 * Публичный API совместим — вызывающие (`newAuthedClient*`) работают как прежде.
 * 401→UnauthorizedException централизован через interceptor (`throwOnUnauthorized`, по умолч.
 * true) — ручные проверки в репозиториях убраны. Login-пути (AuthVerifier), где 401 = «неверный
 * пароль» со своим сообщением, передают `throwOnUnauthorized = false`.
 */
object NetworkFactory {
    @Volatile
    private var base: OkHttpClient = OkHttpClient()
    private val clients = ConcurrentHashMap<String, OkHttpClient>()

    /** Вызывать один раз из Application.onCreate — добавляет диск-кэш (нужен cacheDir). */
    fun init(context: Context) {
        val cacheDir = File(context.applicationContext.cacheDir, "http-cache")
        base = OkHttpClient.Builder()
            .cache(Cache(cacheDir, 20L * 1024 * 1024)) // 20 МБ
            .build()
        clients.clear() // пересобрать производные клиенты уже с кэшем
    }

    fun newAuthedClient(
        username: String,
        appPassword: String,
        trustAllCerts: Boolean = false,
        callTimeoutSeconds: Long = 30,
        readTimeoutSeconds: Long = 30,
        throwOnUnauthorized: Boolean = true,
    ): OkHttpClient {
        val key = "$username|$appPassword|$trustAllCerts|$callTimeoutSeconds|$readTimeoutSeconds|$throwOnUnauthorized"
        return clients.getOrPut(key) {
            base.newBuilder() // общий пул/диспатчер/кэш базового клиента
                .callTimeout(callTimeoutSeconds, TimeUnit.SECONDS)
                .connectTimeout(20, TimeUnit.SECONDS)
                .readTimeout(readTimeoutSeconds, TimeUnit.SECONDS)
                .applyUnsafeSslIfNeeded(trustAllCerts)
                .addInterceptor(BasicAuthInterceptor(username, appPassword))
                .apply { if (throwOnUnauthorized) addInterceptor(UnauthorizedInterceptor) }
                .build()
        }
    }

    /** Collabora / richdocuments: cold start and WOPI can be slow on mobile networks. */
    fun newAuthedClientForOffice(
        username: String,
        appPassword: String,
        trustAllCerts: Boolean = false,
    ): OkHttpClient = newAuthedClient(
        username = username,
        appPassword = appPassword,
        trustAllCerts = trustAllCerts,
        callTimeoutSeconds = 120,
        readTimeoutSeconds = 120,
    )
}
