package com.optix.android.ui.screens.lanmap

import androidx.compose.animation.core.*
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.*
import androidx.compose.foundation.shape.*
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.*
import androidx.compose.ui.draw.*
import androidx.compose.ui.focus.*
import androidx.compose.ui.graphics.*
import androidx.compose.ui.input.pointer.*
import androidx.compose.ui.text.*
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.unit.*
import com.optix.android.domain.model.ExportFormat
import com.optix.android.domain.model.HostResult
import com.optix.android.domain.model.Session
import com.optix.android.ui.components.*
import com.optix.android.ui.navigation.Screen
import com.optix.android.ui.theme.*
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

internal fun subnetKey(ip: String): String =
    ip.split(".").take(3).takeIf { it.size == 3 && it.all { part -> part.all(Char::isDigit) } }?.joinToString(".") ?: ""

internal fun subnetColor(index: Int): Color = when (index % 4) {
    0 -> Color(0xFF3FD4A6)
    1 -> Color(0xFF79A8FF)
    2 -> Color(0xFFFFA24C)
    else -> Color(0xFFFF6A88)
}

internal fun blendColor(base: Color, tint: Color): Color =
    Color(
        red = (base.red * 0.72f + tint.red * 0.28f).coerceIn(0f, 1f),
        green = (base.green * 0.72f + tint.green * 0.28f).coerceIn(0f, 1f),
        blue = (base.blue * 0.72f + tint.blue * 0.28f).coerceIn(0f, 1f),
        alpha = base.alpha,
    )

@Composable
internal fun ToolReadinessStrip(
    readiness: ToolReadiness,
    onRefresh: () -> Unit,
    modifier: Modifier = Modifier,
) {
    Row(
        modifier = modifier
            .background(T.surfaceVar.copy(alpha = 0.75f), RoundedCornerShape(10.dp))
            .border(1.dp, T.border.copy(alpha = 0.4f), RoundedCornerShape(10.dp))
            .padding(horizontal = 12.dp, vertical = 8.dp),
        horizontalArrangement = Arrangement.SpaceBetween,
        verticalAlignment = Alignment.CenterVertically,
    ) {
        Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
            Text("TOOL READINESS", color = T.accent, style = MaterialTheme.typography.labelSmall)
            Text(
                "${readiness.readyCount} ready  ·  ${readiness.needsTermuxCount} Termux-aware  ·  ${readiness.needsRootCount} root-sensitive",
                color = T.onSurfaceMid,
                style = MaterialTheme.typography.bodySmall,
            )
        }
        Row(horizontalArrangement = Arrangement.spacedBy(8.dp), verticalAlignment = Alignment.CenterVertically) {
            StatusBadge(if (readiness.termuxInstalled) "TERMUX READY" else "TERMUX NEEDED", if (readiness.termuxInstalled) T.success else T.warning)
            StatusBadge(if (readiness.rootAvailable) "ROOT READY" else "ROOT OPTIONAL", if (readiness.rootAvailable) T.success else T.onSurfaceMid)
            Text("REFRESH", color = T.onSurface, style = MaterialTheme.typography.labelSmall, modifier = Modifier.clickable(onClick = onRefresh))
        }
    }
}

