package com.seven.ikar.kotlin.app

import android.net.Uri
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import androidx.navigation.NavType
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
import com.seven.ikar.kotlin.core.model.ChatType
import com.seven.ikar.kotlin.core.settings.AppLocaleManager
import com.seven.ikar.kotlin.feature.archive.ArchiveExtractorScreen
import com.seven.ikar.kotlin.feature.archive.ArchiveExtractorViewModel
import com.seven.ikar.kotlin.feature.bots.BotEditorScreen
import com.seven.ikar.kotlin.feature.bots.BotEditorViewModel
import com.seven.ikar.kotlin.feature.bots.BotsScreen
import com.seven.ikar.kotlin.feature.bots.BotsViewModel
import com.seven.ikar.kotlin.feature.call.CallScreen
import com.seven.ikar.kotlin.core.push.AndroidActiveChatState
import com.seven.ikar.kotlin.feature.chat.ChatScreen
import com.seven.ikar.kotlin.feature.chat.ChatViewModel
import com.seven.ikar.kotlin.feature.chatinfo.ChatInfoScreen
import com.seven.ikar.kotlin.feature.chatinfo.ChatInfoViewModel
import com.seven.ikar.kotlin.feature.chats.ChatsScreen
import com.seven.ikar.kotlin.feature.chats.ChatsViewModel
import com.seven.ikar.kotlin.feature.contacts.ContactsScreen
import com.seven.ikar.kotlin.feature.contacts.ContactsViewModel
import com.seven.ikar.kotlin.feature.devices.DevicesScreen
import com.seven.ikar.kotlin.feature.devices.DevicesViewModel
import com.seven.ikar.kotlin.feature.discover.DiscoverScreen
import com.seven.ikar.kotlin.feature.discover.DiscoverViewModel
import com.seven.ikar.kotlin.feature.folders.ChatFoldersScreen
import com.seven.ikar.kotlin.feature.folders.ChatFoldersViewModel
import com.seven.ikar.kotlin.feature.forward.ForwardScreen
import com.seven.ikar.kotlin.feature.forward.ForwardViewModel
import com.seven.ikar.kotlin.feature.login.LoginScreen
import com.seven.ikar.kotlin.feature.login.LoginViewModel
import com.seven.ikar.kotlin.feature.mainmenu.MainMenuViewModel
import com.seven.ikar.kotlin.feature.members.ChatMembersScreen
import com.seven.ikar.kotlin.feature.members.ChatMembersViewModel
import com.seven.ikar.kotlin.feature.profile.AccountSettingsScreen
import com.seven.ikar.kotlin.feature.profile.PeerProfileScreen
import com.seven.ikar.kotlin.feature.profile.PeerProfileViewModel
import com.seven.ikar.kotlin.feature.profile.ProfileScreen
import com.seven.ikar.kotlin.feature.profile.ProfileViewModel
import com.seven.ikar.kotlin.feature.privacy.PrivacySecurityScreen
import com.seven.ikar.kotlin.feature.privacy.PrivacySecurityViewModel
import com.seven.ikar.kotlin.feature.search.GlobalSearchScreen
import com.seven.ikar.kotlin.feature.search.GlobalSearchViewModel
import com.seven.ikar.kotlin.feature.settings.ChatSettingsScreen
import com.seven.ikar.kotlin.feature.settings.ChatNotificationSettingsScreen
import com.seven.ikar.kotlin.feature.settings.ChatNotificationSettingsViewModel
import com.seven.ikar.kotlin.feature.settings.ChatWallpaperScreen
import com.seven.ikar.kotlin.feature.settings.ChatSettingsViewModel
import com.seven.ikar.kotlin.feature.settings.AppSettingsViewModel
import com.seven.ikar.kotlin.feature.settings.BlockedUsersPlaceholderScreen
import com.seven.ikar.kotlin.feature.settings.DataStorageSettingsScreen
import com.seven.ikar.kotlin.feature.settings.LanguagePlaceholderScreen
import com.seven.ikar.kotlin.feature.settings.NotificationSettingsScreen
import com.seven.ikar.kotlin.feature.settings.NotificationSettingsViewModel
import com.seven.ikar.kotlin.feature.settings.PrivacyExceptionsPlaceholderScreen
import com.seven.ikar.kotlin.feature.settings.ProxyPlaceholderScreen
import com.seven.ikar.kotlin.feature.settings.SettingsScreen
import com.seven.ikar.kotlin.feature.settings.SettingsViewModel
import com.seven.ikar.kotlin.feature.settings.ThemePlaceholderScreen
import com.seven.ikar.kotlin.feature.stories.StoriesScreen
import com.seven.ikar.kotlin.feature.stories.StoriesViewModel
import com.seven.ikar.kotlin.feature.stories.StoryComposerScreen
import com.seven.ikar.kotlin.feature.update.AppUpdateScreen
import com.seven.ikar.kotlin.feature.update.AppUpdateViewModel
import com.seven.ikar.kotlin.ui.LocalIkarAccessToken
import com.seven.ikar.kotlin.ui.LocalUnreadChatsCount
import com.seven.ikar.kotlin.ui.theme.IkarKotlinTheme
import kotlinx.coroutines.launch

private const val ChatRoutePattern = "chat/{chatId}?messageId={messageId}&scrollToLatest={scrollToLatest}&scrollRequestId={scrollRequestId}"

