package app.closer.core.navigation

import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.Chat
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material.icons.filled.Star
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.navigation.NavType
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.navArgument
import androidx.navigation.navDeepLink
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.LaunchedEffect
import app.closer.ui.auth.ForgotPasswordScreen
import app.closer.ui.answers.AnswerHistoryScreen
import app.closer.ui.answers.AnswerRevealScreen
import app.closer.ui.auth.LoginScreen
import app.closer.ui.auth.SignUpScreen
import app.closer.ui.home.HomeScreen
import app.closer.ui.home.PartnerHomeScreen
import app.closer.ui.onboarding.CreateProfileScreen
import app.closer.ui.onboarding.OnboardingScreen
import app.closer.ui.pairing.AcceptInviteScreen
import app.closer.ui.pairing.CreateInviteScreen
import app.closer.ui.pairing.InviteConfirmScreen
import app.closer.ui.pairing.PairPromptScreen
import app.closer.ui.pairing.PairingSuccessScreen
import app.closer.ui.pairing.RecoveryScreen
import app.closer.ui.dates.DateMatchScreen
import app.closer.ui.dates.DateMatchesScreen
import app.closer.ui.dates.DateBuilderScreen
import app.closer.ui.dates.BucketListScreen
import app.closer.ui.paywall.PaywallScreen
import app.closer.ui.play.PlayHubScreen
import app.closer.ui.challenges.ConnectionChallengesScreen
import app.closer.ui.memorylane.MemoryLaneScreen
import app.closer.ui.desiresync.DesireSyncScreen
import app.closer.ui.desiresync.DSReplayScreen
import app.closer.ui.howwell.HowWellScreen
import app.closer.ui.howwell.HowWellReplayScreen
import app.closer.ui.thisorthat.ThisOrThatScreen
import app.closer.ui.thisorthat.ThisOrThatReplayScreen
import app.closer.ui.questions.DailyQuestionScreen
import app.closer.ui.questions.QuestionCategoryScreen
import app.closer.ui.questions.QuestionComposerScreen
import app.closer.ui.questions.QuestionPackLibraryScreen
import app.closer.ui.questions.QuestionThreadScreen
import app.closer.ui.messages.MessagesInboxScreen
import app.closer.ui.messages.ConversationScreen
import app.closer.ui.settings.AccountScreen
import app.closer.ui.settings.AppearanceScreen
import app.closer.ui.settings.DeleteAccountScreen
import app.closer.ui.settings.NotificationSettingsScreen
import app.closer.ui.settings.PrivacyScreen
import app.closer.ui.settings.SecurityScreen
import app.closer.ui.settings.RelationshipSettingsScreen
import app.closer.ui.settings.SettingsScreen
import app.closer.ui.settings.SubscriptionScreen
import app.closer.ui.outcomes.YourProgressScreen
import app.closer.ui.activity.ActivityScreen
import app.closer.ui.wheel.CategoryPickerScreen
import app.closer.ui.wheel.SpinWheelScreen
import app.closer.ui.wheel.WheelCompleteScreen
import app.closer.ui.wheel.GameHistoryScreen
import app.closer.ui.wheel.WheelSessionScreen
import app.closer.ui.games.WaitingForPartnerScreen

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AppNavigation(
    modifier: Modifier = Modifier,
    startDestination: String = AppRoute.ONBOARDING,
    pendingDeepLink: String? = null,
    onDeepLinkConsumed: () -> Unit = {}
) {
    val navController = rememberNavController()
    val navBackStackEntry by navController.currentBackStackEntryAsState()
    val currentRoute = navBackStackEntry?.destination?.route
    // Debug paired-home preview shows the real bottom nav too, so the menu stays anchored
    // exactly as it does on the live paired Home (which is the HOME tab route).
    val bottomRoutes = AppRoute.topLevelRoutes + AppRoute.PAIRED_HOME_PREVIEW
    val shellTitle = currentRoute
        ?.takeIf { it in shellBackRoutes }
        ?.let(AppRoute::titleFor)
    // Tab-switch semantics: pop to the graph start and keep a single instance, so a
    // tab is never pushed on top of another tab. We deliberately DON'T save/restore
    // each tab's back stack — tapping a bottom tab always lands on that tab's root,
    // never a sub-screen you previously drilled into. (Restoring the saved stack made
    // re-tapping "Settings" reopen a deep page — e.g. the paired-home preview — which
    // read as "Settings goes to a paired partner".)
    val selectTab: (String) -> Unit = { route ->
        navController.navigate(route) {
            popUpTo(navController.graph.findStartDestination().id) {
                saveState = false
            }
            launchSingleTop = true
            restoreState = false
        }
    }
    val navigateBackOrHome: () -> Unit = {
        if (!navController.popBackStack()) {
            selectTab(AppRoute.HOME)
        }
    }
    // The pre-app entry flow (onboarding + profile/pairing setup + auth). Leaving any of
    // these for Home must CLEAR them from the back stack — otherwise the graph start
    // (ONBOARDING) lingers as the root under Home and a system Back from Home walks
    // backward into the onboarding carousel / login screen, making a signed-in user look
    // logged out (C-NAV-001).
    val entryRoutes = setOf(
        AppRoute.ONBOARDING,
        AppRoute.CREATE_PROFILE,
        AppRoute.PAIR_PROMPT,
        AppRoute.LOGIN,
        AppRoute.SIGN_UP,
        AppRoute.FORGOT_PASSWORD
    )
    val navigateRoute: (String) -> Unit = { route ->
        when {
            route == "back" -> navigateBackOrHome()
            // Completing onboarding/auth: make Home the back-stack root (wipe the entire
            // entry flow) so Back from Home exits the app, never resurfaces onboarding/login.
            route == AppRoute.HOME && currentRoute in entryRoutes ->
                navController.navigate(AppRoute.HOME) {
                    popUpTo(0) { inclusive = true }
                    launchSingleTop = true
                }
            // Top-level tabs must use tab-switch semantics. Plain-navigating to a
            // tab (e.g. a "Game waiting" card → PLAY) would stack it on the current
            // tab; the bottom bar then saves that substack and `restoreState` later
            // lands the user on the wrong tab (Home → Play was the symptom).
            route in AppRoute.topLevelRoutes -> selectTab(route)
            else -> navController.navigate(route)
        }
    }

    // A partner/chat notification was tapped while the app was backgrounded or closed. The OS
    // delivers the FCM payload as intent extras (not a deep-link Uri), so we resolve a route in
    // MainActivity and navigate here — but only once the user is past onboarding (authenticated +
    // on the main graph), otherwise the destination can't load and the tap appears to do nothing.
    LaunchedEffect(pendingDeepLink, currentRoute) {
        val link = pendingDeepLink ?: return@LaunchedEffect
        // Wait until the user has actually settled on Home (authenticated + onboarding finished).
        // Navigating during the onboarding→home transition races its popUpTo, which discards the
        // destination — the symptom of "the app opens but the message never loads".
        if (currentRoute == AppRoute.HOME) {
            kotlinx.coroutines.delay(350)
            navigateRoute(link)
            onDeepLinkConsumed()
        }
    }

    androidx.compose.foundation.layout.Box(
        modifier = androidx.compose.ui.Modifier.fillMaxSize()
    ) {
    Scaffold(
        modifier = modifier,
        topBar = {
            if (shellTitle != null) {
                TopAppBar(
                    title = {
                        Text(
                            text = shellTitle,
                            style = MaterialTheme.typography.titleLarge
                        )
                    },
                    navigationIcon = {
                        IconButton(onClick = navigateBackOrHome) {
                            Icon(
                                imageVector = Icons.AutoMirrored.Filled.ArrowBack,
                                contentDescription = "Back"
                            )
                        }
                    },
                    colors = TopAppBarDefaults.topAppBarColors(
                        containerColor = MaterialTheme.colorScheme.background.copy(alpha = 0.96f)
                    )
                )
            }
        },
        bottomBar = {
            if (currentRoute in bottomRoutes) {
                AppBottomNavigation(
                    currentRoute = currentRoute,
                    onRouteSelected = selectTab
                )
            }
        }
    ) { padding ->
        NavHost(
            navController = navController,
            startDestination = startDestination,
            modifier = Modifier.padding(padding)
        ) {
            // Onboarding
            composable(route = AppRoute.ONBOARDING) {
                OnboardingScreen(onNavigate = navigateRoute)
            }
            composable(route = AppRoute.CREATE_PROFILE) {
                CreateProfileScreen(onNavigate = navigateRoute)
            }
            composable(route = AppRoute.PAIR_PROMPT) {
                PairPromptScreen(onNavigate = navigateRoute)
            }

            // Auth
            composable(route = AppRoute.LOGIN) {
                LoginScreen(onNavigate = navigateRoute)
            }
            composable(route = AppRoute.SIGN_UP) {
                SignUpScreen(onNavigate = navigateRoute)
            }
            composable(route = AppRoute.FORGOT_PASSWORD) {
                ForgotPasswordScreen(onNavigate = navigateRoute)
            }

            // Home
            composable(
                route = AppRoute.HOME,
                deepLinks = listOf(navDeepLink { uriPattern = "closer://closer.app/home" })
            ) {
                HomeScreen(onNavigate = navigateRoute)
            }
            composable(route = AppRoute.PARTNER_HOME) {
                PartnerHomeScreen(onNavigate = navigateRoute)
            }
            composable(
                route = AppRoute.PLAY,
                deepLinks = listOf(navDeepLink { uriPattern = "closer://closer.app/play" })
            ) {
                PlayHubScreen(onNavigate = navigateRoute)
            }

            // Daily Question
            composable(
                route = AppRoute.DAILY_QUESTION,
                deepLinks = listOf(navDeepLink { uriPattern = "closer://closer.app/daily_question" })
            ) {
                DailyQuestionScreen(onNavigate = navigateRoute, onBack = navigateBackOrHome)
            }
            composable(route = AppRoute.QUESTION_PACKS) {
                QuestionPackLibraryScreen(onNavigate = navigateRoute)
            }
            composable(route = AppRoute.MESSAGES) {
                MessagesInboxScreen(onNavigate = navigateRoute)
            }
            composable(
                route = AppRoute.CONVERSATION,
                arguments = listOf(
                    navArgument("coupleId") { type = NavType.StringType },
                    navArgument("conversationId") { type = NavType.StringType }
                ),
                deepLinks = listOf(
                    navDeepLink { uriPattern = "closer://closer.app/conversation/{coupleId}/{conversationId}" }
                )
            ) {
                ConversationScreen(onNavigate = navigateRoute)
            }
            composable(
                route = AppRoute.QUESTION_CATEGORY,
                arguments = listOf(navArgument("categoryId") { type = NavType.StringType })
            ) {
                QuestionCategoryScreen(
                    categoryId = it.arguments?.getString("categoryId") ?: "",
                    onNavigate = navigateRoute
                )
            }
            composable(route = AppRoute.QUESTION_COMPOSER) {
                QuestionComposerScreen(onNavigate = navigateRoute)
            }

            // Question Thread
            composable(
                route = AppRoute.QUESTION_THREAD,
                arguments = listOf(
                    navArgument("coupleId") { type = NavType.StringType },
                    navArgument("questionId") { type = NavType.StringType },
                    navArgument("prevId") {
                        type = NavType.StringType
                        nullable = true
                        defaultValue = null
                    },
                    navArgument("nextId") {
                        type = NavType.StringType
                        nullable = true
                        defaultValue = null
                    }
                ),
                // Lets the "your partner sent a message" notification open the conversation.
                deepLinks = listOf(
                    navDeepLink { uriPattern = "closer://closer.app/question_thread/{coupleId}/{questionId}" }
                )
            ) {
                QuestionThreadScreen(
                    coupleId = it.arguments?.getString("coupleId") ?: "",
                    questionId = it.arguments?.getString("questionId") ?: "",
                    previousQuestionId = it.arguments?.getString("prevId"),
                    nextQuestionId = it.arguments?.getString("nextId"),
                    onNavigate = navigateRoute,
                    onBack = navigateBackOrHome
                )
            }

            // Answers
            composable(
                route = AppRoute.ANSWER_REVEAL,
                arguments = listOf(navArgument("questionId") { type = NavType.StringType }),
                deepLinks = listOf(navDeepLink { uriPattern = "closer://closer.app/answer_reveal/{questionId}" })
            ) {
                AnswerRevealScreen(
                    questionId = it.arguments?.getString("questionId") ?: "",
                    onNavigate = navigateRoute
                )
            }
            composable(
                route = AppRoute.ANSWER_HISTORY,
                deepLinks = listOf(navDeepLink { uriPattern = "closer://closer.app/answer_history" })
            ) {
                AnswerHistoryScreen(onNavigate = navigateRoute)
            }

            // Pairing
            composable(route = AppRoute.CREATE_INVITE) {
                CreateInviteScreen(
                    onNavigate = navigateRoute,
                    onBack = { navController.popBackStack() }
                )
            }
            composable(route = AppRoute.ACCEPT_INVITE) {
                AcceptInviteScreen(
                    onNavigate = navigateRoute,
                    onBack = navigateBackOrHome
                )
            }
            composable(
                route = AppRoute.INVITE_CONFIRM,
                arguments = listOf(navArgument("inviteCode") { type = NavType.StringType })
            ) {
                InviteConfirmScreen(
                    inviteCode = it.arguments?.getString("inviteCode") ?: "",
                    onNavigate = navigateRoute,
                    onBack = navigateBackOrHome
                )
            }
            composable(
                route = AppRoute.PAIRING_SUCCESS,
                arguments = listOf(navArgument("coupleId") { type = NavType.StringType }),
                deepLinks = listOf(navDeepLink { uriPattern = "closer://closer.app/pairing_success/{coupleId}" })
            ) {
                PairingSuccessScreen(
                    coupleId = it.arguments?.getString("coupleId") ?: "",
                    onNavigate = { route ->
                        navController.navigate(route) {
                            popUpTo(0) { inclusive = true }
                        }
                    }
                )
            }

            composable(route = AppRoute.RECOVERY) {
                RecoveryScreen(
                    onRecovered = {
                        navController.navigate(AppRoute.HOME) {
                            popUpTo(AppRoute.RECOVERY) { inclusive = true }
                        }
                    }
                )
            }

            // Wheel / Category Selection
            composable(route = AppRoute.CATEGORY_PICKER) {
                CategoryPickerScreen(onNavigate = navigateRoute)
            }
            composable(route = AppRoute.SPIN_WHEEL_RANDOM) {
                SpinWheelScreen(
                    categoryId = "",
                    onNavigate = navigateRoute,
                    onBack = navigateBackOrHome
                )
            }
            composable(
                route = AppRoute.SPIN_WHEEL,
                arguments = listOf(navArgument("categoryId") { type = NavType.StringType })
            ) {
                SpinWheelScreen(
                    categoryId = it.arguments?.getString("categoryId") ?: "",
                    onNavigate = navigateRoute,
                    onBack = navigateBackOrHome
                )
            }
            composable(
                route = AppRoute.WHEEL_SESSION,
                arguments = listOf(navArgument("sessionId") { type = NavType.StringType })
            ) {
                WheelSessionScreen(
                    sessionId = it.arguments?.getString("sessionId") ?: "",
                    onNavigate = navigateRoute
                )
            }
            composable(
                route = AppRoute.WHEEL_COMPLETE,
                arguments = listOf(navArgument("sessionId") { type = NavType.StringType })
            ) {
                WheelCompleteScreen(
                    sessionId = it.arguments?.getString("sessionId") ?: "",
                    onNavigate = navigateRoute
                )
            }
            composable(route = AppRoute.WHEEL_HISTORY) {
                GameHistoryScreen(onNavigate = navigateRoute)
            }
            composable(route = AppRoute.GAME_HISTORY) {
                GameHistoryScreen(onNavigate = navigateRoute)
            }
            composable(
                route = AppRoute.THIS_OR_THAT_REPLAY,
                arguments = listOf(navArgument("sessionId") { type = NavType.StringType })
            ) {
                ThisOrThatReplayScreen(onNavigate = navigateRoute)
            }
            composable(
                route = AppRoute.DESIRE_SYNC_REPLAY,
                arguments = listOf(navArgument("sessionId") { type = NavType.StringType })
            ) {
                DSReplayScreen(onNavigate = navigateRoute)
            }
            composable(
                route = AppRoute.HOW_WELL_REPLAY,
                arguments = listOf(navArgument("sessionId") { type = NavType.StringType })
            ) {
                HowWellReplayScreen(onNavigate = navigateRoute)
            }
            composable(route = AppRoute.THIS_OR_THAT) {
                ThisOrThatScreen(onNavigate = navigateRoute)
            }
            composable(route = AppRoute.HOW_WELL) {
                HowWellScreen(onNavigate = navigateRoute)
            }
            composable(route = AppRoute.DESIRE_SYNC) {
                DesireSyncScreen(onNavigate = navigateRoute)
            }
            composable(
                route = AppRoute.CONNECTION_CHALLENGES,
                deepLinks = listOf(navDeepLink { uriPattern = "closer://closer.app/connection_challenges" })
            ) {
                ConnectionChallengesScreen(onNavigate = navigateRoute)
            }
            composable(
                route = AppRoute.MEMORY_LANE,
                deepLinks = listOf(navDeepLink { uriPattern = "closer://closer.app/memory_lane" })
            ) {
                MemoryLaneScreen(onNavigate = navigateRoute)
            }
            composable(
                route = AppRoute.MEMORY_LANE_CAPSULE,
                arguments = listOf(navArgument("capsuleId") { type = NavType.StringType })
            ) {
                MemoryLaneScreen(
                    onNavigate = navigateRoute,
                    startingCapsuleId = it.arguments?.getString("capsuleId")
                )
            }
            composable(route = AppRoute.WAITING_FOR_PARTNER) {
                WaitingForPartnerScreen(
                    onNavigate = navigateRoute
                )
            }

            // Dates
            composable(route = AppRoute.DATE_MATCH) {
                DateMatchScreen(onNavigate = navigateRoute)
            }
            composable(route = AppRoute.DATE_MATCHES) {
                DateMatchesScreen(onNavigate = navigateRoute)
            }
            composable(route = AppRoute.DATE_BUILDER) {
                DateBuilderScreen(onNavigate = navigateRoute)
            }
            composable(route = AppRoute.BUCKET_LIST) {
                BucketListScreen(onNavigate = navigateRoute)
            }

            // Paywall
            composable(route = AppRoute.PAYWALL) {
                PaywallScreen(onNavigate = navigateRoute)
            }

            // Settings
            composable(route = AppRoute.SETTINGS) {
                SettingsScreen(onNavigate = navigateRoute)
            }
            composable(route = AppRoute.ACCOUNT) {
                AccountScreen(onNavigate = navigateRoute)
            }
            composable(route = AppRoute.APPEARANCE) {
                AppearanceScreen(onNavigate = navigateRoute)
            }
            composable(route = AppRoute.NOTIFICATIONS) {
                NotificationSettingsScreen(onNavigate = navigateRoute)
            }
            composable(route = AppRoute.PRIVACY) {
                PrivacyScreen(onNavigate = navigateRoute)
            }
            composable(route = AppRoute.SUBSCRIPTION) {
                SubscriptionScreen(onNavigate = navigateRoute)
            }
            composable(route = AppRoute.RELATIONSHIP_SETTINGS) {
                RelationshipSettingsScreen(onNavigate = navigateRoute)
            }
            composable(route = AppRoute.DELETE_ACCOUNT) {
                DeleteAccountScreen(onNavigate = navigateRoute)
            }
            composable(route = AppRoute.SECURITY) {
                SecurityScreen(onNavigate = navigateRoute)
            }
            composable(route = AppRoute.YOUR_PROGRESS) {
                YourProgressScreen(
                    onBack = navigateBackOrHome
                )
            }
            composable(route = AppRoute.ACTIVITY) {
                ActivityScreen(onNavigate = navigateRoute)
            }
            composable(route = AppRoute.ART_PREVIEW) {
                app.closer.ui.debug.ArtPreviewScreen(onNavigate = navigateRoute)
            }
            composable(route = AppRoute.PAIRED_HOME_PREVIEW) {
                app.closer.ui.home.PairedHomePreviewScreen(onNavigate = navigateRoute)
            }
        }
    }

        // Floating in-app chat-head for incoming partner messages — drifts over every screen,
        // draggable, tap to open the conversation.
        app.closer.ui.components.MessageBubbleOverlay(
            onOpen = { c, conv -> navigateRoute(AppRoute.conversation(c, conv)) }
        )
    }
}