@Composable
internal fun SetupSheet(
    bootstrapStatus: BootstrapStatus,
    readiness: ToolReadiness,
    onBootstrap: () -> Unit,
    onDismiss: () -> Unit,
    onClose: () -> Unit,
    modifier: Modifier = Modifier,
) {
    Column(
        modifier = modifier.fillMaxWidth().padding(16.dp),
        verticalArrangement = Arrangement.spacedBy(12.dp),
    ) {
        Text("SETUP / PERMISSIONS", color = T.accent, style = MaterialTheme.typography.titleMedium)

        Row(
            modifier = Modifier.fillMaxWidth(),
            horizontalArrangement = Arrangement.spacedBy(8.dp),
            verticalAlignment = Alignment.CenterVertically,
        ) {
            StatusBadge(
                if (readiness.termuxInstalled) "TERMUX READY" else "TERMUX NEEDED",
                if (readiness.termuxInstalled) T.success else T.warning,
            )
            StatusBadge(
                if (readiness.rootAvailable) "ROOT READY" else "ROOT OPTIONAL",
                if (readiness.rootAvailable) T.success else T.onSurfaceMid,
            )
        }

        Text(
            when {
                readiness.termuxInstalled -> "Termux is installed. Bootstrap installs the packages required by enabled tools."
                else -> "Termux is not installed. Install it from F-Droid, then run setup to provision required packages."
            },
            color = T.onSurfaceMid,
            style = MaterialTheme.typography.bodySmall,
        )

        when (val status = bootstrapStatus) {
            is BootstrapStatus.Running -> {
                Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) {
                    CircularProgressIndicator(Modifier.size(16.dp), T.accent, 2.dp)
                    Text("Bootstrapping capabilitiesâ€¦", color = T.onSurface, style = MaterialTheme.typography.bodyMedium)
                }
            }
            is BootstrapStatus.TermuxMissing -> {
                Text(status.message, color = T.warning, style = MaterialTheme.typography.bodySmall)
            }
            is BootstrapStatus.Done -> {
                if (status.installed.isNotEmpty()) {
                    Text("Installed: ${status.installed.joinToString()}", color = T.success, style = MaterialTheme.typography.bodySmall)
                }
                if (status.failed.isNotEmpty()) {
                    Text("Failed: ${status.failed.joinToString()}", color = T.warning, style = MaterialTheme.typography.bodySmall)
                }
                if (status.installed.isEmpty() && status.failed.isEmpty()) {
                    Text("Nothing to install — all required packages present.", color = T.onSurfaceMid, style = MaterialTheme.typography.bodySmall)
                }
            }
            else -> Unit
        }

        Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
            Button(
                onClick = onBootstrap,
                enabled = bootstrapStatus !is BootstrapStatus.Running,
                colors = ButtonDefaults.buttonColors(containerColor = T.accent, contentColor = if (T.isDark) Color.Black else Color.White),
                shape = RoundedCornerShape(3.dp),
                modifier = Modifier.weight(1f),
            ) { Text("Run Setup") }
            Button(
                onClick = onClose,
                colors = ButtonDefaults.buttonColors(containerColor = T.surfaceVar, contentColor = T.onSurface),
                shape = RoundedCornerShape(3.dp),
            ) { Text("Close") }
        }
    }
}

@Composable
internal fun ScanHistorySheet(
    sessions: List<Session>,
    onShare: (Session) -> Unit,
    onExport: (ExportFormat) -> Unit,
) {
    val formatter = remember { SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.getDefault()) }
    Column(
        modifier = Modifier.fillMaxWidth().padding(16.dp),
        verticalArrangement = Arrangement.spacedBy(10.dp),
    ) {
        Text("SCAN HISTORY", color = T.accent, style = MaterialTheme.typography.titleMedium)
        Row(
            modifier = Modifier.fillMaxWidth(),
            horizontalArrangement = Arrangement.spacedBy(8.dp),
            verticalAlignment = Alignment.CenterVertically,
        ) {
            Text("EXPORT ALL:", color = T.onSurfaceMid, style = MaterialTheme.typography.labelSmall)
            ExportButton("JSON", onExport)
            ExportButton("CSV", onExport)
            ExportButton("REPORT", onExport)
        }
        if (sessions.isEmpty()) {
            Text("No saved sessions yet.", color = T.onSurfaceMid, style = MaterialTheme.typography.bodySmall)
        } else {
            sessions.forEach { session ->
                Column(
                    modifier = Modifier
                        .fillMaxWidth()
                        .background(T.surfaceVar.copy(alpha = 0.7f), RoundedCornerShape(10.dp))
                        .border(1.dp, T.border.copy(alpha = 0.35f), RoundedCornerShape(10.dp))
                        .padding(12.dp),
                    verticalArrangement = Arrangement.spacedBy(4.dp),
                ) {
                    Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically) {
                        Text(session.toolName, color = T.onSurface, style = MaterialTheme.typography.titleSmall)
                        Text(formatter.format(Date(session.createdAt)), color = T.onSurfaceMid, style = MaterialTheme.typography.labelSmall)
                    }
                    Text("${session.results.size} results  ·  ${session.durationMs}ms", color = T.accentGlow, style = MaterialTheme.typography.bodySmall)
                    Text(
                        session.params.entries.joinToString("  ·  ") { "${it.key}=${it.value}" }.ifBlank { "No parameters captured" },
                        color = T.onSurfaceMid,
                        style = MaterialTheme.typography.bodySmall,
                    )
                    Text("SHARE", color = T.accent, style = MaterialTheme.typography.labelSmall, modifier = Modifier.clickable { onShare(session) })
                }
            }
        }
    }
}

