package dev.ulfrx.recipe.navigation

import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.navigation3.runtime.entryProvider
import androidx.navigation3.ui.NavDisplay
import dev.ulfrx.recipe.ui.screens.home.HomeScreen
import dev.ulfrx.recipe.ui.screens.home.HomeViewModel
import dev.ulfrx.recipe.ui.screens.pantry.PantryScreen
import dev.ulfrx.recipe.ui.screens.pantry.PantryViewModel
import dev.ulfrx.recipe.ui.screens.planner.PlannerScreen
import dev.ulfrx.recipe.ui.screens.planner.PlannerViewModel
import dev.ulfrx.recipe.ui.screens.shopping.ShoppingScreen
import dev.ulfrx.recipe.ui.screens.shopping.ShoppingViewModel
import org.koin.compose.viewmodel.koinViewModel

/**
 * Nav 3 host for the 4-tab shell. Renders **one** [NavDisplay] for the active
 * tab, swapped via [AnimatedContent] when [TabNavigator.activeTab] changes.
 *
 * ## Why one display per active tab, not one shared display
 * Nav 3's [NavDisplay] takes a single back stack. A shell with parallel tab
 * stacks therefore needs either:
 *  - one display that re-keys when the tab changes (this implementation), or
 *  - four always-composed displays stacked z-order, alpha-toggled by tab.
 *
 * The re-keyed approach matches the reference [To-Do-CMP](https://github.com/stevdza-san/To-Do-CMP)
 * structure 1:1, gives a clean 180 ms cross-fade between tabs, and avoids the
 * predictive-back-handler arbitration headache that comes with multiple live
 * NavDisplays competing for the gesture (see `NavDisplay.kt` source —
 * `NavigationBackHandler` is enabled when `previousEntries.isNotEmpty()`, which
 * is per-display and would mis-fire if multiple displays were alive at once).
 *
 * ## ViewModel lifetime
 * No `rememberViewModelStoreNavEntryDecorator` is installed, so `koinViewModel`
 * inside `entry<…>` resolves through the **host** `ViewModelStoreOwner`
 * (Android: the Activity; iOS: the root Compose owner). That keeps tab VMs
 * alive across tab switches even though the per-tab [NavDisplay] is unmounted
 * during cross-fade — matches the previous Nav-2 multi-back-stack behaviour
 * (`saveState=true`/`restoreState=true`).
 *
 * Recipe detail is a modal bottom sheet (not a nav destination), so it needs no
 * per-entry VM scope here; its VM is hosted by the surface that opens it.
 *
 * ## Search note
 * Search is a shell-wide overlay (see `AppShell` + `ShellSearchViewModel`), not
 * a tab destination — it lives outside this NavDisplay entirely.
 */
@Composable
fun RootNavDisplay(
    navigator: TabNavigator,
    modifier: Modifier = Modifier,
) {
    AnimatedContent(
        targetState = navigator.activeTab,
        modifier = modifier,
        transitionSpec = {
            fadeIn(tween(durationMillis = 180)) togetherWith
                fadeOut(tween(durationMillis = 180))
        },
        label = "RootNavDisplay tab cross-fade",
    ) { tab ->
        NavDisplay(
            backStack = navigator.backStackFor(tab),
            modifier = Modifier.fillMaxSize(),
            onBack = { navigator.goBack(tab) },
            entryProvider =
                entryProvider {
                    entry<Screen.Home.Root> {
                        val vm: HomeViewModel = koinViewModel()
                        HomeScreen(viewModel = vm)
                    }
                    entry<Screen.Planner.Home> {
                        val vm: PlannerViewModel = koinViewModel()
                        PlannerScreen(viewModel = vm)
                    }
                    entry<Screen.Pantry.Home> {
                        val vm: PantryViewModel = koinViewModel()
                        PantryScreen(viewModel = vm)
                    }
                    entry<Screen.Shopping.Home> {
                        val vm: ShoppingViewModel = koinViewModel()
                        ShoppingScreen(viewModel = vm)
                    }
                },
        )
    }
}
