package com.syncflow.ui.files

import android.content.ClipData
import android.content.Intent
import android.webkit.MimeTypeMap
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.core.content.FileProvider
import androidx.hilt.navigation.compose.hiltViewModel
import com.syncflow.ui.browser.RemoteBrowserViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File

private val STORAGE_ROOT = File("/storage/emulated/0")

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun FilesScreen(
    modifier: Modifier = Modifier,
    vm: FilesViewModel = hiltViewModel(),
) {
    var activeTab by remember { mutableStateOf(0) }
    val context = LocalContext.current
    val snackbarHostState = remember { SnackbarHostState() }
    val scope = rememberCoroutineScope()
    val accounts by vm.accounts.collectAsState()
    var selectedAccountId by remember { mutableStateOf(-1L) }

    LaunchedEffect(accounts) {
        if (selectedAccountId == -1L && accounts.isNotEmpty()) selectedAccountId = accounts.first().id
    }

    val cloudLabel = accounts.find { it.id == selectedAccountId }?.displayName
        ?: accounts.firstOrNull()?.displayName
        ?: "Cloud"

    LaunchedEffect(Unit) {
        vm.fileAction.collect { action ->
            when (action) {
                is FileAction.Open -> try {
                    val uri = FileProvider.getUriForFile(context, "${context.packageName}.fileprovider", action.file)
                    context.startActivity(Intent(Intent.ACTION_VIEW).apply {
                        setDataAndType(uri, action.file.name.mimeType())
                        clipData = ClipData.newRawUri("", uri)
                        addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK)
                    })
                } catch (e: Exception) {
                    scope.launch { snackbarHostState.showSnackbar("Cannot open: ${e.message}") }
                }
                is FileAction.Share -> try {
                    val uri = FileProvider.getUriForFile(context, "${context.packageName}.fileprovider", action.file)
                    context.startActivity(
                        Intent.createChooser(Intent(Intent.ACTION_SEND).apply {
                            type = action.file.name.mimeType()
                            putExtra(Intent.EXTRA_STREAM, uri)
                            clipData = ClipData.newRawUri("", uri)
                            addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK)
                        }, "Share").apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) }
                    )
                } catch (e: Exception) {
                    scope.launch { snackbarHostState.showSnackbar("Cannot share: ${e.message}") }
                }
                is FileAction.ShareMultiple -> try {
                    val uris = action.files.map { FileProvider.getUriForFile(context, "${context.packageName}.fileprovider", it) }
                    context.startActivity(
                        Intent.createChooser(Intent(Intent.ACTION_SEND_MULTIPLE).apply {
                            type = "*/*"
                            putParcelableArrayListExtra(Intent.EXTRA_STREAM, ArrayList(uris))
                            addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK)
                        }, "Share files").apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) }
                    )
                } catch (e: Exception) {
                    scope.launch { snackbarHostState.showSnackbar("Cannot share: ${e.message}") }
                }
                is FileAction.Error -> scope.launch { snackbarHostState.showSnackbar(action.message) }
            }
        }
    }

    Box(modifier = modifier.fillMaxSize()) {
        Column(modifier = Modifier.fillMaxSize()) {

            // ── Phone / Cloud toggle ──────────────────────────────────────────
            SingleChoiceSegmentedButtonRow(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(horizontal = 16.dp, vertical = 8.dp),
            ) {
                SegmentedButton(
                    selected = activeTab == 0,
                    onClick = { activeTab = 0 },
                    shape = SegmentedButtonDefaults.itemShape(0, 2),
                    icon = { SegmentedButtonDefaults.Icon(active = activeTab == 0, activeContent = { Icon(Icons.Default.PhoneAndroid, null, Modifier.size(16.dp)) }) },
                ) {
                    Text("Phone")
                }
                SegmentedButton(
                    selected = activeTab == 1,
                    onClick = { activeTab = 1 },
                    shape = SegmentedButtonDefaults.itemShape(1, 2),
                    icon = { SegmentedButtonDefaults.Icon(active = activeTab == 1, activeContent = { Icon(Icons.Default.Cloud, null, Modifier.size(16.dp)) }) },
                ) {
                    Text(cloudLabel, maxLines = 1, overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis)
                }
            }
            HorizontalDivider()

            when (activeTab) {
                0 -> LocalExplorer(modifier = Modifier.weight(1f))
                1 -> CloudExplorer(
                    vm = vm,
                    selectedAccountId = selectedAccountId,
                    onAccountSelect = { selectedAccountId = it },
                    modifier = Modifier.weight(1f),
                )
            }
        }

        val isDownloading by vm.isDownloading.collectAsState()
        if (isDownloading) {
            Surface(
                color = MaterialTheme.colorScheme.surfaceVariant,
                tonalElevation = 4.dp,
                modifier = Modifier.fillMaxWidth().align(Alignment.BottomCenter),
            ) {
                Row(
                    modifier = Modifier.padding(horizontal = 16.dp, vertical = 10.dp),
                    verticalAlignment = Alignment.CenterVertically,
                    horizontalArrangement = Arrangement.spacedBy(12.dp),
                ) {
                    CircularProgressIndicator(modifier = Modifier.size(18.dp), strokeWidth = 2.dp)
                    Text("Opening file…", style = MaterialTheme.typography.bodySmall)
                }
            }
        }

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

// ── Local file explorer ───────────────────────────────────────────────────────

private data class LocalEntry(val file: File, val isDir: Boolean, val childCount: Int = 0, val sizeBytes: Long = 0L)

@Composable
private fun LocalExplorer(modifier: Modifier = Modifier) {
    val context = LocalContext.current
    val scope = rememberCoroutineScope()

    var currentPath by remember { mutableStateOf(STORAGE_ROOT) }
    var pathStack by remember { mutableStateOf(listOf(STORAGE_ROOT)) }
    var entries by remember { mutableStateOf<List<LocalEntry>>(emptyList()) }
    var isLoading by remember { mutableStateOf(true) }
    var searchQuery by remember { mutableStateOf("") }
    var searchActive by remember { mutableStateOf(false) }
    val breadcrumbState = rememberLazyListState()
    val snackbarHostState = remember { SnackbarHostState() }

    fun loadDir(dir: File) {
        isLoading = true
        entries = emptyList()
        scope.launch {
            val result = withContext(Dispatchers.IO) {
                (dir.listFiles() ?: emptyArray())
                    .filter { !it.name.startsWith(".") }
                    .sortedWith(compareBy({ !it.isDirectory }, { it.name.lowercase() }))
                    .map { f ->
                        if (f.isDirectory) LocalEntry(f, true, f.listFiles()?.size ?: 0)
                        else LocalEntry(f, false, sizeBytes = f.length())
                    }
            }
            entries = result
            isLoading = false
        }
    }

    fun navigate(dir: File) {
        currentPath = dir; pathStack = pathStack + dir
        searchQuery = ""; searchActive = false; loadDir(dir)
    }

    fun navigateUp(): Boolean {
        if (pathStack.size <= 1) return false
        val newStack = pathStack.dropLast(1)
        pathStack = newStack; currentPath = newStack.last()
        searchQuery = ""; searchActive = false; loadDir(currentPath)
        return true
    }

    LaunchedEffect(Unit) { loadDir(currentPath) }
    BackHandler(enabled = pathStack.size > 1) { navigateUp() }

    val relParts = currentPath.absolutePath
        .removePrefix(STORAGE_ROOT.absolutePath).trimStart('/').split('/').filter { it.isNotEmpty() }
    LaunchedEffect(currentPath) {
        scope.launch { breadcrumbState.animateScrollToItem(maxOf(0, relParts.size)) }
        searchQuery = ""; searchActive = false
    }

    val filtered = if (searchQuery.isBlank()) entries
    else entries.filter { it.file.name.contains(searchQuery, ignoreCase = true) }

    Box(modifier = modifier) {
        Column(modifier = Modifier.fillMaxSize()) {

            // ── Breadcrumbs / search bar ──────────────────────────────────────
            Surface(tonalElevation = 1.dp) {
                if (searchActive) {
                    val focusRequester = remember { FocusRequester() }
                    LaunchedEffect(Unit) { focusRequester.requestFocus() }
                    Row(
                        modifier = Modifier.fillMaxWidth().padding(horizontal = 8.dp, vertical = 4.dp),
                        verticalAlignment = Alignment.CenterVertically,
                    ) {
                        OutlinedTextField(
                            value = searchQuery, onValueChange = { searchQuery = it },
                            modifier = Modifier.weight(1f).focusRequester(focusRequester),
                            placeholder = { Text("Search in folder…") },
                            singleLine = true,
                            keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search),
                            keyboardActions = KeyboardActions(onSearch = {}),
                            colors = OutlinedTextFieldDefaults.colors(
                                focusedBorderColor = Color.Transparent, unfocusedBorderColor = Color.Transparent,
                            ),
                        )
                        IconButton(onClick = { searchActive = false; searchQuery = "" }) {
                            Icon(Icons.Default.Close, null)
                        }
                    }
                } else {
                    LazyRow(
                        state = breadcrumbState,
                        modifier = Modifier.fillMaxWidth().padding(horizontal = 8.dp, vertical = 6.dp),
                        verticalAlignment = Alignment.CenterVertically,
                        horizontalArrangement = Arrangement.spacedBy(2.dp),
                    ) {
                        item {
                            BreadcrumbChip("📱 Storage", relParts.isEmpty()) {
                                pathStack = listOf(STORAGE_ROOT); currentPath = STORAGE_ROOT; loadDir(STORAGE_ROOT)
                            }
                        }
                        itemsIndexed(relParts) { idx, part ->
                            Icon(Icons.Default.ChevronRight, null, Modifier.size(14.dp), tint = MaterialTheme.colorScheme.onSurfaceVariant)
                            val partFile = File(STORAGE_ROOT, relParts.take(idx + 1).joinToString("/"))
                            BreadcrumbChip(part, idx == relParts.lastIndex) {
                                val i = pathStack.indexOfLast { it.absolutePath == partFile.absolutePath }
                                pathStack = if (i >= 0) pathStack.take(i + 1) else listOf(partFile)
                                currentPath = partFile; loadDir(partFile)
                            }
                        }
                        item {
                            Spacer(Modifier.width(4.dp))
                            IconButton(onClick = { searchActive = true }, modifier = Modifier.size(28.dp)) {
                                Icon(Icons.Default.Search, null, Modifier.size(18.dp), tint = MaterialTheme.colorScheme.onSurfaceVariant)
                            }
                        }
                    }
                }
            }
            HorizontalDivider()

            // ── Content ───────────────────────────────────────────────────────
            when {
                isLoading -> Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
                    CircularProgressIndicator()
                }
                filtered.isEmpty() -> Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
                    Column(horizontalAlignment = Alignment.CenterHorizontally) {
                        Icon(Icons.Default.FolderOpen, null, Modifier.size(56.dp),
                            tint = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.4f))
                        Spacer(Modifier.height(12.dp))
                        Text(
                            if (searchQuery.isBlank()) "Empty folder" else "No results for \"$searchQuery\"",
                            style = MaterialTheme.typography.bodyLarge,
                            color = MaterialTheme.colorScheme.onSurfaceVariant,
                        )
                    }
                }
                else -> LazyColumn(modifier = Modifier.fillMaxSize()) {
                    if (currentPath.absolutePath == STORAGE_ROOT.absolutePath && searchQuery.isBlank()) {
                        item {
                            Text("Quick access", style = MaterialTheme.typography.labelSmall,
                                color = MaterialTheme.colorScheme.onSurfaceVariant,
                                modifier = Modifier.padding(start = 20.dp, top = 14.dp, bottom = 6.dp))
                            LazyRow(contentPadding = PaddingValues(horizontal = 16.dp),
                                horizontalArrangement = Arrangement.spacedBy(10.dp),
                                modifier = Modifier.padding(bottom = 8.dp)) {
                                val shortcuts = listOf(
                                    Triple("Camera",    Icons.Default.PhotoCamera,  "/storage/emulated/0/DCIM/Camera"),
                                    Triple("Downloads", Icons.Default.Download,     "/storage/emulated/0/Download"),
                                    Triple("Documents", Icons.Default.Description,  "/storage/emulated/0/Documents"),
                                    Triple("Pictures",  Icons.Default.Image,        "/storage/emulated/0/Pictures"),
                                    Triple("Music",     Icons.Default.MusicNote,    "/storage/emulated/0/Music"),
                                    Triple("Videos",    Icons.Default.Videocam,     "/storage/emulated/0/Movies"),
                                )
                                items(shortcuts.filter { File(it.third).isDirectory }) { (label, icon, path) ->
                                    Surface(onClick = { navigate(File(path)) }, shape = RoundedCornerShape(14.dp),
                                        color = MaterialTheme.colorScheme.secondaryContainer,
                                        modifier = Modifier.height(72.dp).width(80.dp)) {
                                        Column(modifier = Modifier.fillMaxSize().padding(8.dp),
                                            horizontalAlignment = Alignment.CenterHorizontally,
                                            verticalArrangement = Arrangement.Center) {
                                            Icon(icon, null, Modifier.size(24.dp), tint = MaterialTheme.colorScheme.onSecondaryContainer)
                                            Spacer(Modifier.height(4.dp))
                                            Text(label, style = MaterialTheme.typography.labelSmall,
                                                color = MaterialTheme.colorScheme.onSecondaryContainer, maxLines = 1)
                                        }
                                    }
                                }
                            }
                            HorizontalDivider(modifier = Modifier.padding(vertical = 4.dp))
                            Text("All files", style = MaterialTheme.typography.labelSmall,
                                color = MaterialTheme.colorScheme.onSurfaceVariant,
                                modifier = Modifier.padding(start = 20.dp, top = 4.dp, bottom = 4.dp))
                        }
                    }
                    items(filtered, key = { it.file.absolutePath }) { entry ->
                        LocalFileItem(
                            entry = entry,
                            onClick = {
                                if (entry.isDir) navigate(entry.file)
                                else {
                                    try {
                                        val uri = FileProvider.getUriForFile(context, "${context.packageName}.fileprovider", entry.file)
                                        context.startActivity(Intent(Intent.ACTION_VIEW).apply {
                                            setDataAndType(uri, entry.file.name.mimeType())
                                            clipData = ClipData.newRawUri("", uri)
                                            addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK)
                                        })
                                    } catch (e: Exception) {
                                        scope.launch { snackbarHostState.showSnackbar("No app can open this file") }
                                    }
                                }
                            },
                            onShare = {
                                try {
                                    val uri = FileProvider.getUriForFile(context, "${context.packageName}.fileprovider", entry.file)
                                    context.startActivity(Intent.createChooser(Intent(Intent.ACTION_SEND).apply {
                                        type = entry.file.name.mimeType()
                                        putExtra(Intent.EXTRA_STREAM, uri)
                                        clipData = ClipData.newRawUri("", uri)
                                        addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK)
                                    }, "Share").apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) })
                                } catch (_: Exception) {}
                            },
                        )
                    }
                    item { Spacer(Modifier.height(80.dp)) }
                }
            }
        }

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