@Composable
private fun ExportButton(label: String, onExport: (ExportFormat) -> Unit) {
    val format = when (label) {
        "JSON" -> ExportFormat.JSON
        "CSV" -> ExportFormat.CSV
        else -> ExportFormat.REPORT
    }
    Box(
        modifier = Modifier
            .background(T.accent.copy(alpha = 0.1f), RoundedCornerShape(4.dp))
            .border(1.dp, T.accent.copy(alpha = 0.4f), RoundedCornerShape(4.dp))
            .clickable { onExport(format) }
            .padding(horizontal = 10.dp, vertical = 5.dp),
    ) {
        Text(label, color = T.accent, style = MaterialTheme.typography.labelSmall)
    }
}

@Composable
internal fun BottomControlPanel(
    state: LanMapUiState,
    onPickTool: () -> Unit,
    onParamChange: (String, String) -> Unit,
    onRun: () -> Unit,
    onCancel: () -> Unit,
    onClearTarget: () -> Unit,
    onClearLogs: () -> Unit,
    onShareResult: (String) -> Unit,
    onResultAction: (ResultAction) -> Unit,
    onRunChain: () -> Unit,
    onDismissChain: () -> Unit,
    modifier: Modifier = Modifier
) {
    var selectedTab by remember { mutableStateOf("TARGET") }
    val runPulse by rememberInfiniteTransition(label = "rp").animateFloat(0.5f, 1f, infiniteRepeatable(tween(600), RepeatMode.Reverse), label = "rp")

    Column(modifier = modifier.fillMaxWidth().height(260.dp).background(T.surface).border(1.dp, T.border.copy(alpha = 0.5f))) {
        // Chain suggestion chip (follow-up after discovery)
        state.suggestedChain?.let { (toolName, params) ->
            Row(
                modifier = Modifier.fillMaxWidth().padding(horizontal = 8.dp, vertical = 2.dp)
                    .background(T.accent.copy(alpha = 0.12f), RoundedCornerShape(4.dp))
                    .border(1.dp, T.accent.copy(alpha = 0.4f), RoundedCornerShape(4.dp))
                    .padding(horizontal = 8.dp, vertical = 4.dp),
                horizontalArrangement = Arrangement.spacedBy(8.dp),
                verticalAlignment = Alignment.CenterVertically,
            ) {
                Text("NEXT:", color = T.accent, style = MaterialTheme.typography.labelSmall)
                val summary = params.entries.firstOrNull()?.value?.toString() ?: ""
                Text(
                    if (summary.isNotBlank()) "$toolName  ($summary)" else toolName,
                    color = T.onSurface, style = MaterialTheme.typography.bodySmall,
                    modifier = Modifier.weight(1f), maxLines = 1,
                )
                Text("RUN", color = T.accent, style = MaterialTheme.typography.labelSmall,
                    modifier = Modifier.clickable { onRunChain() })
                Text("✕", color = T.onSurfaceMid, style = MaterialTheme.typography.labelSmall,
                    modifier = Modifier.clickable { onDismissChain() })
            }
        }

        // Top Action Bar
        Row(
            modifier = Modifier.fillMaxWidth().padding(8.dp),
            horizontalArrangement = Arrangement.spacedBy(8.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            // Target Chip
            Box(
                modifier = Modifier
                    .background(T.surfaceVar, RoundedCornerShape(4.dp))
                    .border(1.dp, if (state.activeTargetIp != null) T.accent else T.border, RoundedCornerShape(4.dp))
                    .clickable { selectedTab = "TARGET" }
                    .padding(horizontal = 8.dp, vertical = 6.dp)
            ) {
                Text(
                    text = state.activeTargetIp?.let { "TARGET: $it" } ?: "NO TARGET",
                    color = if (state.activeTargetIp != null) T.accent else T.onSurfaceMid,
                    style = MaterialTheme.typography.labelSmall
                )
            }

            // Tool Picker
            Row(
                modifier = Modifier.weight(1f).background(T.surfaceVar, RoundedCornerShape(4.dp)).border(1.dp, T.border, RoundedCornerShape(4.dp))
                    .clickable { onPickTool(); selectedTab = "TOOL" }.padding(horizontal = 8.dp, vertical = 6.dp),
                horizontalArrangement = Arrangement.SpaceBetween,
                verticalAlignment = Alignment.CenterVertically
            ) {
                Text(state.selectedTool?.displayName ?: "SELECT TOOL", color = if (state.selectedTool != null) T.onSurface else T.onSurfaceMid, style = MaterialTheme.typography.labelSmall)
                Icon(Icons.Default.ArrowDropDown, null, tint = T.onSurfaceMid, modifier = Modifier.size(14.dp))
            }

            // Run Button
            Box(
                modifier = Modifier
                    .background(if (state.isRunning) T.warning.copy(alpha = 0.2f) else T.accent.copy(alpha = 0.1f), RoundedCornerShape(4.dp))
                    .border(1.dp, if (state.isRunning) T.warning else T.accent, RoundedCornerShape(4.dp))
                    .clickable { if (state.isRunning) onCancel() else onRun() }
                    .padding(horizontal = 12.dp, vertical = 6.dp)
            ) {
                Text(
                    if (state.isRunning) "STOP" else "RUN",
                    color = if (state.isRunning) T.warning else T.accent,
                    style = MaterialTheme.typography.labelSmall
                )
            }
        }

        // Tabs
        Row(modifier = Modifier.fillMaxWidth().padding(horizontal = 8.dp), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
            listOf("TARGET", "TOOL", "CONSOLE").forEach { tab ->
                val isSelected = selectedTab == tab
                Text(
                    tab,
                    color = if (isSelected) T.accent else T.onSurfaceMid,
                    style = MaterialTheme.typography.labelSmall,
                    modifier = Modifier.clickable { selectedTab = tab }.padding(horizontal = 4.dp, vertical = 4.dp)
                )
            }

            Spacer(modifier = Modifier.weight(1f))

            if (selectedTab == "CONSOLE") {
                Text("CLEAR", color = T.onSurfaceMid, style = MaterialTheme.typography.labelSmall, modifier = Modifier.clickable { onClearLogs() }.padding(horizontal = 4.dp, vertical = 4.dp))
            }
        }

        Box(modifier = Modifier.fillMaxWidth().weight(1f).background(T.background.copy(alpha = 0.5f))) {
            when (selectedTab) {
                "TARGET" -> TargetDetailsTab(state, onClearTarget)
                "TOOL" -> ToolConfigTab(state, onParamChange, onRun, onCancel, onShareResult, onResultAction)
                "CONSOLE" -> ConsoleStream(logs = state.globalConsoleLogs, modifier = Modifier.fillMaxSize())
            }
        }
    }
}

@Composable
private fun TargetDetailsTab(state: LanMapUiState, onClearTarget: () -> Unit) {
    val targetScrollState = rememberScrollState()
    val node = state.nodes.find { it.ip == state.activeTargetIp }

    Box(modifier = Modifier.fillMaxSize()) {
        Column(
            modifier = Modifier.fillMaxSize().verticalScroll(targetScrollState).padding(12.dp),
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            if (node != null) {
                val context = androidx.compose.ui.platform.LocalContext.current
                Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically) {
                    Column {
                        Text(node.alias?.takeIf { it.isNotBlank() } ?: node.deviceType ?: "Network Host", color = T.onSurface, style = MaterialTheme.typography.titleSmall)
                        Text(node.ip, color = T.accentGlow, style = MaterialTheme.typography.titleMedium, fontFamily = FontFamily.Monospace)
                    }
                    Row(horizontalArrangement = Arrangement.spacedBy(6.dp)) {
                        Box(
                            modifier = Modifier
                                .background(T.accent.copy(alpha = 0.12f), RoundedCornerShape(4.dp))
                                .border(1.dp, T.accent.copy(alpha = 0.4f), RoundedCornerShape(4.dp))
                                .clickable {
                                    val clipboard = context.getSystemService(android.content.Context.CLIPBOARD_SERVICE) as android.content.ClipboardManager
                                    val clip = android.content.ClipData.newPlainText("IP Address", node.ip)
                                    clipboard.setPrimaryClip(clip)
                                }
                                .padding(horizontal = 8.dp, vertical = 4.dp)
                        ) {
                            Text("COPY IP", color = T.accent, style = MaterialTheme.typography.labelSmall)
                        }
                    }
                }
                node.hostname?.takeIf { it.isNotBlank() && it != node.ip }?.let { Text(it, color = T.onSurfaceMid, style = MaterialTheme.typography.bodySmall, maxLines = 1) }
                Text("TYPE: ${node.deviceType ?: "Network Host"}", color = T.onSurfaceMid, style = MaterialTheme.typography.bodySmall)
                Text(if (node.transport == "wifi") "BSSID: ${node.macAddress ?: "Unknown"}" else "MAC: ${node.macAddress ?: "Unknown"}", color = T.onSurfaceMid, style = MaterialTheme.typography.bodySmall)

                if (node.transport == "wifi") {
                    Text("SECURITY: ${node.security ?: "Unknown"}", color = T.onSurface, style = MaterialTheme.typography.bodySmall)
                    Text("SIGNAL: ${node.signalLevelDbm?.let { "$it dBm" } ?: "Unknown"}", color = T.onSurfaceMid, style = MaterialTheme.typography.bodySmall)
                } else {
                    Text("PORTS: ${if (node.openPorts.isNotEmpty()) node.openPorts.joinToString(", ") else "None yet"}", color = T.onSurface, style = MaterialTheme.typography.bodySmall)
                }

                TextButton(onClick = onClearTarget, contentPadding = PaddingValues(0.dp)) {
                    Text("CLEAR TARGET", color = T.warning, style = MaterialTheme.typography.labelSmall)
                }
            } else {
                Text("No target selected", color = T.onSurface, style = MaterialTheme.typography.titleSmall)
                Text("Select a node on the globe to view details here.", color = T.onSurfaceMid, style = MaterialTheme.typography.bodySmall)
            }
        }
    }
}

