package com.atridad.ascently.ui

import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import androidx.navigation.toRoute
import com.atridad.ascently.data.database.AscentlyDatabase
import com.atridad.ascently.data.repository.ClimbRepository
import com.atridad.ascently.data.sync.SyncService
import com.atridad.ascently.navigation.Screen
import com.atridad.ascently.navigation.bottomNavigationItems
import com.atridad.ascently.ui.components.NotificationPermissionDialog
import com.atridad.ascently.ui.screens.*
import com.atridad.ascently.ui.viewmodel.ClimbViewModel
import com.atridad.ascently.ui.viewmodel.ClimbViewModelFactory
import com.atridad.ascently.utils.AppLogger
import com.atridad.ascently.utils.AppShortcutManager
import com.atridad.ascently.utils.NotificationPermissionUtils

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AscentlyApp(
    shortcutAction: String? = null,
    lastUsedGymId: String? = null,
    onShortcutActionProcessed: () -> Unit = {},
) {
    val navController = rememberNavController()
    val context = LocalContext.current

    var lastUsedGym by remember { mutableStateOf<com.atridad.ascently.data.model.Gym?>(null) }

    val database = remember { AscentlyDatabase.getDatabase(context) }
    val repository = remember { ClimbRepository(database, context) }
    val syncService = remember { SyncService(context, repository) }
    val viewModel: ClimbViewModel =
        viewModel(factory = ClimbViewModelFactory(repository, syncService, context))

    var showNotificationPermissionDialog by remember { mutableStateOf(false) }
    var hasCheckedNotificationPermission by remember { mutableStateOf(false) }

    val permissionLauncher =
        rememberLauncherForActivityResult(
            contract = ActivityResultContracts.RequestPermission(),
        ) { isGranted: Boolean ->
            if (!isGranted) {
                showNotificationPermissionDialog = false
            }
        }

    LaunchedEffect(Unit) {
        if (!hasCheckedNotificationPermission) {
            hasCheckedNotificationPermission = true

            if (NotificationPermissionUtils.shouldRequestNotificationPermission() &&
                !NotificationPermissionUtils.isNotificationPermissionGranted(context)
            ) {
                showNotificationPermissionDialog = true
            }
        }
    }

    LaunchedEffect(Unit) { viewModel.ensureSessionTrackingServiceRunning(context) }

    LaunchedEffect(Unit) { syncService.triggerAutoSync() }

    val activeSession by viewModel.activeSession.collectAsState()
    val gyms by viewModel.gyms.collectAsState()

    LaunchedEffect(gyms) {
        if (gyms.isNotEmpty() && lastUsedGym == null) {
            lastUsedGym = viewModel.getLastUsedGym()
        }
    }

    LaunchedEffect(activeSession, gyms, lastUsedGym) {
        AppShortcutManager.updateShortcuts(
            context = context,
            hasActiveSession = activeSession != null,
            hasGyms = gyms.isNotEmpty(),
            lastUsedGym = if (activeSession == null && gyms.size > 1) lastUsedGym else null,
        )
    }

    LaunchedEffect(shortcutAction) {
        when (shortcutAction) {
            AppShortcutManager.ACTION_START_SESSION -> {
                navController.navigate(Screen.Sessions) {
                    popUpTo(0) { inclusive = true }
                    launchSingleTop = true
                }
            }

            AppShortcutManager.ACTION_END_SESSION -> {
                navController.navigate(Screen.Sessions) {
                    popUpTo(0) { inclusive = true }
                    launchSingleTop = true
                }

                activeSession?.let { session -> viewModel.endSession(context, session.id) }
            }
        }
    }

    LaunchedEffect(shortcutAction, activeSession, gyms, lastUsedGym) {
        if (shortcutAction == AppShortcutManager.ACTION_START_SESSION && gyms.isNotEmpty()) {
            AppLogger.d("AscentlyApp") { "Processing shortcut action: activeSession=$activeSession, gyms.size=${gyms.size}, lastUsedGymId=$lastUsedGymId, lastUsedGym=${lastUsedGym?.name}" }

            if (activeSession == null) {
                if (NotificationPermissionUtils.shouldRequestNotificationPermission() &&
                    !NotificationPermissionUtils.isNotificationPermissionGranted(
                        context,
                    )
                ) {
                    AppLogger.d("AscentlyApp") { "Showing notification permission dialog" }
                    showNotificationPermissionDialog = true
                } else {
                    if (gyms.size == 1) {
                        AppLogger.d("AscentlyApp") { "Starting session with single gym: ${gyms.first().name}" }
                        viewModel.startSession(context, gyms.first().id)
                    } else {
                        val targetGym =
                            lastUsedGymId?.let { gymId -> gyms.find { it.id == gymId } }
                                ?: lastUsedGym

                        if (targetGym != null) {
                            AppLogger.d("AscentlyApp") { "Starting session with target gym: ${targetGym.name}" }
                            viewModel.startSession(context, targetGym.id)
                        } else {
                            AppLogger.d("AscentlyApp") { "No target gym found, navigating to selection" }
                            navController.navigate(Screen.AddEditSession())
                        }
                    }
                }
            } else {
                AppLogger.d("AscentlyApp") { "Active session already exists: ${activeSession?.id}" }
            }

            onShortcutActionProcessed()
        }
    }

    var fabConfig by remember { mutableStateOf<FabConfig?>(null) }

    Scaffold(
        bottomBar = { AscentlyBottomNavigation(navController = navController) },
        floatingActionButton = {
            fabConfig?.let { config ->
                FloatingActionButton(
                    onClick = config.onClick,
                    containerColor = MaterialTheme.colorScheme.primary,
                ) {
                    Icon(
                        imageVector = config.icon,
                        contentDescription = config.contentDescription,
                    )
                }
            }
        },
    ) { innerPadding ->
        NavHost(
            navController = navController,
            startDestination = Screen.Sessions,
            modifier = Modifier.padding(innerPadding),
        ) {
            composable<Screen.Sessions> {
                LaunchedEffect(gyms, activeSession) {
                    fabConfig =
                        if (gyms.isNotEmpty() && activeSession == null) {
                            FabConfig(
                                icon = Icons.Default.PlayArrow,
                                contentDescription = "Start Session",
                                onClick = {
                                    if (NotificationPermissionUtils
                                            .shouldRequestNotificationPermission() &&
                                        !NotificationPermissionUtils
                                            .isNotificationPermissionGranted(
                                                context,
                                            )
                                    ) {
                                        showNotificationPermissionDialog = true
                                    } else {
                                        navController.navigate(Screen.AddEditSession())
                                    }
                                },
                            )
                        } else {
                            null
                        }
                }
                SessionsScreen(
                    viewModel = viewModel,
                    onNavigateToSessionDetail = { sessionId ->
                        navController.navigate(Screen.SessionDetail(sessionId))
                    },
                )
            }

            composable<Screen.Problems> {
                LaunchedEffect(gyms) {
                    fabConfig =
                        if (gyms.isNotEmpty()) {
                            FabConfig(
                                icon = Icons.Default.Add,
                                contentDescription = "Add Problem",
                                onClick = {
                                    navController.navigate(Screen.AddEditProblem())
                                },
                            )
                        } else {
                            null
                        }
                }
                ProblemsScreen(
                    viewModel = viewModel,
                    onNavigateToProblemDetail = { problemId ->
                        navController.navigate(Screen.ProblemDetail(problemId))
                    },
                )
            }

            composable<Screen.Analytics> {
                LaunchedEffect(Unit) { fabConfig = null }
                AnalyticsScreen(viewModel = viewModel)
            }

            composable<Screen.Gyms> {
                LaunchedEffect(Unit) {
                    fabConfig =
                        FabConfig(
                            icon = Icons.Default.Add,
                            contentDescription = "Add Gym",
                            onClick = { navController.navigate(Screen.AddEditGym()) },
                        )
                }
                GymsScreen(
                    viewModel = viewModel,
                    onNavigateToGymDetail = { gymId ->
                        navController.navigate(Screen.GymDetail(gymId))
                    },
                )
            }

            composable<Screen.Settings> {
                LaunchedEffect(Unit) { fabConfig = null }
                SettingsScreen(viewModel = viewModel)
            }

            composable<Screen.SessionDetail> { backStackEntry ->
                val args = backStackEntry.toRoute<Screen.SessionDetail>()
                LaunchedEffect(Unit) { fabConfig = null }
                SessionDetailScreen(
                    sessionId = args.sessionId,
                    viewModel = viewModel,
                    onNavigateBack = { navController.popBackStack() },
                    onNavigateToProblemDetail = { problemId ->
                        navController.navigate(Screen.ProblemDetail(problemId))
                    },
                )
            }

            composable<Screen.ProblemDetail> { backStackEntry ->
                val args = backStackEntry.toRoute<Screen.ProblemDetail>()
                LaunchedEffect(Unit) { fabConfig = null }
                ProblemDetailScreen(
                    problemId = args.problemId,
                    viewModel = viewModel,
                    onNavigateBack = { navController.popBackStack() },
                    onNavigateToEdit = { problemId ->
                        navController.navigate(Screen.AddEditProblem(problemId = problemId))
                    },
                )
            }

            composable<Screen.GymDetail> { backStackEntry ->
                val args = backStackEntry.toRoute<Screen.GymDetail>()
                LaunchedEffect(Unit) { fabConfig = null }
                GymDetailScreen(
                    gymId = args.gymId,
                    viewModel = viewModel,
                    onNavigateBack = { navController.popBackStack() },
                    onNavigateToEdit = { gymId ->
                        navController.navigate(Screen.AddEditGym(gymId = gymId))
                    },
                    onNavigateToSessionDetail = { sessionId ->
                        navController.navigate(Screen.SessionDetail(sessionId))
                    },
                    onNavigateToProblemDetail = { problemId ->
                        navController.navigate(Screen.ProblemDetail(problemId))
                    },
                )
            }

            composable<Screen.AddEditGym> { backStackEntry ->
                val args = backStackEntry.toRoute<Screen.AddEditGym>()
                LaunchedEffect(Unit) { fabConfig = null }
                AddEditGymScreen(
                    gymId = args.gymId,
                    viewModel = viewModel,
                    onNavigateBack = { navController.popBackStack() },
                )
            }

            composable<Screen.AddEditProblem> { backStackEntry ->
                val args = backStackEntry.toRoute<Screen.AddEditProblem>()
                LaunchedEffect(Unit) { fabConfig = null }
                AddEditProblemScreen(
                    problemId = args.problemId,
                    gymId = args.gymId,
                    viewModel = viewModel,
                    onNavigateBack = { navController.popBackStack() },
                )
            }

            composable<Screen.AddEditSession> { backStackEntry ->
                val args = backStackEntry.toRoute<Screen.AddEditSession>()
                LaunchedEffect(Unit) { fabConfig = null }
                AddEditSessionScreen(
                    sessionId = args.sessionId,
                    gymId = args.gymId,
                    viewModel = viewModel,
                    onNavigateBack = { navController.popBackStack() },
                )
            }
        }

        if (showNotificationPermissionDialog) {
            NotificationPermissionDialog(
                onDismiss = { showNotificationPermissionDialog = false },
                onRequestPermission = {
                    permissionLauncher.launch(
                        NotificationPermissionUtils.getNotificationPermissionString(),
                    )
                },
            )
        }
    }
}