// ── Cloud file explorer ───────────────────────────────────────────────────────

@Composable
private fun CloudExplorer(
    vm: FilesViewModel,
    selectedAccountId: Long,
    onAccountSelect: (Long) -> Unit,
    modifier: Modifier = Modifier,
) {
    val accounts by vm.accounts.collectAsState()
    val cloudVm: RemoteBrowserViewModel = hiltViewModel(key = "cloud_explorer")
    val state by cloudVm.state.collectAsState()
    val breadcrumbState = rememberLazyListState()
    val scope = rememberCoroutineScope()
    var searchQuery by remember { mutableStateOf("") }
    var searchActive by remember { mutableStateOf(false) }

    LaunchedEffect(selectedAccountId) {
        if (selectedAccountId != -1L) cloudVm.init(selectedAccountId, "/")
    }

    LaunchedEffect(state.currentPath) {
        val segs = state.currentPath.trimEnd('/').split('/').filter { it.isNotEmpty() }
        scope.launch { breadcrumbState.animateScrollToItem(maxOf(0, segs.size)) }
        searchQuery = ""; searchActive = false
    }

    BackHandler(enabled = state.pathStack.size > 1) { cloudVm.navigateUp() }

    if (accounts.isEmpty()) {
        Box(modifier = modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
            Column(horizontalAlignment = Alignment.CenterHorizontally) {
                Icon(Icons.Default.CloudOff, null, Modifier.size(56.dp),
                    tint = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.4f))
                Spacer(Modifier.height(12.dp))
                Text("No cloud accounts", style = MaterialTheme.typography.bodyLarge,
                    color = MaterialTheme.colorScheme.onSurfaceVariant)
                Text("Add an account in Settings", style = MaterialTheme.typography.bodySmall,
                    color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.6f))
            }
        }
        return
    }

    val segments = state.currentPath.trimEnd('/').split('/').filter { it.isNotEmpty() }
    val filtered = if (searchQuery.isBlank()) state.entries
    else state.entries.filter { it.name.contains(searchQuery, ignoreCase = true) }

    Column(modifier = modifier) {

        // ── Account chips ─────────────────────────────────────────────────────
        if (accounts.size > 1) {
            LazyRow(
                contentPadding = PaddingValues(horizontal = 12.dp, vertical = 8.dp),
                horizontalArrangement = Arrangement.spacedBy(8.dp),
            ) {
                items(accounts) { acct ->
                    FilterChip(
                        selected = acct.id == selectedAccountId,
                        onClick = { onAccountSelect(acct.id); cloudVm.init(acct.id, "/") },
                        label = { Text(acct.displayName, maxLines = 1) },
                        leadingIcon = { Icon(Icons.Default.Cloud, null, Modifier.size(14.dp)) },
                    )
                }
            }
            HorizontalDivider()
        }

        // ── Breadcrumbs / search ──────────────────────────────────────────────
        Surface(tonalElevation = 1.dp) {
            if (searchActive) {
                val focusRequester = remember { FocusRequester() }
                LaunchedEffect(Unit) { focusRequester.requestFocus() }
                Row(
                    modifier = Modifier.fillMaxWidth().padding(horizontal = 8.dp, vertical = 4.dp),
                    verticalAlignment = Alignment.CenterVertically,
                ) {
                    OutlinedTextField(
                        value = searchQuery, onValueChange = { searchQuery = it },
                        modifier = Modifier.weight(1f).focusRequester(focusRequester),
                        placeholder = { Text("Search in folder…") }, singleLine = true,
                        keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search),
                        keyboardActions = KeyboardActions(onSearch = {}),
                        colors = OutlinedTextFieldDefaults.colors(
                            focusedBorderColor = Color.Transparent, unfocusedBorderColor = Color.Transparent,
                        ),
                    )
                    IconButton(onClick = { searchActive = false; searchQuery = "" }) { Icon(Icons.Default.Close, null) }
                }
            } else {
                LazyRow(
                    state = breadcrumbState,
                    modifier = Modifier.fillMaxWidth().padding(horizontal = 8.dp, vertical = 6.dp),
                    verticalAlignment = Alignment.CenterVertically,
                    horizontalArrangement = Arrangement.spacedBy(2.dp),
                ) {
                    item { BreadcrumbChip("☁ Root", segments.isEmpty()) { cloudVm.navigateToBreadcrumb("/") } }
                    itemsIndexed(segments) { idx, seg ->
                        Icon(Icons.Default.ChevronRight, null, Modifier.size(14.dp), tint = MaterialTheme.colorScheme.onSurfaceVariant)
                        val segPath = "/" + segments.take(idx + 1).joinToString("/")
                        BreadcrumbChip(seg, idx == segments.lastIndex) { cloudVm.navigateToBreadcrumb(segPath) }
                    }
                    item {
                        Spacer(Modifier.width(4.dp))
                        IconButton(onClick = { searchActive = true }, modifier = Modifier.size(28.dp)) {
                            Icon(Icons.Default.Search, null, Modifier.size(18.dp), tint = MaterialTheme.colorScheme.onSurfaceVariant)
                        }
                    }
                }
            }
        }
        HorizontalDivider()

        // ── Content ───────────────────────────────────────────────────────────
        Box(modifier = Modifier.weight(1f)) {
            when {
                state.isLoading -> Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
                    CircularProgressIndicator()
                }
                state.error != null -> Column(
                    modifier = Modifier.fillMaxSize().padding(32.dp),
                    horizontalAlignment = Alignment.CenterHorizontally,
                    verticalArrangement = Arrangement.Center,
                ) {
                    Icon(Icons.Default.CloudOff, null, Modifier.size(56.dp), tint = MaterialTheme.colorScheme.error)
                    Spacer(Modifier.height(12.dp))
                    Text(state.error!!, color = MaterialTheme.colorScheme.error, style = MaterialTheme.typography.bodyMedium)
                    Spacer(Modifier.height(16.dp))
                    FilledTonalButton(onClick = cloudVm::retry) {
                        Icon(Icons.Default.Refresh, null, Modifier.size(18.dp))
                        Spacer(Modifier.width(6.dp))
                        Text("Retry")
                    }
                }
                filtered.isEmpty() -> Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
                    Column(horizontalAlignment = Alignment.CenterHorizontally) {
                        Icon(Icons.Default.FolderOpen, null, Modifier.size(56.dp),
                            tint = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.4f))
                        Spacer(Modifier.height(12.dp))
                        Text(
                            if (searchQuery.isBlank()) "Empty folder" else "No results for \"$searchQuery\"",
                            style = MaterialTheme.typography.bodyLarge,
                            color = MaterialTheme.colorScheme.onSurfaceVariant,
                        )
                    }
                }
                else -> LazyColumn(modifier = Modifier.fillMaxSize()) {
                    items(filtered, key = { it.path }) { entry ->
                        CloudFileItem(
                            file = entry,
                            onClick = {
                                if (entry.isDirectory) cloudVm.navigateTo(entry.path)
                                else vm.openCloudFile(selectedAccountId, entry.path)
                            },
                        )
                    }
                    item { Spacer(Modifier.height(80.dp)) }
                }
            }
        }
    }
}