@Composable
private fun ToolConfigTab(
    state: LanMapUiState,
    onParamChange: (String, String) -> Unit,
    onRun: () -> Unit,
    onCancel: () -> Unit,
    onShareResult: (String) -> Unit,
    onResultAction: (ResultAction) -> Unit,
) {
    val toolListState = rememberLazyListState()

    Box(modifier = Modifier.fillMaxSize()) {
        LazyColumn(
            state = toolListState,
            modifier = Modifier.fillMaxSize().padding(end = 8.dp),
            contentPadding = PaddingValues(12.dp),
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            if (state.selectedTool != null) {
                item {
                    ToolConfigForm(
                        tool = state.selectedTool,
                        params = state.params,
                        onParamChange = onParamChange,
                        onRun = onRun,
                        onCancel = onCancel,
                        isRunning = state.isRunning
                    )
                }
                state.progress?.let { (cur, total) ->
                    item { NeonProgressBar(cur to total, Modifier.fillMaxWidth()) }
                }
                state.error?.let { err ->
                    item { Text("⚠ $err", color = T.warning, style = MaterialTheme.typography.bodySmall) }
                }
                if (state.results.isNotEmpty()) {
                    item { Text("RESULTS", color = T.onSurfaceMid, style = MaterialTheme.typography.labelSmall) }
                    items(state.results) { result -> ResultCard(result = result, onExport = onShareResult, onAction = onResultAction) }
                }
            } else {
                item { Text("SELECT A TOOL TO BEGIN", color = T.onSurfaceMid, style = MaterialTheme.typography.labelLarge, modifier = Modifier.padding(12.dp)) }
            }
        }
    }
}

