package ru.forbion.f7cloud.feature.files

import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items as gridItems
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import ru.forbion.f7cloud.core.auth.AuthSession
import ru.forbion.f7cloud.core.designsystem.F7AlertDialog
import ru.forbion.f7cloud.core.designsystem.F7Colors
import ru.forbion.f7cloud.core.designsystem.F7CreateButton
import ru.forbion.f7cloud.core.designsystem.F7ModuleScreen
import ru.forbion.f7cloud.core.designsystem.F7OverlayDismissHandler
import ru.forbion.f7cloud.core.designsystem.F7OutlinedField
import ru.forbion.f7cloud.core.designsystem.F7SecondaryButton
import java.io.File

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun FilesScreen(
    session: AuthSession,
    modifier: Modifier = Modifier,
    uploadRequest: Int = 0,
    pushRefreshRequest: Int = 0,
    openFileId: Long? = null,
    sidebarOpen: Boolean = false,
    onSidebarOpenChange: (Boolean) -> Unit = {},
    settingsOpen: Boolean = false,
    onSettingsOpenChange: (Boolean) -> Unit = {},
    onOpenFileConsumed: () -> Unit = {},
    onUnauthorized: () -> Unit = {},
    onOpenOfficeEditor: (OfficeEditorLaunch) -> Unit = {},
) {
    val context = LocalContext.current
    val vm: FilesViewModel = viewModel(factory = FilesViewModel.Factory(context))
    val state by vm.state.collectAsState()
    val snackbarHostState = remember { SnackbarHostState() }
    var viewMode by remember { mutableStateOf(FilesViewMode.List) }
    var showCreateMenu by remember { mutableStateOf(false) }
    var showNewFolderDialog by remember { mutableStateOf(false) }
    var newFolderName by remember { mutableStateOf("") }
    var contextMenuItem by remember { mutableStateOf<FileItem?>(null) }
    var contextMenuAnchor by remember { mutableStateOf<Rect?>(null) }
    var bulkMenuAnchor by remember { mutableStateOf<Rect?>(null) }
    var bulkMenuOpen by remember { mutableStateOf(false) }
    var deleteConfirmItem by remember { mutableStateOf<FileItem?>(null) }
    var deleteConfirmBulk by remember { mutableStateOf(false) }

    F7OverlayDismissHandler(
        enabled = state.detailsItem != null,
        onDismiss = vm::hideDetails,
    )
    F7OverlayDismissHandler(
        enabled = showCreateMenu,
        onDismiss = { showCreateMenu = false },
    )
    F7OverlayDismissHandler(
        enabled = contextMenuItem != null,
        onDismiss = { contextMenuItem = null },
    )

    val uploadFilesLauncher = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.OpenMultipleDocuments(),
    ) { uris ->
        if (uris.isNotEmpty()) {
            vm.uploadFromUris(context, session, uris)
        }
    }
    val uploadFolderLauncher = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.OpenDocumentTree(),
    ) { uri ->
        if (uri != null) {
            context.contentResolver.takePersistableUriPermission(
                uri,
                android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION,
            )
            vm.uploadFolderTree(context, session, uri)
        }
    }

    LaunchedEffect(session.serverUrl, session.username, session.davUserId) {
        OfficeWarmup.warm(session)
        vm.load(session)
        vm.loadSidebarData(session)
    }
    LaunchedEffect(uploadRequest) {
        if (uploadRequest > 0) showCreateMenu = true
    }
    LaunchedEffect(pushRefreshRequest) {
        if (pushRefreshRequest > 0) vm.load(session)
    }
    LaunchedEffect(openFileId) {
        val fileId = openFileId ?: return@LaunchedEffect
        vm.openFileById(session, fileId)
        onOpenFileConsumed()
    }
    LaunchedEffect(state.unauthorized) {
        if (state.unauthorized) onUnauthorized()
    }
    LaunchedEffect(state.editorLaunch) {
        val launch = state.editorLaunch ?: return@LaunchedEffect
        onOpenOfficeEditor(launch)
        vm.clearEditorLaunch()
    }
    LaunchedEffect(state.openAction) {
        when (val action = state.openAction) {
            null -> Unit
            is FileOpenAction.Image -> {
                context.startActivity(ImageViewerActivity.intent(context, action.path, action.title))
                vm.clearOpenAction()
            }
            is FileOpenAction.External -> {
                LocalFileOpener.openExternal(context, File(action.path), action.mimeType)
                vm.clearOpenAction()
            }
        }
    }
    LaunchedEffect(state.snackbar) {
        val msg = state.snackbar ?: return@LaunchedEffect
        snackbarHostState.showSnackbar(msg)
        vm.clearSnackbar()
    }

    val displayItems = vm.displayItems(state)
    val pathLabel = when (state.browseMode) {
        FilesBrowseMode.AllFiles -> if (state.currentPath.isBlank()) "Все файлы" else state.currentPath.replace("/", " › ")
        FilesBrowseMode.Personal -> "Личные файлы"
        FilesBrowseMode.Recent -> "Недавно изменённые"
        FilesBrowseMode.Favorites -> "Избранные"
    }
    val allSelected = displayItems.isNotEmpty() && displayItems.all { it.relativePath in state.selectedPaths }
    val selectionMode = state.selectedPaths.isNotEmpty()

    val isRefreshing = state.loading && displayItems.isNotEmpty()
    val listState = rememberLazyListState()

    Box(modifier = modifier.fillMaxSize()) {
        F7ModuleScreen(
            modifier = Modifier.fillMaxSize(),
            loading = state.loading && displayItems.isEmpty(),
            error = state.error,
            onErrorRetry = { vm.refreshCurrent(session) },
            headerActions = {},
        ) {
            Column(modifier = Modifier.fillMaxSize()) {
                // Поиск + переключатель вид список⇄сетка (макет F-17/F-22)
                Row(
                    modifier = Modifier.fillMaxWidth(),
                    horizontalArrangement = Arrangement.spacedBy(8.dp),
                    verticalAlignment = Alignment.CenterVertically,
                ) {
                    FilesSearchBar(
                        serverUrl = session.serverUrl,
                        query = state.searchQuery,
                        onQueryChange = { vm.setSearchQuery(session, it) },
                        modifier = Modifier.weight(1f),
                    )
                    FilesViewToggleButton(viewMode) {
                        viewMode = if (viewMode == FilesViewMode.List) FilesViewMode.Grid else FilesViewMode.List
                    }
                    // Кнопки создания в шапке нет (живая тема): «Создать или загрузить» —
                    // градиентная кнопка сверху панели навигации.
                }
                // Хлебные крошки
                val crumbSegments = state.currentPath.split("/").filter { it.isNotBlank() }
                FilesBreadcrumb(
                    segments = crumbSegments,
                    onHomeClick = { vm.navigateToPath(session, "") },
                    onSegmentClick = { i -> vm.navigateToPath(session, crumbSegments.take(i + 1).joinToString("/")) },
                )
                if (selectionMode) {
                    val allSelected = displayItems.isNotEmpty() &&
                        state.selectedPaths.size >= displayItems.size
                    FilesBulkActionsBar(
                        serverUrl = session.serverUrl,
                        selectedCount = state.selectedPaths.size,
                        allSelected = allSelected,
                        onToggleSelectAll = {
                            if (allSelected) vm.clearSelection() else vm.selectAllVisible()
                        },
                        onActionsClick = { rect ->
                            bulkMenuAnchor = rect
                            bulkMenuOpen = true
                        },
                    )
                } else {
                    // Фильтр-чипы вместо десктопной колоночной шапки (макет F-18/F-22)
                    FilesFilterChips(
                        onTypeClick = { vm.setSortColumn(FilesSortColumn.Type) },
                        onParticipantsClick = {},
                        onModifiedClick = { vm.setSortColumn(FilesSortColumn.Modified) },
                    )
                }
                if (state.openingFile != null) {
                    CircularProgressIndicator(color = F7Colors.Primary)
                    Text(
                        text = "Открываем «${state.openingFile}»…",
                        style = MaterialTheme.typography.bodySmall,
                        color = F7Colors.TextSecondary,
                    )
                }
                PullToRefreshBox(
                    isRefreshing = isRefreshing,
                    onRefresh = { vm.refreshCurrent(session) },
                    modifier = Modifier
                        .fillMaxWidth()
                        .weight(1f),
                ) {
                    val openItem: (FileItem) -> Unit = { item ->
                        val openable = !item.isDirectory &&
                            (OfficeFiles.isOfficeFile(item.name) || OpenableFiles.isOpenable(item.name))
                        when {
                            item.isDirectory -> vm.openFolder(session, item)
                            openable -> vm.openItem(session, item)
                        }
                    }
                    if (displayItems.isEmpty() && !state.loading && state.error.isNullOrBlank()) {
                        val searching = state.searchQuery.isNotBlank()
                        FilesEmptyState(
                            iconUrl = "file:///android_asset/filetypes/file.svg",
                            title = if (searching) "Нет результатов поиска" else "Папка пуста",
                            subtitle = if (searching) {
                                "По запросу «${state.searchQuery}» ничего не найдено"
                            } else {
                                "Загрузите контент или синхронизируйте его своими устройствами"
                            },
                        )
                    } else if (viewMode == FilesViewMode.Grid) {
                        LazyVerticalGrid(
                            columns = GridCells.Fixed(2),
                            modifier = Modifier.fillMaxSize(),
                            horizontalArrangement = Arrangement.spacedBy(12.dp),
                            verticalArrangement = Arrangement.spacedBy(12.dp),
                            contentPadding = PaddingValues(vertical = 8.dp),
                        ) {
                            gridItems(displayItems, key = { it.relativePath }) { item ->
                                FilesGridCard(
                                    serverUrl = session.serverUrl,
                                    item = item,
                                    selected = item.relativePath in state.selectedPaths,
                                    favorite = item.favorite,
                                    onSelectedChange = { vm.toggleSelection(item.relativePath) },
                                    onOpenClick = { openItem(item) },
                                    onMenuClick = {
                                        contextMenuItem = item
                                    },
                                )
                            }
                        }
                    } else {
                        LazyColumn(
                            state = listState,
                            modifier = Modifier.fillMaxSize(),
                        ) {
                            items(displayItems, key = { it.relativePath }) { item ->
                                FilesListRow(
                                    serverUrl = session.serverUrl,
                                    item = item,
                                    selected = item.relativePath in state.selectedPaths,
                                    showExtensions = state.userConfig.showExtensions,
                                    onSelectedChange = { vm.toggleSelection(item.relativePath) },
                                    onOpenClick = { openItem(item) },
                                    onMenuClick = { rect ->
                                        contextMenuItem = item
                                        contextMenuAnchor = rect
                                    },
                                )
                            }
                        }
                    }
                }
            }
        }

        FilesNavigationSidebar(
            serverUrl = session.serverUrl,
            visible = sidebarOpen,
            browseMode = state.browseMode,
            storageStats = state.storageStats,
            folderTree = state.folderTree,
            expandedTreePaths = state.expandedTreePaths,
            expandedSections = state.expandedSidebarSections,
            onDismiss = { onSidebarOpenChange(false) },
            onBrowseModeClick = { mode ->
                vm.navigateBrowseMode(session, mode)
                onSidebarOpenChange(false)
            },
            onFolderPathClick = { path ->
                vm.navigateToPath(session, path)
                onSidebarOpenChange(false)
            },
            onToggleTreePath = vm::toggleTreePath,
            onToggleSection = vm::toggleSidebarSection,
            onWebOnlyClick = { title ->
                vm.showWebOnlyMessage(title)
                onSidebarOpenChange(false)
            },
            onCreateClick = {
                onSidebarOpenChange(false)
                showCreateMenu = true
            },
        )

        FilesCreateMenu(
            serverUrl = session.serverUrl,
            visible = showCreateMenu,
            onDismiss = { showCreateMenu = false },
            onAction = { action ->
                when (action) {
                    FilesCreateAction.UploadFiles -> uploadFilesLauncher.launch(arrayOf("*/*"))
                    FilesCreateAction.UploadFolders -> uploadFolderLauncher.launch(null)
                    FilesCreateAction.NewFolder -> {
                        newFolderName = ""
                        showNewFolderDialog = true
                    }
                    else -> vm.handleCreateAction(session, action)
                }
            },
        )

        SnackbarHost(
            hostState = snackbarHostState,
            modifier = Modifier.align(Alignment.BottomCenter),
        )
    }

    FilesSettingsSheet(
        visible = settingsOpen,
        config = state.userConfig,
        onDismiss = { onSettingsOpenChange(false) },
        onToggle = { key, value -> vm.updateUserConfig(session, key, value) },
        onDefaultViewChange = { vm.updateUserConfig(session, "default_view", it) },
    )

    FilesDetailsSheet(
        serverUrl = session.serverUrl,
        ownerLabel = session.username,
        item = state.detailsItem,
        tab = state.detailsTab,
        details = state.fileDetails,
        loading = state.detailsLoading,
        onDismiss = vm::hideDetails,
        onTabChange = vm::setDetailsTab,
        onToggleFavorite = { state.detailsItem?.let { vm.toggleFavorite(session, it) } },
        onWebOnlyAction = vm::showWebOnlyMessage,
    )

    FilesRenameDialog(
        item = state.renameItem,
        onDismiss = vm::hideRename,
        onConfirm = { newName ->
            state.renameItem?.let { vm.renameItem(session, it, newName) }
        },
    )

    val contextItem = contextMenuItem
    if (contextItem != null) {
        FileActionMenuPopup(
            expanded = true,
            serverUrl = session.serverUrl,
            anchorBounds = contextMenuAnchor,
            entries = buildFileContextMenu(contextItem),
            onDismiss = { contextMenuItem = null },
            onAction = { action ->
                when (action) {
                    FileContextAction.Favorite -> vm.toggleFavorite(session, contextItem)
                    FileContextAction.Details -> vm.showDetails(session, contextItem)
                    FileContextAction.Sharing -> vm.showDetails(session, contextItem, FileDetailsTab.Sharing)
                    FileContextAction.Tags -> vm.showWebOnlyMessage("Управление метками")
                    FileContextAction.Rename -> vm.showRename(contextItem)
                    FileContextAction.MoveCopy -> vm.showWebOnlyMessage("Перемещение и копирование")
                    FileContextAction.Reminder -> vm.showWebOnlyMessage("Напоминания")
                    FileContextAction.OpenLocally -> vm.showWebOnlyMessage("Открытие локально")
                    FileContextAction.Download -> vm.downloadItem(session, contextItem, context)
                    FileContextAction.Archive -> vm.showWebOnlyMessage("Архивирование")
                    FileContextAction.Delete -> deleteConfirmItem = contextItem
                }
            },
        )
    }

    FilesBulkActionMenuPopup(
        expanded = bulkMenuOpen,
        serverUrl = session.serverUrl,
        anchorBounds = bulkMenuAnchor,
        onDismiss = { bulkMenuOpen = false },
        onAction = { action ->
            when (action) {
                FilesBulkAction.Favorite -> vm.favoriteSelected(session)
                FilesBulkAction.Download -> vm.showWebOnlyMessage("Массовое скачивание")
                FilesBulkAction.Delete -> deleteConfirmBulk = true
            }
        },
    )

    deleteConfirmItem?.let { item ->
        F7AlertDialog(
            title = if (item.isDirectory) "Удалить папку?" else "Удалить файл?",
            onDismiss = { deleteConfirmItem = null },
            confirmText = "Удалить",
            onConfirm = {
                deleteConfirmItem = null
                vm.deleteItem(session, item)
            },
        ) {
            Text("«${item.name}» будет удалён.")
        }
    }

    if (deleteConfirmBulk) {
        F7AlertDialog(
            title = "Удалить выбранные элементы?",
            onDismiss = { deleteConfirmBulk = false },
            confirmText = "Удалить",
            onConfirm = {
                deleteConfirmBulk = false
                vm.deleteSelected(session)
            },
        ) {
            Text("Будет удалено элементов: ${state.selectedPaths.size}")
        }
    }

    if (showNewFolderDialog) {
        F7AlertDialog(
            title = "Новая папка",
            onDismiss = { showNewFolderDialog = false },
            confirmText = "Создать",
            onConfirm = {
                showNewFolderDialog = false
                vm.createFolder(session, newFolderName)
            },
            confirmEnabled = newFolderName.trim().isNotBlank(),
        ) {
            F7OutlinedField(
                value = newFolderName,
                onValueChange = { newFolderName = it },
                label = "Имя папки",
            )
        }
    }
}