// ── Shared UI components ──────────────────────────────────────────────────────

@Composable
private fun BreadcrumbChip(label: String, isLast: Boolean, onClick: () -> Unit) {
    if (isLast) {
        Surface(shape = RoundedCornerShape(8.dp), color = MaterialTheme.colorScheme.primaryContainer) {
            Text(label, modifier = Modifier.padding(horizontal = 10.dp, vertical = 4.dp),
                style = MaterialTheme.typography.labelMedium, fontWeight = FontWeight.SemiBold,
                color = MaterialTheme.colorScheme.onPrimaryContainer, maxLines = 1)
        }
    } else {
        TextButton(onClick = onClick, contentPadding = PaddingValues(horizontal = 8.dp, vertical = 2.dp)) {
            Text(label, style = MaterialTheme.typography.labelMedium,
                color = MaterialTheme.colorScheme.primary, maxLines = 1)
        }
    }
}

@Composable
private fun LocalFileItem(entry: LocalEntry, onClick: () -> Unit, onShare: () -> Unit) {
    var menuExpanded by remember { mutableStateOf(false) }
    Row(
        modifier = Modifier.fillMaxWidth().clickable(onClick = onClick).padding(horizontal = 16.dp, vertical = 10.dp),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.spacedBy(14.dp),
    ) {
        Box(
            modifier = Modifier.size(46.dp).clip(RoundedCornerShape(12.dp)).background(
                if (entry.isDir) Color(0xFF1B5E20).copy(alpha = 0.12f) else Color(0xFF0D47A1).copy(alpha = 0.10f)
            ),
            contentAlignment = Alignment.Center,
        ) {
            Icon(
                imageVector = if (entry.isDir) Icons.Default.Folder else fileIcon(entry.file.name),
                contentDescription = null, modifier = Modifier.size(26.dp),
                tint = if (entry.isDir) Color(0xFF2E7D32) else Color(0xFF1565C0),
            )
        }
        Column(modifier = Modifier.weight(1f)) {
            Text(entry.file.name, style = MaterialTheme.typography.bodyLarge, maxLines = 1,
                overflow = TextOverflow.Ellipsis,
                fontWeight = if (entry.isDir) FontWeight.Medium else FontWeight.Normal)
            Text(
                if (entry.isDir) "${entry.childCount} item${if (entry.childCount != 1) "s" else ""}"
                else entry.sizeBytes.toDisplaySize(),
                style = MaterialTheme.typography.bodySmall,
                color = MaterialTheme.colorScheme.onSurfaceVariant,
            )
        }
        if (entry.isDir) {
            Icon(Icons.Default.ChevronRight, null, Modifier.size(20.dp),
                tint = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.5f))
        } else {
            Box {
                IconButton(onClick = { menuExpanded = true }, modifier = Modifier.size(36.dp)) {
                    Icon(Icons.Default.MoreVert, null, Modifier.size(18.dp), tint = MaterialTheme.colorScheme.onSurfaceVariant)
                }
                DropdownMenu(expanded = menuExpanded, onDismissRequest = { menuExpanded = false }) {
                    DropdownMenuItem(text = { Text("Open") }, leadingIcon = { Icon(Icons.Default.OpenInNew, null) },
                        onClick = { menuExpanded = false; onClick() })
                    DropdownMenuItem(text = { Text("Share") }, leadingIcon = { Icon(Icons.Default.Share, null) },
                        onClick = { menuExpanded = false; onShare() })
                }
            }
        }
    }
    HorizontalDivider(modifier = Modifier.padding(start = 76.dp), thickness = 0.5.dp)
}

