package ru.forbion.f7cloud.mobile

import android.util.Log
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ProcessLifecycleOwner
import coil.ImageLoader
import coil.ImageLoaderFactory
import coil.decode.SvgDecoder
import coil.disk.DiskCache
import coil.memory.MemoryCache
import com.google.firebase.messaging.FirebaseMessaging
import ru.f7cloud.talk.application.F7cloudTalkApplication
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import ru.forbion.f7cloud.core.auth.AuthStore
import ru.forbion.f7cloud.core.designsystem.AppForegroundTracker
import ru.forbion.f7cloud.core.network.NetworkFactory
import ru.forbion.f7cloud.core.push.F7NotificationChannels
import ru.forbion.f7cloud.core.push.F7PushRegistrar
import ru.forbion.f7cloud.feature.talknative.TalkVendorBootstrap

/**
 * F7cloud application entry. Extends talk-android [F7cloudTalkApplication] so native
 * WebRTC (CallActivity, Dagger, Room) can initialize when [TalkVendorBootstrap] is enabled.
 */
class F7MobileApp : F7cloudTalkApplication(), ImageLoaderFactory {
    override fun onCreate() {
        super.onCreate()
        ProcessLifecycleOwner.get().lifecycle.addObserver(object : DefaultLifecycleObserver {
            override fun onStart(owner: LifecycleOwner) {
                AppForegroundTracker.setForeground(true)
            }

            override fun onStop(owner: LifecycleOwner) {
                AppForegroundTracker.setForeground(false)
            }
        })
        F7NotificationChannels.ensureAll(this)
        NetworkFactory.init(this) // общий HTTP-клиент + диск-кэш (переиспользование соединений)
        TalkVendorBootstrap.onApplicationCreate(this)
        val auth = AuthStore(this).load() ?: return
        try {
            bootstrapFcmRegistration(auth)
        } catch (t: Throwable) {
            Log.w("F7MobileApp", "Firebase unavailable, push bootstrap skipped", t)
        }
    }

    /**
     * Re-register after Firebase config changes (e.g. google-services.json for .mobile package).
     */
    private fun bootstrapFcmRegistration(auth: ru.forbion.f7cloud.core.auth.AuthSession) {
        val prefs = getSharedPreferences("f7push", MODE_PRIVATE)
        val configGeneration = 2
        val needsRefresh = prefs.getInt("fcm_config_generation", 0) < configGeneration

        fun registerToken(token: String) {
            CoroutineScope(Dispatchers.IO).launch {
                val code = F7PushRegistrar.registerBlocking(this@F7MobileApp, auth, token)
                Log.d("F7MobileApp", "push register result: $code")
            }
        }

        if (needsRefresh) {
            FirebaseMessaging.getInstance().deleteToken().addOnCompleteListener {
                FirebaseMessaging.getInstance().token.addOnSuccessListener { token ->
                    prefs.edit().putInt("fcm_config_generation", configGeneration).apply()
                    registerToken(token)
                }
            }
            return
        }

        FirebaseMessaging.getInstance().token.addOnSuccessListener { registerToken(it) }
    }

    override fun newImageLoader(): ImageLoader {
        // OkHttp с Basic-auth для хоста сервера: серверные картинки (иконки внешних сайтов
        // /apps/external/img, превью и т.п.) требуют логина — без заголовка coil ловит 401.
        val authedClient = okhttp3.OkHttpClient.Builder()
            .addInterceptor { chain ->
                val request = chain.request()
                val session = runCatching { AuthStore(this).load() }.getOrNull()
                val serverHost = session?.serverUrl?.let {
                    runCatching { android.net.Uri.parse(it).host }.getOrNull()
                }
                val patched = if (session != null && serverHost != null && request.url.host == serverHost) {
                    request.newBuilder()
                        .header(
                            "Authorization",
                            okhttp3.Credentials.basic(session.username, session.appPassword),
                        )
                        .header("OCS-APIRequest", "true")
                        .build()
                } else {
                    request
                }
                chain.proceed(patched)
            }
            .build()
        return ImageLoader.Builder(this)
            .okHttpClient(authedClient)
            .components { add(SvgDecoder.Factory()) }
            .crossfade(false)
            .memoryCache {
                MemoryCache.Builder(this)
                    .maxSizePercent(0.12)
                    .build()
            }
            .diskCache {
                DiskCache.Builder()
                    .directory(cacheDir.resolve("coil_image_cache"))
                    .maxSizePercent(0.02)
                    .build()
            }
            .build()
    }
}
