package com.swoosh.microblog.ui.navigation

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.animation.slideOutVertically
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.BarChart
import androidx.compose.material.icons.filled.Email
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.font.FontWeight
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import com.swoosh.microblog.data.model.FeedPost
import com.swoosh.microblog.data.model.GhostMember
import com.swoosh.microblog.ui.composer.ComposerScreen
import com.swoosh.microblog.ui.composer.ComposerViewModel
import com.swoosh.microblog.ui.detail.DetailScreen
import com.swoosh.microblog.ui.feed.FeedScreen
import com.swoosh.microblog.ui.pages.PagesScreen
import com.swoosh.microblog.ui.feed.FeedViewModel
import com.swoosh.microblog.ui.members.MemberDetailScreen
import com.swoosh.microblog.ui.members.MembersScreen
import com.swoosh.microblog.ui.newsletter.NewsletterScreen
import com.swoosh.microblog.ui.preview.PreviewScreen
import com.swoosh.microblog.ui.settings.SettingsScreen
import com.swoosh.microblog.ui.setup.SetupScreen
import com.swoosh.microblog.ui.stats.StatsScreen
import com.swoosh.microblog.ui.tags.TagsScreen
import com.swoosh.microblog.ui.theme.ThemeViewModel

object Routes {
    const val SETUP = "setup"
    const val FEED = "feed"
    const val SEARCH = "search"
    const val COMPOSER = "composer"
    const val DETAIL = "detail"
    const val SETTINGS = "settings"
    const val STATS = "stats"
    const val PREVIEW = "preview"
    const val ADD_ACCOUNT = "add_account"
    const val PAGES = "pages"
    const val MEMBERS = "members"
    const val MEMBER_DETAIL = "member_detail"
    const val TAGS = "tags"
    const val NEWSLETTER = "newsletter"
}

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

val bottomNavItems = listOf(
    BottomNavItem(Routes.FEED, "Home", Icons.Default.Home),
    BottomNavItem(Routes.NEWSLETTER, "Newsletter", Icons.Default.Email),
    BottomNavItem(Routes.STATS, "Stats", Icons.Default.BarChart),
    BottomNavItem(Routes.SETTINGS, "Settings", Icons.Default.Settings)
)

/** Routes where the bottom navigation bar should be visible */
private val bottomBarRoutes = setOf(Routes.FEED, Routes.NEWSLETTER, Routes.STATS, Routes.SETTINGS)