@Composable
private fun CloudFileItem(file: com.syncflow.domain.model.RemoteFile, onClick: () -> Unit) {
    Row(
        modifier = Modifier.fillMaxWidth().clickable(onClick = onClick).padding(horizontal = 16.dp, vertical = 10.dp),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.spacedBy(14.dp),
    ) {
        Box(
            modifier = Modifier.size(46.dp).clip(RoundedCornerShape(12.dp)).background(
                if (file.isDirectory) Color(0xFF1B5E20).copy(alpha = 0.12f) else Color(0xFF0D47A1).copy(alpha = 0.10f)
            ),
            contentAlignment = Alignment.Center,
        ) {
            Icon(
                imageVector = if (file.isDirectory) Icons.Default.Folder else fileIcon(file.name),
                contentDescription = null, modifier = Modifier.size(26.dp),
                tint = if (file.isDirectory) Color(0xFF2E7D32) else Color(0xFF1565C0),
            )
        }
        Column(modifier = Modifier.weight(1f)) {
            Text(file.name, style = MaterialTheme.typography.bodyLarge, maxLines = 1,
                overflow = TextOverflow.Ellipsis,
                fontWeight = if (file.isDirectory) FontWeight.Medium else FontWeight.Normal)
            if (!file.isDirectory) {
                Text(file.sizeBytes.toDisplaySize(), style = MaterialTheme.typography.bodySmall,
                    color = MaterialTheme.colorScheme.onSurfaceVariant)
            }
        }
        if (file.isDirectory) {
            Icon(Icons.Default.ChevronRight, null, Modifier.size(20.dp),
                tint = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.5f))
        } else {
            Icon(Icons.Default.FileDownload, null, Modifier.size(20.dp),
                tint = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.5f))
        }
    }
    HorizontalDivider(modifier = Modifier.padding(start = 76.dp), thickness = 0.5.dp)
}