@Composable
internal fun TopScreenTabs(
    currentScreen: Screen,
    runningByRoute: Map<String, Boolean>,
    onNavigate: (Screen) -> Unit,
    modifier: Modifier = Modifier,
) {
    Row(modifier = modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(6.dp)) {
        listOf(Screen.Chat, Screen.Network).forEach { screen ->
            val selected = currentScreen.route == screen.route
            val isRunning = runningByRoute[screen.route] == true
            val pulseAlpha by rememberInfiniteTransition(label = "tab-${screen.route}").animateFloat(
                0.4f, 1f, infiniteRepeatable(tween(700), RepeatMode.Reverse), label = "tab-pulse-${screen.route}"
            )
            Row(
                modifier = Modifier
                    .weight(1f)
                    .background(if (selected) T.accent.copy(alpha = 0.12f) else T.surfaceVar.copy(alpha = 0.88f), RoundedCornerShape(999.dp))
                    .border(1.dp, if (selected) T.accent.copy(alpha = 0.40f) else T.border.copy(alpha = 0.45f), RoundedCornerShape(999.dp))
                    .clickable { onNavigate(screen) }
                    .padding(horizontal = 10.dp, vertical = 6.dp),
                horizontalArrangement = Arrangement.SpaceBetween,
                verticalAlignment = Alignment.CenterVertically,
            ) {
                Row(horizontalArrangement = Arrangement.spacedBy(8.dp), verticalAlignment = Alignment.CenterVertically) {
                    Icon(screen.icon, screen.label, tint = if (selected) T.accent else T.onSurfaceMid, modifier = Modifier.size(14.dp))
                    Text(screen.label, color = if (selected) T.accent else T.onSurface, style = MaterialTheme.typography.labelSmall)
                }
                if (isRunning) {
                    Box(Modifier.size(6.dp).background(T.success.copy(alpha = pulseAlpha), CircleShape))
                }
            }
        }
    }
}

