package cl.homelogic.platform.navigation

import androidx.navigation.NavUri
import cl.homelogic.platform.common.logging.Trace
import cl.homelogic.platform.common.logging.TreeRoots
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlin.time.Clock
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Instant

sealed class NavigationCommand {
    data class Route(
        val destination: NavigationDestination,
    ) : NavigationCommand()

    data class DeepLink(
        val uri: NavUri,
    ) : NavigationCommand()

    data object PopBack : NavigationCommand()

    data class PopUpTo(
        val destination: NavigationDestination,
        val inclusive: Boolean = false,
    ) : NavigationCommand()
}

class NavigationManager {
    private val _navigationEvents = MutableSharedFlow<NavigationCommand>()
    internal val navigationEvents = _navigationEvents.asSharedFlow()

    private val throttleWindow = 100.milliseconds
    private var lastNavigationTime: Instant = Instant.DISTANT_PAST

    suspend fun navigate(destination: NavigationDestination) {
        if (shouldThrottleNavigation()) {
            Trace.d(TreeRoots.Navigation, "Navigation throttled: ${destination::class}")
            return
        }

        Trace.d(
            TreeRoots.Navigation,
            "Navigating to: ${
                destination::class
                    .qualifiedName
                    ?.split(".")
                    ?.takeLast(2)
                    ?.joinToString(".") ?: destination::class.simpleName
            }",
        )
        updateLastNavigationTime()
        _navigationEvents.emit(NavigationCommand.Route(destination))
    }

    suspend fun navigate(deepLink: NavUri) {
        if (shouldThrottleNavigation()) {
            Trace.d(TreeRoots.Navigation, "DeepLink navigation throttled for: $deepLink")
            return
        }

        Trace.d(TreeRoots.Navigation, "Navigating to deeplink: $deepLink")
        updateLastNavigationTime()
        _navigationEvents.emit(NavigationCommand.DeepLink(deepLink))
    }

    suspend fun popBackStack() {
        if (shouldThrottleNavigation()) {
            Trace.d(TreeRoots.Navigation, "PopBackStack throttled")
            return
        }

        Trace.d(TreeRoots.Navigation, "PopBackStack triggered")
        updateLastNavigationTime()
        _navigationEvents.emit(NavigationCommand.PopBack)
    }

    suspend fun popUpTo(
        destination: NavigationDestination,
        inclusive: Boolean,
    ) {
        if (shouldThrottleNavigation()) {
            Trace.d(TreeRoots.Navigation, "PopBackStack throttled")
            return
        }

        Trace.d(TreeRoots.Navigation, "PopBackStack triggered")
        updateLastNavigationTime()
        _navigationEvents.emit(NavigationCommand.PopUpTo(destination, inclusive))
    }

    private fun shouldThrottleNavigation(): Boolean {
        val currentTime = Clock.System.now()
        val lastNavigation = lastNavigationTime
        return (currentTime - lastNavigation) < throttleWindow
    }

    private fun updateLastNavigationTime() {
        lastNavigationTime = Clock.System.now()
    }
}
