package com.jttools.datacontrol.service

import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import javax.inject.Inject
import javax.inject.Singleton

enum class NetworkTransport { CELLULAR, WIFI, OTHER, NONE }

/**
 * Observe le réseau par défaut de l'appareil et expose son transport (cellulaire / Wi-Fi / autre).
 * Le pare-feu VPN ne doit être actif QUE lorsque le transport actif est CELLULAR — sur Wi-Fi,
 * l'accès Internet de toutes les applications reste totalement libre.
 */
@Singleton
class ConnectivityObserver @Inject constructor(
    @ApplicationContext private val context: Context
) {
    fun observe(): Flow<NetworkTransport> = callbackFlow {
        val cm = context.getSystemService(ConnectivityManager::class.java)

        fun transportOf(caps: NetworkCapabilities?): NetworkTransport = when {
            caps == null -> NetworkTransport.NONE
            caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> NetworkTransport.CELLULAR
            caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> NetworkTransport.WIFI
            else -> NetworkTransport.OTHER
        }

        val callback = object : ConnectivityManager.NetworkCallback() {
            override fun onCapabilitiesChanged(network: Network, caps: NetworkCapabilities) {
                trySend(transportOf(caps))
            }

            override fun onLost(network: Network) {
                trySend(NetworkTransport.NONE)
            }
        }

        val request = NetworkRequest.Builder()
            .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
            .build()

        trySend(transportOf(cm.getNetworkCapabilities(cm.activeNetwork)))
        cm.registerNetworkCallback(request, callback)

        awaitClose { cm.unregisterNetworkCallback(callback) }
    }.distinctUntilChanged()
}