@Composable
fun AscentlyBottomNavigation(navController: NavHostController) {
    val navBackStackEntry by navController.currentBackStackEntryAsState()
    val currentRoute = navBackStackEntry?.destination?.route

    NavigationBar {
        bottomNavigationItems.forEach { item ->
            val isSelected =
                when (item.screen) {
                    is Screen.Sessions -> currentRoute?.contains("Session") == true
                    is Screen.Problems -> currentRoute?.contains("Problem") == true
                    is Screen.Gyms -> currentRoute?.contains("Gym") == true
                    is Screen.Analytics -> currentRoute?.contains("Analytics") == true
                    is Screen.Settings -> currentRoute?.contains("Settings") == true
                    else -> currentRoute?.contains(item.screen::class.simpleName ?: "") == true
                }

            NavigationBarItem(
                icon = { Icon(item.icon, contentDescription = item.label) },
                label = { Text(item.label) },
                selected = isSelected,
                onClick = {
                    navController.navigate(item.screen) {
                        popUpTo(0) { inclusive = true }
                        launchSingleTop = true
                        // Don't restore state - always start fresh when switching tabs
                        restoreState = false
                    }
                },
            )
        }
    }
}

data class FabConfig(
    val icon: androidx.compose.ui.graphics.vector.ImageVector,
    val contentDescription: String,
    val onClick: () -> Unit,
)