@Composable
internal fun CornerZoomButton(
    label: String,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
) {
    Box(
        modifier = modifier
            .size(44.dp)
            .background(T.background.copy(alpha = 0.78f), RoundedCornerShape(999.dp))
            .border(1.dp, T.border.copy(alpha = 0.45f), RoundedCornerShape(999.dp))
            .clickable(onClick = onClick),
        contentAlignment = Alignment.Center,
    ) {
        Text(label, color = T.onSurface, style = MaterialTheme.typography.labelMedium)
    }
}

@Composable
private fun PanelScrollbar(
    modifier: Modifier = Modifier,
) {
    Box(
        modifier = modifier
            .width(3.dp)
            .background(T.border.copy(alpha = 0.16f), RoundedCornerShape(999.dp)),
    ) {
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .fillMaxHeight(0.28f)
                .align(Alignment.TopCenter)
                .offset(y = 18.dp)
                .background(T.onSurfaceMid.copy(alpha = 0.48f), RoundedCornerShape(999.dp)),
        )
    }
}



@Composable
internal fun ResultsDropdown(
    nodes: List<HostResult>,
    gatewayIp: String?,
    onSelectNode: (HostResult) -> Unit,
    onSetTarget: (HostResult) -> Unit,
    onSelectTool: (String, String) -> Unit,
    modifier: Modifier = Modifier,
) {
    var expanded by remember { mutableStateOf(false) }
    val visibleNodes = nodes.filter { it.ip != gatewayIp }
    val resultsState = rememberLazyListState()

    Column(modifier = modifier.width(220.dp)) {
        Row(
            modifier = Modifier
                .background(T.surface, RoundedCornerShape(6.dp))
                .border(1.dp, T.border.copy(alpha = 0.35f), RoundedCornerShape(6.dp))
                .clickable { expanded = !expanded }
                .padding(horizontal = 14.dp, vertical = 10.dp),
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.SpaceBetween,
        ) {
            Column {
                Text("RESULTS", color = T.accent, style = MaterialTheme.typography.labelSmall)
                Text("${nodes.size} hosts", color = T.onSurfaceMid, style = MaterialTheme.typography.bodySmall)
            }
            Icon(
                if (expanded) Icons.Default.KeyboardArrowUp else Icons.Default.KeyboardArrowDown,
                contentDescription = null,
                tint = T.accent,
                modifier = Modifier.size(18.dp),
            )
        }

        if (expanded) {
            Box(
                modifier = Modifier
                    .fillMaxWidth()
                    .background(T.surfaceVar, RoundedCornerShape(6.dp))
                    .border(1.dp, T.border.copy(alpha = 0.20f), RoundedCornerShape(6.dp))
                    .padding(6.dp)
                    .heightIn(max = 280.dp),
            ) {
                if (visibleNodes.isEmpty()) {
                    Text(
                        "No hosts found. Run a scan.",
                        color = T.onSurfaceMid,
                        style = MaterialTheme.typography.bodySmall,
                        modifier = Modifier.padding(8.dp),
                    )
                } else {
                    Box(modifier = Modifier.fillMaxWidth()) {
                        LazyColumn(
                            state = resultsState,
                            modifier = Modifier.fillMaxWidth().padding(end = 8.dp),
                            verticalArrangement = Arrangement.spacedBy(2.dp),
                        ) {
                            items(visibleNodes) { node ->
                                Row(
                                    modifier = Modifier
                                        .fillMaxWidth()
                                        .clickable { onSelectNode(node); expanded = false }
                                        .padding(horizontal = 10.dp, vertical = 8.dp),
                                    horizontalArrangement = Arrangement.SpaceBetween,
                                    verticalAlignment = Alignment.CenterVertically,
                                ) {
                                    Text(
                                        node.ip,
                                        color = T.textAccent,
                                        style = MaterialTheme.typography.bodySmall,
                                        fontFamily = FontFamily.Monospace,
                                    )
                                    Text(
                                        node.alias?.takeIf { it.isNotBlank() }
                                            ?: node.deviceType?.takeIf { it.isNotBlank() }
                                            ?: node.hostname?.takeIf { it.isNotBlank() && it != node.ip }
                                            ?: "Unknown",
                                        color = T.onSurfaceMid,
                                        style = MaterialTheme.typography.labelSmall,
                                        maxLines = 1,
                                    )
                                }
                            }
                        }
                        MinimalLazyScrollbar(
                            state = resultsState,
                            itemCount = visibleNodes.size,
                            modifier = Modifier.align(Alignment.CenterEnd).fillMaxHeight(),
                        )
                    }
                }
            }
        }
    }
}