private fun chatRoute(
    chatId: String,
    messageId: String? = null,
    scrollToLatest: Boolean = false,
    scrollRequestId: Long? = null
): String {
    val query = buildList {
        messageId?.takeIf { it.isNotBlank() }?.let { add("messageId=${Uri.encode(it)}") }
        if (scrollToLatest) {
            add("scrollToLatest=true")
        }
        scrollRequestId?.let { add("scrollRequestId=$it") }
    }
    val route = "chat/${Uri.encode(chatId)}"
    return if (query.isEmpty()) route else "$route?${query.joinToString("&")}"
}

@Composable
fun IkarApp() {
    val context = LocalContext.current
    val application = context.applicationContext as IkarNativeApp
    val navController = rememberNavController()
    val currentBackStackEntry by navController.currentBackStackEntryAsState()
    val activeCall by application.container.callManager.currentCall.collectAsStateWithLifecycle()
    val pendingShare by application.container.incomingShareStore.pendingShare.collectAsStateWithLifecycle()
    val pendingArchive by application.container.incomingArchiveStore.pendingArchive.collectAsStateWithLifecycle()
    val pendingCallInvite by application.container.incomingCallInviteStore.pendingInvite.collectAsStateWithLifecycle()
    val pendingPushNavigation by application.container.incomingPushNavigationStore.pendingNavigation.collectAsStateWithLifecycle()
    val appSettings by application.container.appSettings.snapshot.collectAsStateWithLifecycle()
    val isAppLocked by application.container.appLockState.isLocked.collectAsStateWithLifecycle()
    val mainMenuViewModel: MainMenuViewModel = viewModel(
        factory = viewModelFactory {
            initializer { MainMenuViewModel(application.container) }
        }
    )
    val mainMenuState by mainMenuViewModel.uiState.collectAsStateWithLifecycle()
    var currentAccessToken by rememberSaveable { mutableStateOf(application.container.sessionStore.read()?.accessToken) }
    var startDestination by rememberSaveable { mutableStateOf("bootstrap") }

    fun navigatePrimary(route: String) {
        if (currentBackStackEntry?.destination?.route == route) {
            return
        }

        navController.navigate(route) {
            popUpTo(navController.graph.findStartDestination().id) { saveState = true }
            launchSingleTop = true
            restoreState = true
        }
    }

    fun logoutAndReturnToLogin() {
        application.container.realtimeService.disconnect()
        application.container.applicationScope.launch {
            runCatching { application.container.pushRegistrationManager.unregisterCurrentDeviceAsync() }
        }
        application.container.sessionStore.clear()
        currentAccessToken = null
        mainMenuViewModel.clear()
        navController.navigate("login") {
            popUpTo(0)
            launchSingleTop = true
        }
    }

    LaunchedEffect(Unit) {
        val session = application.container.sessionStore.read()
        currentAccessToken = session?.accessToken
        startDestination = if (session == null) "login" else "chats"
    }

    LaunchedEffect(appSettings.languageMode) {
        AppLocaleManager.apply(context, appSettings.languageMode)
    }

    IkarKotlinTheme(settings = appSettings) {
        CompositionLocalProvider(
            LocalUnreadChatsCount provides mainMenuState.unreadChatsCount,
            LocalIkarAccessToken provides currentAccessToken
        ) {
            if (startDestination != "bootstrap") {
                Box(modifier = Modifier.fillMaxSize()) {
                    NavHost(navController = navController, startDestination = startDestination) {
                    composable("login") {
                        val viewModel: LoginViewModel = viewModel(
                            factory = viewModelFactory {
                                initializer { LoginViewModel(application.container) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        if (state.isAuthenticated) {
                            LaunchedEffect(state.isAuthenticated) {
                                currentAccessToken = application.container.sessionStore.read()?.accessToken
                                mainMenuViewModel.refresh()
                                navController.navigate("chats") {
                                    popUpTo("login") { inclusive = true }
                                }
                            }
                        }
                        LoginScreen(
                            state = state,
                            onPhoneNumberChanged = viewModel::updatePhoneNumber,
                            onDisplayNameChanged = viewModel::updateDisplayName,
                            onVerificationCodeChanged = viewModel::updateVerificationCode,
                            onRequestCodeClick = viewModel::requestCode,
                            onVerifyCodeClick = viewModel::verifyCode,
                            onChangePhoneNumberClick = viewModel::changePhoneNumber
                        )
                    }

                    composable("chats") {
                        val viewModel: ChatsViewModel = viewModel(
                            factory = viewModelFactory {
                                initializer { ChatsViewModel(application.container) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        val chatSettings by application.container.chatSettings.snapshot.collectAsStateWithLifecycle()
                        LaunchedEffect(state.pendingShareNavigation?.requestId) {
                            val target = state.pendingShareNavigation ?: return@LaunchedEffect
                            viewModel.consumePendingShareNavigation()
                            navController.navigate(
                                chatRoute(
                                    chatId = target.chatId,
                                    messageId = target.messageId,
                                    scrollToLatest = target.scrollToLatest,
                                    scrollRequestId = target.requestId
                                )
                            )
                        }
                        ChatsScreen(
                            state = state,
                            chatSettings = chatSettings,
                            onChatClick = { chat ->
                                if (state.isShareMode) {
                                    viewModel.sendShareToChat(chat)
                                } else {
                                    navController.navigate("chat/${chat.id}")
                                }
                            },
                            onChatSelectionClick = viewModel::handleChatSelectionTap,
                            onChatLongPress = viewModel::handleChatLongPress,
                            onClearSelection = viewModel::clearSelection,
                            onSendSelectedChatsClick = viewModel::sendShareToSelectedChats,
                            onDismissPendingShare = viewModel::dismissPendingShare,
                            onDeleteSelectedClick = viewModel::showDeleteDialog,
                            onPinSelectedChatsClick = viewModel::togglePinSelectedChats,
                            onArchiveSelectedChatsClick = viewModel::archiveSelectedChats,
                            onMuteSelectedChatsClick = viewModel::muteSelectedChats,
                            onDismissDeleteDialog = viewModel::dismissDeleteDialog,
                            onDeleteForEveryoneChanged = viewModel::updateDeleteForEveryone,
                            onConfirmDeleteSelected = viewModel::confirmDeleteSelected,
                            onLogoutClick = {
                                viewModel.logout()
                                currentAccessToken = null
                                mainMenuViewModel.clear()
                                navController.navigate("login") {
                                    popUpTo("chats") { inclusive = true }
                                }
                            },
                            onRefreshClick = viewModel::refresh,
                            onProfileClick = { navigatePrimary("profile") },
                            onContactsClick = { navigatePrimary("contacts") },
                            onDiscoverClick = { navController.navigate("discover") },
                            onComposeStoryClick = { navController.navigate("stories/compose") },
                            onStoryClick = { story -> navController.navigate("stories/view/${story.id}") },
                            onSettingsClick = { navigatePrimary("settings") },
                            onNotificationsClick = { navController.navigate("settings/notifications") },
                            onGlobalSearchClick = { navController.navigate("search") },
                            onQueryChanged = viewModel::updateQuery
                        )
                    }

                    composable("search") {
                        val viewModel: GlobalSearchViewModel = viewModel(
                            factory = viewModelFactory {
                                initializer { GlobalSearchViewModel(application.container) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        GlobalSearchScreen(
                            state = state,
                            onBackClick = { navController.popBackStack() },
                            onQueryChanged = viewModel::updateQuery,
                            onFilterChanged = viewModel::updateFilter,
                            onDateFilterChanged = viewModel::updateDateFilter,
                            onResultTypeChanged = viewModel::updateResultType,
                            onAuthorFilterChanged = viewModel::updateAuthorFilter,
                            onLoadMore = viewModel::loadMore,
                            onResultClick = { result ->
                                val messageId = result.message?.id
                                if (messageId == null) {
                                    navController.navigate(chatRoute(result.chat.id))
                                } else {
                                    navController.navigate(chatRoute(result.chat.id, messageId = messageId))
                                }
                            }
                        )
                    }

                    composable(
                        route = ChatRoutePattern,
                        arguments = listOf(
                            navArgument("chatId") { type = NavType.StringType },
                            navArgument("messageId") {
                                type = NavType.StringType
                                nullable = true
                                defaultValue = null
                            },
                            navArgument("scrollToLatest") {
                                type = NavType.BoolType
                                defaultValue = false
                            },
                            navArgument("scrollRequestId") {
                                type = NavType.StringType
                                nullable = true
                                defaultValue = null
                            }
                        )
                    ) { backStackEntry ->
                        val chatId = backStackEntry.arguments?.getString("chatId").orEmpty()
                        val messageId = backStackEntry.arguments?.getString("messageId")?.takeIf { it.isNotBlank() }
                        val scrollToLatest = backStackEntry.arguments?.getBoolean("scrollToLatest") ?: false
                        val scrollRequestId = backStackEntry.arguments?.getString("scrollRequestId")
                        val viewModel: ChatViewModel = viewModel(
                            key = "chat-$chatId",
                            factory = viewModelFactory {
                                initializer { ChatViewModel(application.container, chatId) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        val chatSettings by application.container.chatSettings.snapshot.collectAsStateWithLifecycle()
                        LaunchedEffect(messageId, scrollToLatest, scrollRequestId) {
                            if (scrollRequestId != null) {
                                viewModel.refresh()
                            }
                            when {
                                messageId != null -> viewModel.requestScrollToMessage(messageId)
                                scrollToLatest -> viewModel.requestScrollToLatest()
                            }
                        }
                        ChatScreen(
                            state = state,
                            viewModel = viewModel,
                            chatSettings = chatSettings,
                            onBackClick = { navController.popBackStack() },
                            onPeerProfileClick = state.peer?.id?.let { userId ->
                                { navController.navigate("profile/user/$userId") }
                            } ?: when {
                                state.chatType != ChatType.Direct -> {
                                    { navController.navigate("chat/$chatId/info") }
                                }
                                else -> null
                            },
                            onChatNotificationsClick = {
                                val encodedTitle = Uri.encode(state.title.ifBlank { "Чат" })
                                navController.navigate("chat/$chatId/notifications?title=$encodedTitle")
                            },
                            onChatWallpaperClick = { navController.navigate("settings/chats/wallpaper") },
                            onForwardMessage = { message ->
                                if (!message.hasProtectedContent) {
                                    navController.navigate("forward/${message.chatId}/${message.id}")
                                }
                            }
                        )
                    }

                    composable(
                        route = "chat/{chatId}/notifications?title={title}",
                        arguments = listOf(
                            navArgument("chatId") { type = NavType.StringType },
                            navArgument("title") {
                                type = NavType.StringType
                                nullable = true
                                defaultValue = null
                            }
                        )
                    ) { backStackEntry ->
                        val chatId = backStackEntry.arguments?.getString("chatId").orEmpty()
                        val title = backStackEntry.arguments?.getString("title").orEmpty()
                        val viewModel: ChatNotificationSettingsViewModel = viewModel(
                            key = "chat-notifications-$chatId",
                            factory = viewModelFactory {
                                initializer {
                                    ChatNotificationSettingsViewModel(
                                        application.container,
                                        chatId,
                                        title
                                    )
                                }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        ChatNotificationSettingsScreen(
                            state = state,
                            messageSoundOptions = viewModel.messageSoundOptions,
                            onBackClick = { navController.popBackStack() },
                            onSnapshotChanged = { snapshot -> viewModel.updateSnapshot { snapshot } },
                            onMessageSoundChanged = viewModel::setMessageSound,
                            onResetClick = viewModel::reset
                        )
                    }

                    composable(
                        route = "chat/{chatId}/members",
                        arguments = listOf(navArgument("chatId") { type = NavType.StringType })
                    ) { backStackEntry ->
                        val chatId = backStackEntry.arguments?.getString("chatId").orEmpty()
                        val viewModel: ChatMembersViewModel = viewModel(
                            key = "chat-members-$chatId",
                            factory = viewModelFactory {
                                initializer { ChatMembersViewModel(application.container, chatId) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        ChatMembersScreen(
                            state = state,
                            onBackClick = { navController.popBackStack() },
                            onRefreshClick = viewModel::refresh,
                            onToggleAdmin = viewModel::toggleAdmin,
                            onToggleCanPost = viewModel::toggleCanPost,
                            onToggleCanPin = viewModel::toggleCanPin,
                            onToggleCanDelete = viewModel::toggleCanDelete,
                            onToggleCanInvite = viewModel::toggleCanInvite,
                            onMemberSearchChanged = viewModel::updateMemberSearchQuery,
                            onAddMember = { user -> viewModel.addMember(user, asAdmin = false) },
                            onAddAdmin = { user -> viewModel.addMember(user, asAdmin = true) },
                            onApproveJoinRequest = viewModel::approveJoinRequest,
                            onDeclineJoinRequest = viewModel::declineJoinRequest
                        )
                    }

                    composable(
                        route = "chat/{chatId}/info",
                        arguments = listOf(navArgument("chatId") { type = NavType.StringType })
                    ) { backStackEntry ->
                        val chatId = backStackEntry.arguments?.getString("chatId").orEmpty()
                        val viewModel: ChatInfoViewModel = viewModel(
                            key = "chat-info-$chatId",
                            factory = viewModelFactory {
                                initializer { ChatInfoViewModel(application.container, chatId) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        ChatInfoScreen(
                            state = state,
                            onBackClick = { navController.popBackStack() },
                            onRefreshClick = viewModel::refresh,
                            onMembersClick = { navController.navigate("chat/$chatId/members") },
                            onSearchClick = { navController.navigate("search") },
                            onInviteTitleChanged = viewModel::updateInviteTitle,
                            onInviteJoinRequestChanged = viewModel::updateInviteCreatesJoinRequest,
                            onCreateInviteClick = viewModel::createInviteLink,
                            onRevokeInviteClick = viewModel::revokeInviteLink,
                            onTopicTitleChanged = viewModel::updateTopicTitle,
                            onCreateTopicClick = viewModel::createTopic
                        )
                    }

                    composable(
                        route = "profile/user/{userId}",
                        arguments = listOf(navArgument("userId") { type = NavType.StringType })
                    ) { backStackEntry ->
                        val userId = backStackEntry.arguments?.getString("userId").orEmpty()
                        val viewModel: PeerProfileViewModel = viewModel(
                            key = "peer-profile-$userId",
                            factory = viewModelFactory {
                                initializer { PeerProfileViewModel(application.container, userId) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        PeerProfileScreen(
                            state = state,
                            onBackClick = { navController.popBackStack() },
                            onRefreshClick = viewModel::refresh
                        )
                    }

                    composable("profile") {
                        val viewModel: ProfileViewModel = viewModel(
                            factory = viewModelFactory {
                                initializer { ProfileViewModel(application.container) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        ProfileScreen(
                            state = state,
                            onSettingsClick = { navController.navigate("settings/account") },
                            onLogoutClick = ::logoutAndReturnToLogin,
                            onManageAvatarClick = viewModel::uploadAvatar,
                            onChatsClick = { navigatePrimary("chats") },
                            onContactsClick = { navigatePrimary("contacts") },
                            onProfileClick = { navigatePrimary("profile") },
                            onSettingsTabClick = { navigatePrimary("settings") }
                        )
                    }

                    composable("settings/account") {
                        val viewModel: ProfileViewModel = viewModel(
                            key = "account-settings",
                            factory = viewModelFactory {
                                initializer { ProfileViewModel(application.container) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        AccountSettingsScreen(
                            state = state,
                            onBackClick = { navController.popBackStack() },
                            onDisplayNameChanged = viewModel::updateDisplayName,
                            onAboutChanged = viewModel::updateAbout,
                            onSaveClick = viewModel::save,
                            onDeleteAvatarClick = viewModel::deleteAvatar,
                            onAvatarSelected = viewModel::uploadAvatar
                        )
                    }

                    composable("contacts") {
                        val viewModel: ContactsViewModel = viewModel(
                            factory = viewModelFactory {
                                initializer { ContactsViewModel(application.container) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        LaunchedEffect(state.pendingChatId) {
                            val chatId = state.pendingChatId ?: return@LaunchedEffect
                            viewModel.consumePendingChatNavigation()
                            navController.navigate("chat/$chatId")
                        }
                        ContactsScreen(
                            state = state,
                            items = viewModel.filteredItems(),
                            onQueryChanged = viewModel::updateQuery,
                            onContactClick = viewModel::startDirectChat,
                            onRefresh = viewModel::refresh,
                            onChatsClick = { navigatePrimary("chats") },
                            onContactsClick = { navigatePrimary("contacts") },
                            onSettingsClick = { navigatePrimary("settings") },
                            onProfileClick = { navigatePrimary("profile") },
                            onOpenNewMessageClick = { navController.navigate("discover") }
                        )
                    }

                    composable("discover") {
                        val viewModel: DiscoverViewModel = viewModel(
                            factory = viewModelFactory {
                                initializer { DiscoverViewModel(application.container) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        LaunchedEffect(state.pendingChatId) {
                            val chatId = state.pendingChatId ?: return@LaunchedEffect
                            viewModel.consumePendingChatNavigation()
                            navController.navigate("chat/$chatId")
                        }
                        DiscoverScreen(
                            state = state,
                            onBackClick = { navController.popBackStack() },
                            onQueryChanged = viewModel::updateQuery,
                            onRefreshClick = viewModel::refresh,
                            onUserClick = viewModel::handleUserTap,
                            onBeginGroupSelection = viewModel::beginGroupSelection,
                            onBeginChannelSelection = viewModel::beginChannelSelection,
                            onCancelSelection = viewModel::cancelSelection,
                            onChannelBackClick = viewModel::previousChannelWizardStep,
                            onChannelTitleChanged = viewModel::updateChannelTitle,
                            onChannelDescriptionChanged = viewModel::updateChannelDescription,
                            onChannelVisibilityChanged = viewModel::updateChannelVisibility,
                            onChannelPublicUsernameChanged = viewModel::updateChannelPublicUsername,
                            onChannelSignaturesChanged = viewModel::updateChannelSignaturesEnabled,
                            onContinueChannelWizard = viewModel::continueChannelWizard,
                            onCompleteSelection = viewModel::completeSelection
                        )
                    }

                    composable(
                        route = "forward/{sourceChatId}/{sourceMessageId}",
                        arguments = listOf(
                            navArgument("sourceChatId") { type = NavType.StringType },
                            navArgument("sourceMessageId") { type = NavType.StringType }
                        )
                    ) { backStackEntry ->
                        val sourceChatId = backStackEntry.arguments?.getString("sourceChatId").orEmpty()
                        val sourceMessageId = backStackEntry.arguments?.getString("sourceMessageId").orEmpty()
                        val viewModel: ForwardViewModel = viewModel(
                            key = "forward-$sourceChatId-$sourceMessageId",
                            factory = viewModelFactory {
                                initializer { ForwardViewModel(application.container, sourceChatId, sourceMessageId) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        LaunchedEffect(state.pendingChatId) {
                            val chatId = state.pendingChatId ?: return@LaunchedEffect
                            viewModel.consumePendingChatNavigation()
                            navController.navigate("chat/$chatId") {
                                popUpTo("chats")
                            }
                        }
                        ForwardScreen(
                            state = state,
                            onBackClick = { navController.popBackStack() },
                            onQueryChanged = viewModel::updateQuery,
                            onUserClick = viewModel::forwardToUser
                        )
                    }

                    composable("settings") {
                        val viewModel: SettingsViewModel = viewModel(
                            factory = viewModelFactory {
                                initializer { SettingsViewModel(application.container) }
                            }
                        )
                        SettingsScreen(
                            state = viewModel.uiState,
                            onChatsClick = { navigatePrimary("chats") },
                            onContactsClick = { navigatePrimary("contacts") },
                            onSettingsClick = { navigatePrimary("settings") },
                            onProfileClick = { navigatePrimary("profile") },
                            onAccountClick = { navController.navigate("settings/account") },
                            onChatSettingsClick = { navController.navigate("settings/chats") },
                            onPrivacyClick = { navController.navigate("settings/privacy") },
                            onNotificationsClick = { navController.navigate("settings/notifications") },
                            onBotsClick = { navController.navigate("bots") },
                            onFoldersClick = { navController.navigate("settings/folders") },
                            onDevicesClick = { navController.navigate("settings/devices") },
                            onUpdatesClick = { navController.navigate("settings/update") },
                            onDataStorageClick = { navController.navigate("settings/data-storage") },
                            onThemeClick = { navController.navigate("settings/theme") },
                            onLanguageClick = { navController.navigate("settings/language") },
                            onProxyClick = { navController.navigate("settings/proxy") },
                            onStoriesClick = { navController.navigate("stories") },
                        )
                    }

                    composable("settings/privacy") {
                        val viewModel: PrivacySecurityViewModel = viewModel(
                            factory = viewModelFactory {
                                initializer { PrivacySecurityViewModel(application.container) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        PrivacySecurityScreen(
                            state = state,
                            onBackClick = { navController.popBackStack() },
                            onRefreshClick = viewModel::refresh,
                            onBlockedUsersClick = { navController.navigate("settings/privacy/blocked") },
                            onExceptionsClick = { navController.navigate("settings/privacy/exceptions") },
                            onUpdate = viewModel::update
                        )
                    }

                    composable("settings/privacy/blocked") {
                        BlockedUsersPlaceholderScreen(onBackClick = { navController.popBackStack() })
                    }

                    composable("settings/privacy/exceptions") {
                        PrivacyExceptionsPlaceholderScreen(onBackClick = { navController.popBackStack() })
                    }

                    composable("settings/data-storage") {
                        val viewModel: AppSettingsViewModel = viewModel(
                            factory = viewModelFactory {
                                initializer { AppSettingsViewModel(application.container) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        DataStorageSettingsScreen(
                            state = state,
                            onBackClick = { navController.popBackStack() },
                            onSnapshotChanged = viewModel::updateSnapshot,
                            onProxyClick = { navController.navigate("settings/proxy") },
                            onResetClick = viewModel::reset
                        )
                    }

                    composable("settings/theme") {
                        val viewModel: AppSettingsViewModel = viewModel(
                            factory = viewModelFactory {
                                initializer { AppSettingsViewModel(application.container) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        ThemePlaceholderScreen(
                            state = state,
                            onBackClick = { navController.popBackStack() },
                            onSnapshotChanged = viewModel::updateSnapshot,
                            onResetClick = viewModel::reset
                        )
                    }

                    composable("settings/language") {
                        val viewModel: AppSettingsViewModel = viewModel(
                            factory = viewModelFactory {
                                initializer { AppSettingsViewModel(application.container) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        LanguagePlaceholderScreen(
                            state = state,
                            onBackClick = { navController.popBackStack() },
                            onSnapshotChanged = viewModel::updateSnapshot
                        )
                    }

                    composable("settings/proxy") {
                        val viewModel: AppSettingsViewModel = viewModel(
                            factory = viewModelFactory {
                                initializer { AppSettingsViewModel(application.container) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        ProxyPlaceholderScreen(
                            state = state,
                            onBackClick = { navController.popBackStack() },
                            onSnapshotChanged = viewModel::updateSnapshot
                        )
                    }

                    composable("stories") {
                        val viewModel: StoriesViewModel = viewModel(
                            factory = viewModelFactory {
                                initializer { StoriesViewModel(application.container) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        StoriesScreen(
                            state = state,
                            onBackClick = { navController.popBackStack() },
                            onComposeClick = { navController.navigate("stories/compose") },
                            onRefreshClick = viewModel::refresh,
                            onStoryClick = viewModel::openStory,
                            onDeleteStory = viewModel::deleteStory,
                            onCloseStoryPreview = viewModel::closeStoryPreview,
                            onNextStory = viewModel::openNextStory,
                            onPreviousStory = viewModel::openPreviousStory,
                            onRetryTransfer = viewModel::retryTransfer,
                            onCancelTransfer = viewModel::cancelTransfer
                        )
                    }

                    composable(
                        route = "stories/view/{storyId}",
                        arguments = listOf(navArgument("storyId") { type = NavType.StringType })
                    ) { backStackEntry ->
                        val storyId = backStackEntry.arguments?.getString("storyId").orEmpty()
                        val viewModel: StoriesViewModel = viewModel(
                            key = "story-view-$storyId",
                            factory = viewModelFactory {
                                initializer { StoriesViewModel(application.container) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        LaunchedEffect(storyId) {
                            viewModel.openStoryById(storyId)
                        }
                        StoriesScreen(
                            state = state,
                            onBackClick = { navController.popBackStack() },
                            onComposeClick = { navController.navigate("stories/compose") },
                            onRefreshClick = viewModel::refresh,
                            onStoryClick = viewModel::openStory,
                            onDeleteStory = viewModel::deleteStory,
                            onCloseStoryPreview = {
                                viewModel.closeStoryPreview()
                                navController.popBackStack()
                            },
                            onNextStory = viewModel::openNextStory,
                            onPreviousStory = viewModel::openPreviousStory,
                            onRetryTransfer = viewModel::retryTransfer,
                            onCancelTransfer = viewModel::cancelTransfer
                        )
                    }

                    composable("stories/compose") {
                        val viewModel: StoriesViewModel = viewModel(
                            factory = viewModelFactory {
                                initializer { StoriesViewModel(application.container) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        StoryComposerScreen(
                            state = state,
                            onBackClick = { navController.popBackStack() },
                            onTextChanged = viewModel::updateDraftText,
                            onVisibilityChanged = viewModel::setVisibility,
                            onProtectedChanged = viewModel::setProtectedContent,
                            onTtlChanged = viewModel::setTtlSeconds,
                            onMediaSelected = viewModel::consumeMediaUris,
                            onRemoveMedia = viewModel::removePendingMedia,
                            onClearMedia = viewModel::clearPendingMedia,
                            onCreateClick = { viewModel.createStory { navController.popBackStack() } },
                            onRetryTransfer = viewModel::retryTransfer,
                            onCancelTransfer = viewModel::cancelTransfer
                        )
                    }

                    composable("settings/devices") {
                        val viewModel: DevicesViewModel = viewModel(
                            factory = viewModelFactory {
                                initializer { DevicesViewModel(application.container) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        DevicesScreen(
                            state = state,
                            onBackClick = { navController.popBackStack() },
                            onRefreshClick = viewModel::refresh,
                            onRevokeClick = viewModel::revoke
                        )
                    }

                    composable("settings/folders") {
                        val viewModel: ChatFoldersViewModel = viewModel(
                            factory = viewModelFactory {
                                initializer { ChatFoldersViewModel(application.container) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        ChatFoldersScreen(
                            state = state,
                            onBackClick = { navController.popBackStack() },
                            onRefreshClick = viewModel::refresh,
                            onNewFolderKeyChanged = viewModel::updateNewFolderKey,
                            onFolderSelected = viewModel::selectFolder,
                            onChatToggled = viewModel::toggleChat,
                            onAssignSelected = viewModel::assignSelectedToFolder,
                            onClearSelected = viewModel::clearSelectedFolders
                        )
                    }

                    composable("settings/update") {
                        val viewModel: AppUpdateViewModel = viewModel(
                            factory = viewModelFactory {
                                initializer { AppUpdateViewModel(application.container) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        val lifecycleOwner = LocalLifecycleOwner.current
                        DisposableEffect(lifecycleOwner) {
                            val observer = LifecycleEventObserver { _, event ->
                                if (event == Lifecycle.Event.ON_RESUME) {
                                    viewModel.refreshStatus()
                                }
                            }
                            lifecycleOwner.lifecycle.addObserver(observer)
                            onDispose {
                                lifecycleOwner.lifecycle.removeObserver(observer)
                            }
                        }
                        AppUpdateScreen(
                            state = state,
                            onBackClick = { navController.popBackStack() },
                            onRefreshClick = {
                                if (state.canRequestPackageInstalls) {
                                    viewModel.checkForUpdates()
                                } else {
                                    viewModel.requestUnknownSourcesPermission()
                                    context.startActivity(
                                        application.container.appUpdateManager
                                            .buildUnknownSourcesIntent()
                                            .addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK)
                                    )
                                }
                            },
                            onInstallClick = viewModel::installAvailableUpdate,
                            onGrantPermissionClick = {
                                viewModel.requestUnknownSourcesPermission()
                                context.startActivity(
                                    application.container.appUpdateManager
                                        .buildUnknownSourcesIntent()
                                        .addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK)
                                )
                            }
                        )
                    }

                    composable("archive/open") {
                        val viewModel: ArchiveExtractorViewModel = viewModel(
                            factory = viewModelFactory {
                                initializer { ArchiveExtractorViewModel(application.container) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        ArchiveExtractorScreen(
                            state = state,
                            onBackClick = {
                                viewModel.clearAndClose()
                                navController.popBackStack()
                            },
                            onKeepFoldersChanged = viewModel::setKeepFolders,
                            onOverwriteExistingChanged = viewModel::setOverwriteExisting,
                            onExtractClick = viewModel::extract,
                            onCancelClick = viewModel::cancelExtraction
                        )
                    }

                    composable("settings/chats") {
                        val viewModel: ChatSettingsViewModel = viewModel(
                            factory = viewModelFactory {
                                initializer { ChatSettingsViewModel(application.container) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        ChatSettingsScreen(
                            state = state,
                            onBackClick = { navController.popBackStack() },
                            onSnapshotChanged = { snapshot -> viewModel.updateSnapshot { snapshot } },
                            onWallpaperClick = { navController.navigate("settings/chats/wallpaper") },
                            onResetClick = viewModel::reset
                        )
                    }

                    composable("settings/chats/wallpaper") {
                        val viewModel: ChatSettingsViewModel = viewModel(
                            factory = viewModelFactory {
                                initializer { ChatSettingsViewModel(application.container) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        ChatWallpaperScreen(
                            snapshot = state.snapshot,
                            onBackClick = { navController.popBackStack() },
                            onPresetSelected = { presetId ->
                                viewModel.updateSnapshot {
                                    it.copy(
                                        selectedWallpaperPresetId = presetId,
                                        useCustomWallpaper = false
                                    )
                                }
                            },
                            onCustomWallpaperSelected = { uri ->
                                viewModel.updateSnapshot {
                                    it.copy(
                                        customWallpaperUri = uri.toString(),
                                        useCustomWallpaper = true
                                    )
                                }
                            },
                            onUseCustomWallpaper = {
                                viewModel.updateSnapshot { snapshot ->
                                    if (snapshot.customWallpaperUri.isNullOrBlank()) {
                                        snapshot
                                    } else {
                                        snapshot.copy(useCustomWallpaper = true)
                                    }
                                }
                            }
                        )
                    }

                    composable("settings/notifications") {
                        val viewModel: NotificationSettingsViewModel = viewModel(
                            factory = viewModelFactory {
                                initializer { NotificationSettingsViewModel(application.container) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        NotificationSettingsScreen(
                            state = state,
                            messageSoundOptions = viewModel.messageSoundOptions,
                            callRingtoneOptions = viewModel.callRingtoneOptions,
                            repeatIntervalOptions = viewModel.repeatIntervalOptions,
                            onBackClick = { navController.popBackStack() },
                            onSnapshotChanged = { snapshot -> viewModel.updateSnapshot { snapshot } },
                            onMessageSoundChanged = viewModel::setMessageSound,
                            onCallRingtoneChanged = viewModel::setCallRingtone,
                            onRepeatIntervalChanged = viewModel::setRepeatInterval,
                            onSaveClick = viewModel::save,
                            onResetClick = viewModel::reset
                        )
                    }

                    composable("bots") {
                        val viewModel: BotsViewModel = viewModel(
                            factory = viewModelFactory {
                                initializer { BotsViewModel(application.container) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        BotsScreen(
                            state = state,
                            onBackClick = { navController.popBackStack() },
                            onCreateBotClick = { navController.navigate("bots/editor") },
                            onBotClick = { bot -> navController.navigate("bots/editor?botId=${bot.id}") }
                        )
                    }

                    composable(
                        route = "bots/editor?botId={botId}",
                        arguments = listOf(
                            navArgument("botId") {
                                type = NavType.StringType
                                nullable = true
                                defaultValue = null
                            }
                        )
                    ) { backStackEntry ->
                        val botId = backStackEntry.arguments?.getString("botId")
                        val viewModel: BotEditorViewModel = viewModel(
                            key = "bot-editor-${botId ?: "new"}",
                            factory = viewModelFactory {
                                initializer { BotEditorViewModel(application.container, botId) }
                            }
                        )
                        val state by viewModel.uiState.collectAsStateWithLifecycle()
                        LaunchedEffect(state.pendingChatId) {
                            val chatId = state.pendingChatId ?: return@LaunchedEffect
                            viewModel.consumePendingChatNavigation()
                            navController.navigate("chat/$chatId")
                        }
                        LaunchedEffect(state.deleteCompleted) {
                            if (!state.deleteCompleted) {
                                return@LaunchedEffect
                            }

                            viewModel.consumeDeleteCompleted()
                            navController.navigate("bots") {
                                popUpTo("bots") {
                                    inclusive = true
                                }
                            }
                        }
                        BotEditorScreen(
                            state = state,
                            onBackClick = { navController.popBackStack() },
                            onDisplayNameChanged = viewModel::updateDisplayName,
                            onUsernameChanged = viewModel::updateUsername,
                            onAboutChanged = viewModel::updateAbout,
                            onCommandsChanged = viewModel::updateCommandsText,
                            onEnabledChanged = viewModel::updateEnabled,
                            onSaveClick = viewModel::save,
                            onRegenerateTokenClick = viewModel::regenerateToken,
                            onDeleteBotClick = viewModel::deleteBot,
                            onOpenChatClick = viewModel::openChat
                        )
                    }
                }

                LaunchedEffect(pendingShare?.id, currentBackStackEntry?.destination?.route) {
                    if (pendingShare == null) {
                        return@LaunchedEffect
                    }
                    if (application.container.sessionStore.read() == null) {
                        return@LaunchedEffect
                    }
                    if (currentBackStackEntry?.destination?.route == "chats") {
                        return@LaunchedEffect
                    }

                    navigatePrimary("chats")
                }

                LaunchedEffect(pendingArchive?.id, currentBackStackEntry?.destination?.route) {
                    if (pendingArchive == null) {
                        return@LaunchedEffect
                    }
                    if (currentBackStackEntry?.destination?.route == "archive/open") {
                        return@LaunchedEffect
                    }

                    navController.navigate("archive/open") {
                        launchSingleTop = true
                    }
                }

                LaunchedEffect(pendingCallInvite?.requestId) {
                    val invite = pendingCallInvite ?: return@LaunchedEffect
                    if (application.container.sessionStore.read() == null) {
                        application.container.incomingCallInviteStore.clear(invite.requestId)
                        return@LaunchedEffect
                    }

                    application.container.callManager.presentIncomingCallInvite(
                        callId = invite.callId,
                        chatId = invite.chatId,
                        callerId = invite.callerId,
                        callerDisplayName = invite.callerDisplayName,
                        callerPhoneNumber = invite.callerPhoneNumber,
                        mediaType = invite.mediaType
                    )
                    application.container.incomingCallInviteStore.clear(invite.requestId)
                }

                LaunchedEffect(
                    pendingPushNavigation?.requestId,
                    currentBackStackEntry?.destination?.route,
                    currentBackStackEntry?.arguments?.getString("chatId")
                ) {
                    val pendingPush = pendingPushNavigation ?: return@LaunchedEffect
                    if (application.container.sessionStore.read() == null) {
                        return@LaunchedEffect
                    }

                    val currentRoute = currentBackStackEntry?.destination?.route
                    val currentChatId = currentBackStackEntry?.arguments?.getString("chatId")
                    val route = chatRoute(
                        chatId = pendingPush.chatId,
                        messageId = pendingPush.messageId,
                        scrollRequestId = pendingPush.requestId
                    )
                    if (currentRoute == ChatRoutePattern && currentChatId == pendingPush.chatId) {
                        if (!pendingPush.messageId.isNullOrBlank()) {
                            navController.navigate(route) {
                                launchSingleTop = true
                            }
                        }
                        application.container.incomingPushNavigationStore.clear(pendingPush.requestId)
                        return@LaunchedEffect
                    }

                    navController.navigate(route) {
                        launchSingleTop = true
                    }
                    application.container.incomingPushNavigationStore.clear(pendingPush.requestId)
                }

                LaunchedEffect(
                    currentBackStackEntry?.destination?.route,
                    currentBackStackEntry?.arguments?.getString("chatId")
                ) {
                    val activeChatId = if (currentBackStackEntry?.destination?.route == ChatRoutePattern) {
                        currentBackStackEntry?.arguments?.getString("chatId")
                    } else {
                        null
                    }
                    AndroidActiveChatState.setActiveChatId(activeChatId)
                }

                activeCall?.let { call ->
                    CallScreen(
                        state = call,
                        onAccept = application.container.callManager::acceptCurrentCall,
                        onDecline = application.container.callManager::declineCurrentCall,
                        onEnd = application.container.callManager::endCurrentCall
                    )
                }

                if (isAppLocked) {
                    AppLockedOverlay()
                }
            }
        }
    }
}
}

@Composable
private fun AppLockedOverlay() {
    Box(
        modifier = Modifier
            .fillMaxSize()
            .background(Color(0xFF101820)),
        contentAlignment = Alignment.Center
    ) {
        Text(
            text = "Икар заблокирован",
            style = MaterialTheme.typography.headlineLarge,
            color = Color.White
        )
    }
}