private data class TopLevelRoute(
    val route: String,
    val label: String,
    val icon: ImageVector
)

private val topLevelRoutes = listOf(
    TopLevelRoute(AppRoute.HOME, "Home", Icons.Filled.Home),
    TopLevelRoute(AppRoute.DAILY_QUESTION, "Today", Icons.Filled.Favorite),
    TopLevelRoute(AppRoute.PLAY, "Play", Icons.Filled.PlayArrow),
    TopLevelRoute(AppRoute.MESSAGES, "Messages", Icons.AutoMirrored.Filled.Chat),
    TopLevelRoute(AppRoute.SETTINGS, "Settings", Icons.Filled.Settings)
)

private val shellBackRoutes = setOf(
    AppRoute.PARTNER_HOME,
    AppRoute.QUESTION_CATEGORY,
    AppRoute.QUESTION_COMPOSER,
    AppRoute.QUESTION_THREAD,
    AppRoute.ANSWER_REVEAL,
    AppRoute.ANSWER_HISTORY,
    AppRoute.CATEGORY_PICKER,
    AppRoute.SPIN_WHEEL,
    AppRoute.WHEEL_SESSION,
    AppRoute.WHEEL_COMPLETE,
    AppRoute.DATE_MATCH,
    AppRoute.DATE_MATCHES,
    AppRoute.THIS_OR_THAT,
    AppRoute.HOW_WELL,
    AppRoute.DESIRE_SYNC,
    // NB: CONNECTION_CHALLENGES is intentionally NOT here — that screen renders its OWN
    // header (title + "Pick a series…" subtitle + back) for both the pick and active views.
    // Adding it to the shell set drew a SECOND "Connection Challenges" app bar + back arrow
    // on top of the screen's own (C-CC-001 duplicate header / double back).
    AppRoute.WAITING_FOR_PARTNER,
    AppRoute.SUBSCRIPTION,
    AppRoute.WHEEL_HISTORY,
    AppRoute.GAME_HISTORY,
    AppRoute.THIS_OR_THAT_REPLAY,
    AppRoute.DESIRE_SYNC_REPLAY,
    AppRoute.HOW_WELL_REPLAY,
)

@Composable
private fun AppBottomNavigation(
    currentRoute: String?,
    onRouteSelected: (String) -> Unit
) {
    NavigationBar {
        topLevelRoutes.forEach { item ->
            NavigationBarItem(
                selected = currentRoute == item.route,
                onClick = { onRouteSelected(item.route) },
                icon = {
                    Icon(
                        imageVector = item.icon,
                        contentDescription = item.label
                    )
                },
                label = { Text(item.label) }
            )
        }
    }
}