@Composable
private fun NodeDetailPanel(
    node: HostResult,
    isActiveTarget: Boolean,
    isPortScanning: Boolean,
    portScanProgress: Pair<Int, Int>?,
    onAliasChange: (String) -> Unit,
    onPortScan: () -> Unit,
    onSetTarget: () -> Unit,
    onChainTool: (String) -> Unit,
    onDismiss: () -> Unit,
    modifier: Modifier = Modifier,
) {
    var aliasText by remember(node.ip, node.alias) { mutableStateOf(node.alias ?: "") }
    Box(
        modifier = modifier
            .fillMaxWidth()
            .padding(bottom = 16.dp)
            .background(T.surface.copy(alpha = 0.85f), RoundedCornerShape(14.dp))
            .border(1.dp, T.accent.copy(alpha = 0.5f), RoundedCornerShape(14.dp))
            .padding(18.dp),
    ) {
        Column(
            modifier = Modifier.verticalScroll(rememberScrollState()),
            verticalArrangement = Arrangement.spacedBy(12.dp)
        ) {
            Row(
                Modifier.fillMaxWidth(),
                horizontalArrangement = Arrangement.SpaceBetween,
                verticalAlignment = Alignment.CenterVertically,
            ) {
                Column {
                    node.alias?.takeIf { it.isNotBlank() }?.let {
                        Text(it, color = T.onSurface, style = MaterialTheme.typography.titleSmall)
                    }
                    Text(node.ip, color = T.accent, style = MaterialTheme.typography.titleMedium)
                    node.hostname?.takeIf { it.isNotBlank() }?.let {
                        Text(it, color = T.onSurfaceMid, style = MaterialTheme.typography.bodySmall)
                    }
                }
                IconButton(onClick = onDismiss, modifier = Modifier.size(28.dp)) {
                    Icon(Icons.Default.Close, contentDescription = "Dismiss", tint = T.onSurfaceMid)
                }
            }

            Row(horizontalArrangement = Arrangement.spacedBy(8.dp), verticalAlignment = Alignment.CenterVertically) {
                StatusBadge(node.status, if (node.status.contains("up", true)) T.success else T.onSurfaceMid)
                if (isActiveTarget) {
                    StatusBadge("ACTIVE TARGET", T.accentGlow)
                }
            }

            OutlinedTextField(
                value = aliasText,
                onValueChange = { aliasText = it },
                modifier = Modifier
                    .fillMaxWidth()
                    .onFocusChanged { focusState ->
                        if (!focusState.isFocused) onAliasChange(aliasText)
                    },
                label = { Text("Device label") },
                singleLine = true,
                keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
                keyboardActions = KeyboardActions(onDone = { onAliasChange(aliasText) }),
                trailingIcon = {
                    TextButton(onClick = { onAliasChange(aliasText) }) {
                        Text("SAVE", color = T.accent, style = MaterialTheme.typography.labelSmall)
                    }
                },
            )

            Text(
                buildString {
                    append("STATUS: ${node.status}")
                    node.latencyMs.takeIf { it > 0 }?.let { append("  ·  LATENCY: ${it}ms") }
                },
                color = T.onSurfaceMid,
                style = MaterialTheme.typography.bodySmall,
            )

            node.deviceType?.takeIf { it.isNotBlank() }?.let {
                Text("TYPE: $it", color = T.onSurface, style = MaterialTheme.typography.bodySmall)
            }
            Text(
                if (node.transport == "wifi") "BSSID: ${node.macAddress ?: "Unknown"}"
                else "MAC: ${node.macAddress ?: "Unknown"}",
                color = T.onSurfaceMid,
                style = MaterialTheme.typography.bodySmall,
            )
            if (node.transport == "wifi") {
                Text("SECURITY: ${node.security ?: "Unknown"}", color = T.onSurface, style = MaterialTheme.typography.bodySmall)
                Text("SIGNAL: ${node.signalLevelDbm?.let { "$it dBm" } ?: "Unknown"}", color = T.onSurfaceMid, style = MaterialTheme.typography.bodySmall)
                node.note?.takeIf { it.isNotBlank() }?.let {
                    Text(it, color = T.success, style = MaterialTheme.typography.bodySmall)
                }
            } else {
                Text(
                    "PORTS: ${if (node.openPorts.isNotEmpty()) node.openPorts.joinToString(", ") else "None discovered yet"}",
                    color = if (node.openPorts.isNotEmpty()) T.onSurface else T.onSurfaceMid,
                    style = MaterialTheme.typography.bodySmall,
                )
            }

            if (node.transport != "wifi" && isPortScanning) {
                val progressText = portScanProgress?.let { "${it.first}/${it.second}" } ?: "…"
                Text("PORT SCAN: $progressText", color = T.success, style = MaterialTheme.typography.bodySmall)
            }

            Row(horizontalArrangement = Arrangement.spacedBy(10.dp), modifier = Modifier.fillMaxWidth()) {
                Button(
                    onClick = onSetTarget,
                    enabled = node.transport != "wifi",
                    colors = ButtonDefaults.buttonColors(containerColor = T.accent, contentColor = if (T.isDark) Color.Black else Color.White),
                    shape = RoundedCornerShape(8.dp),
                    modifier = Modifier.weight(1f),
                ) {
                    Text(if (node.transport == "wifi") "NOT AN IP TARGET" else "SET TARGET")
                }
                OutlinedButton(
                    onClick = if (node.transport == "wifi") onDismiss else onPortScan,
                    colors = ButtonDefaults.outlinedButtonColors(contentColor = T.accent),
                    shape = RoundedCornerShape(8.dp),
                    modifier = Modifier.weight(1f),
                ) {
                    Text(if (node.transport == "wifi") "DISMISS" else if (isPortScanning) "SCANNING…" else "SCAN PORTS")
                }
            }

            if (node.transport != "wifi" && !isPortScanning) {
                Row(horizontalArrangement = Arrangement.spacedBy(10.dp), modifier = Modifier.fillMaxWidth()) {
                    OutlinedButton(
                        onClick = { onChainTool("port_scanner") },
                        colors = ButtonDefaults.outlinedButtonColors(contentColor = T.onSurface),
                        shape = RoundedCornerShape(8.dp),
                        modifier = Modifier.weight(1f),
                    ) {
                        Text("CHAIN PORT SCAN")
                    }
                    OutlinedButton(
                        onClick = { onChainTool("nmap_termux") },
                        colors = ButtonDefaults.outlinedButtonColors(contentColor = T.onSurface),
                        shape = RoundedCornerShape(8.dp),
                        modifier = Modifier.weight(1f),
                    ) {
                        Text("CHAIN NMAP")
                    }
                }
            }
        }
    }
}
