package com.github.nullptroma.wallenc.ui

import android.content.Intent
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.rounded.List
import androidx.compose.material.icons.rounded.Menu
import androidx.compose.material.icons.rounded.Settings
import androidx.compose.material.icons.rounded.Sync
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.navDeepLink
import com.github.nullptroma.wallenc.ui.elements.FloatingWallencNavigationBar
import com.github.nullptroma.wallenc.ui.navigation.NavBarItemData
import com.github.nullptroma.wallenc.ui.navigation.WallencDeepLinks
import com.github.nullptroma.wallenc.ui.navigation.matchesWallencDeepLink
import com.github.nullptroma.wallenc.ui.navigation.rememberNavigationState
import com.github.nullptroma.wallenc.ui.screens.main.MainRoute
import com.github.nullptroma.wallenc.ui.screens.main.MainScreen
import com.github.nullptroma.wallenc.ui.screens.main.MainViewModel
import com.github.nullptroma.wallenc.ui.screens.main.screens.tasks.TaskPipelineRoute
import com.github.nullptroma.wallenc.ui.screens.main.screens.tasks.TaskPipelineScreen
import com.github.nullptroma.wallenc.ui.screens.settings.SettingsRoute
import com.github.nullptroma.wallenc.ui.screens.settings.SettingsScreen
import com.github.nullptroma.wallenc.ui.screens.settings.SettingsViewModel
import com.github.nullptroma.wallenc.ui.screens.sync.StorageSyncRoute
import com.github.nullptroma.wallenc.ui.screens.sync.StorageSyncScreen
import com.github.nullptroma.wallenc.ui.screens.sync.StorageSyncViewModel
import com.github.nullptroma.wallenc.ui.theme.WallencTheme


@Composable
fun WallencUi(
    deepLinkPulse: Int = 0,
    deepLinkIntent: Intent = Intent(),
) {
    WallencTheme {
        Surface {
            WallencNavRoot(
                deepLinkPulse = deepLinkPulse,
                deepLinkIntent = deepLinkIntent,
            )
        }
    }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun WallencNavRoot(
    viewModel: WallencViewModel = hiltViewModel(),
    deepLinkPulse: Int = 0,
    deepLinkIntent: Intent = Intent(),
) {
    val navState = rememberNavigationState()

    val mainViewModel: MainViewModel = hiltViewModel()
    val settingsViewModel: SettingsViewModel = hiltViewModel()
    val storageSyncViewModel: StorageSyncViewModel = hiltViewModel()

    val topLevelRoutes = viewModel.routes

    LaunchedEffect(deepLinkPulse) {
        if (deepLinkPulse <= 0) return@LaunchedEffect
        if (!deepLinkIntent.matchesWallencDeepLink()) return@LaunchedEffect
        navState.navHostController.handleDeepLink(deepLinkIntent)
    }

    val topLevelNavBarItems = remember {
        mapOf(
            MainRoute::class.qualifiedName!! to NavBarItemData(
                R.string.nav_label_main, MainRoute::class.qualifiedName!!, Icons.Rounded.Menu
            ),
            TaskPipelineRoute::class.qualifiedName!! to NavBarItemData(
                R.string.task_pipeline_title,
                TaskPipelineRoute::class.qualifiedName!!,
                Icons.AutoMirrored.Rounded.List,
                R.string.task_pipeline_open,
            ),
            StorageSyncRoute::class.qualifiedName!! to NavBarItemData(
                R.string.nav_label_sync,
                StorageSyncRoute::class.qualifiedName!!,
                Icons.Rounded.Sync,
            ),
            SettingsRoute::class.qualifiedName!! to NavBarItemData(
                R.string.nav_label_settings,
                SettingsRoute::class.qualifiedName!!,
                Icons.Rounded.Settings,
            ),
        )
    }

    val navBackStackEntry by navState.navHostController.currentBackStackEntryAsState()
    val currentRoute = navBackStackEntry?.destination?.route

    Scaffold(
        bottomBar = {
            Box(
                modifier = Modifier
                    .navigationBarsPadding()
                    .padding(horizontal = 12.dp)
                    .padding(top = 4.dp, bottom = 6.dp),
            ) {
                FloatingWallencNavigationBar(
                    items = topLevelNavBarItems,
                    routes = topLevelRoutes,
                    currentRoute = currentRoute,
                    onNavigate = { item ->
                        val route = topLevelRoutes[item.screenRouteClass]
                            ?: error("Route ${item.screenRouteClass} not found")
                        if (currentRoute?.startsWith(item.screenRouteClass) != true) {
                            navState.changeTop(route)
                        }
                    },
                )
            }
        },
    ) { innerPaddings ->
        NavHost(
            navState.navHostController,
            startDestination = topLevelRoutes[MainRoute::class.qualifiedName]!!,
            modifier = Modifier.padding(innerPaddings),
        ) {
            composable<MainRoute>(
                deepLinks = listOf(
                    navDeepLink { uriPattern = WallencDeepLinks.MAIN_URI_PATTERN },
                ),
                enterTransition = {
                    fadeIn(tween(200))
                },
                exitTransition = {
                    fadeOut(tween(200))
                },
            ) {
                MainScreen(
                    modifier = Modifier,
                    viewModel = mainViewModel,
                )
            }
            composable<SettingsRoute>(
                deepLinks = listOf(
                    navDeepLink { uriPattern = WallencDeepLinks.SETTINGS_URI_PATTERN },
                ),
                enterTransition = {
                    fadeIn(tween(200))
                },
                exitTransition = {
                    fadeOut(tween(200))
                },
            ) {
                SettingsScreen(Modifier, settingsViewModel)
            }
            composable<StorageSyncRoute>(
                deepLinks = listOf(
                    navDeepLink { uriPattern = WallencDeepLinks.SYNC_URI_PATTERN },
                ),
                enterTransition = {
                    fadeIn(tween(200))
                },
                exitTransition = {
                    fadeOut(tween(200))
                },
            ) {
                StorageSyncScreen(
                    modifier = Modifier,
                    viewModel = storageSyncViewModel,
                )
            }
            composable<TaskPipelineRoute>(
                deepLinks = listOf(
                    navDeepLink { uriPattern = WallencDeepLinks.TASKS_URI_PATTERN },
                ),
                enterTransition = {
                    fadeIn(tween(200))
                },
                exitTransition = {
                    fadeOut(tween(200))
                },
            ) {
                TaskPipelineScreen(modifier = Modifier)
            }
        }
    }
}