@Composable
fun SwooshNavGraph(
    navController: NavHostController,
    startDestination: String,
    themeViewModel: ThemeViewModel
) {
    // Shared state for passing posts between screens
    var selectedPost by remember { mutableStateOf<FeedPost?>(null) }
    var editPost by remember { mutableStateOf<FeedPost?>(null) }
    var previewHtml by remember { mutableStateOf("") }
    var selectedMember by remember { mutableStateOf<GhostMember?>(null) }

    val feedViewModel: FeedViewModel = viewModel()

    val navBackStackEntry by navController.currentBackStackEntryAsState()
    val currentRoute = navBackStackEntry?.destination?.route
    val showBottomBar = currentRoute in bottomBarRoutes

    Scaffold(
        bottomBar = {
            AnimatedVisibility(
                visible = showBottomBar,
                enter = slideInVertically(initialOffsetY = { it }) + fadeIn(tween(150)),
                exit = slideOutVertically(targetOffsetY = { it }) + fadeOut(tween(100))
            ) {
                NavigationBar {
                    bottomNavItems.forEach { item ->
                        val selected = currentRoute == item.route
                        NavigationBarItem(
                            selected = selected,
                            onClick = {
                                if (item.route == Routes.FEED) {
                                    feedViewModel.deactivateSearch()
                                    feedViewModel.refreshTagsEnabled()
                                }
                                navController.navigate(item.route) {
                                    popUpTo(navController.graph.findStartDestination().id) {
                                        saveState = true
                                    }
                                    launchSingleTop = true
                                    restoreState = true
                                }
                            },
                            icon = {
                                Icon(
                                    imageVector = item.icon,
                                    contentDescription = item.label
                                )
                            },
                            label = {
                                Text(
                                    text = item.label,
                                    style = MaterialTheme.typography.labelMedium.copy(
                                        fontWeight = FontWeight.SemiBold
                                    )
                                )
                            },
                            colors = NavigationBarItemDefaults.colors(
                                selectedIconColor = MaterialTheme.colorScheme.primary,
                                selectedTextColor = MaterialTheme.colorScheme.primary,
                                unselectedIconColor = MaterialTheme.colorScheme.onSurfaceVariant,
                                unselectedTextColor = MaterialTheme.colorScheme.onSurfaceVariant
                            )
                        )
                    }
                }
            }
        }
    ) { scaffoldPadding ->
        NavHost(
            navController = navController,
            startDestination = startDestination,
            modifier = Modifier.padding(scaffoldPadding)
        ) {
            composable(
                Routes.SETUP,
                enterTransition = { fadeIn(tween(300)) },
                exitTransition = { fadeOut(tween(200)) }
            ) {
                SetupScreen(
                    onSetupComplete = {
                        feedViewModel.refresh()
                        navController.navigate(Routes.FEED) {
                            popUpTo(Routes.SETUP) { inclusive = true }
                        }
                    }
                )
            }

            composable(
                Routes.FEED,
                enterTransition = { fadeIn(tween(200)) },
                exitTransition = { fadeOut(tween(150)) },
                popEnterTransition = { fadeIn(tween(200)) },
                popExitTransition = { fadeOut(tween(150)) }
            ) {
                FeedScreen(
                    viewModel = feedViewModel,
                    onPostClick = { post ->
                        selectedPost = post
                        navController.navigate(Routes.DETAIL)
                    },
                    onCompose = {
                        editPost = null
                        navController.navigate(Routes.COMPOSER)
                    },
                    onEditPost = { post ->
                        editPost = post
                        navController.navigate(Routes.COMPOSER)
                    },
                    onAddAccount = {
                        navController.navigate(Routes.ADD_ACCOUNT)
                    }
                )
            }

            composable(
                Routes.COMPOSER,
                enterTransition = { slideInVertically(initialOffsetY = { it }, animationSpec = tween(250)) + fadeIn(tween(200)) },
                exitTransition = { fadeOut(tween(150)) },
                popEnterTransition = { fadeIn(tween(200)) },
                popExitTransition = { slideOutVertically(targetOffsetY = { it }, animationSpec = tween(200)) + fadeOut(tween(150)) }
            ) {
                val composerViewModel: ComposerViewModel = viewModel()
                ComposerScreen(
                    editPost = editPost,
                    viewModel = composerViewModel,
                    onDismiss = {
                        feedViewModel.refresh()
                        navController.popBackStack()
                    },
                    onFullScreenPreview = { html ->
                        previewHtml = html
                        navController.navigate(Routes.PREVIEW)
                    }
                )
            }

            composable(
                Routes.DETAIL,
                enterTransition = { slideInHorizontally(initialOffsetX = { it }, animationSpec = tween(250)) + fadeIn(tween(200)) },
                exitTransition = { fadeOut(tween(150)) },
                popEnterTransition = { fadeIn(tween(200)) },
                popExitTransition = { slideOutHorizontally(targetOffsetX = { it }, animationSpec = tween(200)) + fadeOut(tween(150)) }
            ) {
                val post = selectedPost
                if (post != null) {
                    DetailScreen(
                        post = post,
                        onBack = { navController.popBackStack() },
                        onEdit = { p ->
                            editPost = p
                            navController.navigate(Routes.COMPOSER)
                        },
                        onDelete = { p ->
                            feedViewModel.deletePost(p)
                            navController.popBackStack()
                        },
                        onPreview = { html ->
                            previewHtml = html
                            navController.navigate(Routes.PREVIEW)
                        },
                        onTogglePin = { p ->
                            feedViewModel.toggleFeatured(p)
                            // Update selected post so UI reflects the change
                            selectedPost = p.copy(featured = !p.featured)
                        }
                    )
                }
            }

            composable(
                Routes.SETTINGS,
                enterTransition = { fadeIn(tween(200)) },
                exitTransition = { fadeOut(tween(150)) },
                popEnterTransition = { fadeIn(tween(200)) },
                popExitTransition = { fadeOut(tween(150)) }
            ) {
                SettingsScreen(
                    themeViewModel = themeViewModel,
                    onBack = {
                        feedViewModel.refreshAccountsList()
                        feedViewModel.refresh()
                        navController.navigate(Routes.FEED) {
                            popUpTo(navController.graph.findStartDestination().id) {
                                saveState = true
                            }
                            launchSingleTop = true
                        }
                    },
                    onLogout = {
                        navController.navigate(Routes.SETUP) {
                            popUpTo(0) { inclusive = true }
                        }
                    },
                    onNavigateToPages = {
                        navController.navigate(Routes.PAGES)
                    },
                    onNavigateToTags = {
                        navController.navigate(Routes.TAGS)
                    }
                )
            }

            composable(
                Routes.STATS,
                enterTransition = { fadeIn(tween(200)) },
                exitTransition = { fadeOut(tween(150)) },
                popEnterTransition = { fadeIn(tween(200)) },
                popExitTransition = { fadeOut(tween(150)) }
            ) {
                StatsScreen(
                    onNavigateToMembers = {
                        navController.navigate(Routes.MEMBERS)
                    }
                )
            }

            composable(
                Routes.NEWSLETTER,
                enterTransition = { fadeIn(tween(200)) },
                exitTransition = { fadeOut(tween(150)) },
                popEnterTransition = { fadeIn(tween(200)) },
                popExitTransition = { fadeOut(tween(150)) }
            ) {
                NewsletterScreen()
            }

            composable(
                Routes.TAGS,
                enterTransition = { slideInHorizontally(initialOffsetX = { it }, animationSpec = tween(250)) + fadeIn(tween(200)) },
                exitTransition = { fadeOut(tween(150)) },
                popEnterTransition = { fadeIn(tween(200)) },
                popExitTransition = { slideOutHorizontally(targetOffsetX = { it }, animationSpec = tween(200)) + fadeOut(tween(150)) }
            ) {
                TagsScreen(
                    onBack = { navController.popBackStack() }
                )
            }

            composable(
                Routes.PREVIEW,
                enterTransition = { slideInVertically(initialOffsetY = { it }, animationSpec = tween(250)) + fadeIn(tween(200)) },
                exitTransition = { fadeOut(tween(150)) },
                popEnterTransition = { fadeIn(tween(200)) },
                popExitTransition = { slideOutVertically(targetOffsetY = { it }, animationSpec = tween(200)) + fadeOut(tween(150)) }
            ) {
                PreviewScreen(
                    html = previewHtml,
                    onBack = { navController.popBackStack() }
                )
            }

            composable(
                Routes.ADD_ACCOUNT,
                enterTransition = { slideInVertically(initialOffsetY = { it }, animationSpec = tween(250)) + fadeIn(tween(200)) },
                exitTransition = { fadeOut(tween(150)) },
                popEnterTransition = { fadeIn(tween(200)) },
                popExitTransition = { slideOutVertically(targetOffsetY = { it }, animationSpec = tween(200)) + fadeOut(tween(150)) }
            ) {
                SetupScreen(
                    onSetupComplete = {
                        feedViewModel.refreshAccountsList()
                        feedViewModel.refresh()
                        navController.popBackStack()
                    },
                    onBack = {
                        navController.popBackStack()
                    }
                )
            }

            composable(
                Routes.PAGES,
                enterTransition = { slideInHorizontally(initialOffsetX = { it }, animationSpec = tween(250)) + fadeIn(tween(200)) },
                exitTransition = { fadeOut(tween(150)) },
                popEnterTransition = { fadeIn(tween(200)) },
                popExitTransition = { slideOutHorizontally(targetOffsetX = { it }, animationSpec = tween(200)) + fadeOut(tween(150)) }
            ) {
                PagesScreen(
                    onBack = { navController.popBackStack() }
                )
            }

            composable(
                Routes.MEMBERS,
                enterTransition = { slideInHorizontally(initialOffsetX = { it }, animationSpec = tween(250)) + fadeIn(tween(200)) },
                exitTransition = { fadeOut(tween(150)) },
                popEnterTransition = { fadeIn(tween(200)) },
                popExitTransition = { slideOutHorizontally(targetOffsetX = { it }, animationSpec = tween(200)) + fadeOut(tween(150)) }
            ) {
                MembersScreen(
                    onMemberClick = { member ->
                        selectedMember = member
                        navController.navigate(Routes.MEMBER_DETAIL)
                    },
                    onBack = { navController.popBackStack() }
                )
            }

            composable(
                Routes.MEMBER_DETAIL,
                enterTransition = { slideInHorizontally(initialOffsetX = { it }, animationSpec = tween(250)) + fadeIn(tween(200)) },
                exitTransition = { fadeOut(tween(150)) },
                popEnterTransition = { fadeIn(tween(200)) },
                popExitTransition = { slideOutHorizontally(targetOffsetX = { it }, animationSpec = tween(200)) + fadeOut(tween(150)) }
            ) {
                val member = selectedMember
                if (member != null) {
                    MemberDetailScreen(
                        member = member,
                        onBack = { navController.popBackStack() }
                    )
                }
            }
        }
    }
}