// ── Helpers ───────────────────────────────────────────────────────────────────

private fun String.mimeType(): String {
    val ext = substringAfterLast('.', "").lowercase()
    return MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext) ?: "*/*"
}

private fun fileIcon(name: String): ImageVector = when {
    name.endsWith(".pdf", ignoreCase = true) -> Icons.Default.PictureAsPdf
    name.endsWith(".jpg", ignoreCase = true) || name.endsWith(".jpeg", ignoreCase = true) ||
        name.endsWith(".png", ignoreCase = true) || name.endsWith(".gif", ignoreCase = true) ||
        name.endsWith(".webp", ignoreCase = true) -> Icons.Default.Image
    name.endsWith(".mp4", ignoreCase = true) || name.endsWith(".mkv", ignoreCase = true) ||
        name.endsWith(".mov", ignoreCase = true) -> Icons.Default.VideoFile
    name.endsWith(".mp3", ignoreCase = true) || name.endsWith(".m4a", ignoreCase = true) ||
        name.endsWith(".ogg", ignoreCase = true) -> Icons.Default.AudioFile
    name.endsWith(".zip", ignoreCase = true) || name.endsWith(".tar", ignoreCase = true) ||
        name.endsWith(".gz", ignoreCase = true) -> Icons.Default.FolderZip
    name.endsWith(".txt", ignoreCase = true) || name.endsWith(".md", ignoreCase = true) -> Icons.Default.TextSnippet
    else -> Icons.Default.InsertDriveFile
}

private fun Long.toDisplaySize(): String = when {
    this < 1_024 -> "$this B"
    this < 1_048_576 -> "${"%.1f".format(this / 1_024.0)} KB"
    this < 1_073_741_824 -> "${"%.1f".format(this / 1_048_576.0)} MB"
    else -> "${"%.1f".format(this / 1_073_741_824.0)} GB"
}
