package chat.vojo.proxy.ui

import android.annotation.SuppressLint
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.selection.toggleable
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import chat.vojo.proxy.data.AppInfo
import chat.vojo.proxy.ui.theme.Vojo

@Composable
fun AppsScreen(
    apps: List<AppInfo>,
    loading: Boolean,
    selected: Set<String>,
    loadIcon: suspend (String) -> ImageBitmap?,
    cachedIcon: (String) -> ImageBitmap?,
    onToggle: (String, Boolean) -> Unit,
    onClear: () -> Unit,
    onLoad: () -> Unit,
) {
    LaunchedEffect(Unit) { onLoad() }
    var query by rememberSaveable { mutableStateOf("") }

    // All network-capable apps are shown — no system/user split.
    val filtered = remember(apps, query) {
        apps.asSequence()
            .filter { query.isBlank() || it.label.contains(query, true) || it.packageName.contains(query, true) }
            .toList()
    }
    // Selected apps pin to the top — the whitelist must be reviewable at a glance.
    val pinned = remember(apps, selected) { apps.filter { it.packageName in selected } }
    val missing = remember(apps, selected, loading) {
        if (apps.isEmpty()) emptyList()
        else (selected - apps.map { it.packageName }.toSet()).sorted()
    }
    val rest = remember(filtered, selected) { filtered.filter { it.packageName !in selected } }

    Column(Modifier.fillMaxSize()) {
        Column(Modifier.padding(horizontal = 14.dp, vertical = 12.dp)) {
            Row(verticalAlignment = Alignment.CenterVertically) {
                Text(
                    if (selected.isEmpty()) "Проксируются: все приложения" else "Проксируются",
                    color = Vojo.text, fontSize = 15.sp, fontWeight = FontWeight.SemiBold,
                )
                if (selected.isNotEmpty()) {
                    Spacer(Modifier.width(8.dp))
                    Box(
                        Modifier
                            .clip(RoundedCornerShape(99.dp))
                            .background(Vojo.fleet)
                            .padding(horizontal = 8.dp, vertical = 2.dp),
                    ) {
                        Text("${selected.size}", color = Color(0xFF0C0C0E), fontSize = 11.sp, fontWeight = FontWeight.Bold)
                    }
                }
                Spacer(Modifier.weight(1f))
                if (selected.isNotEmpty()) {
                    Text(
                        "Сбросить",
                        color = Vojo.fleetSoft, fontSize = 13.sp,
                        modifier = Modifier
                            .clip(RoundedCornerShape(8.dp))
                            .clickable { onClear() }
                            .padding(horizontal = 10.dp, vertical = 8.dp),
                    )
                }
            }
            Text(
                "Пустой список = весь трафик идёт через прокси.",
                color = Vojo.faint, fontSize = 12.sp,
            )
            Spacer(Modifier.height(12.dp))
            // Embedded search field (Fleet composer style)
            Row(
                Modifier
                    .fillMaxWidth()
                    .clip(RoundedCornerShape(12.dp))
                    .background(Vojo.bgPanel)
                    .border(1.dp, Vojo.divider, RoundedCornerShape(12.dp))
                    .padding(horizontal = 14.dp),
                verticalAlignment = Alignment.CenterVertically,
            ) {
                Icon(VojoIcons.Search, contentDescription = null, tint = Vojo.faint, modifier = Modifier.size(17.dp))
                Spacer(Modifier.width(10.dp))
                BasicTextField(
                    value = query,
                    onValueChange = { query = it },
                    singleLine = true,
                    modifier = Modifier.weight(1f),
                    textStyle = TextStyle(color = Vojo.text, fontSize = 15.sp),
                    cursorBrush = SolidColor(Vojo.fleet),
                    decorationBox = { inner ->
                        Box(Modifier.padding(vertical = 14.dp)) {
                            if (query.isEmpty()) Text("Поиск приложений…", color = Vojo.faint, fontSize = 15.sp)
                            inner()
                        }
                    },
                )
            }
        }

        if (loading && apps.isEmpty()) {
            Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
                CircularProgressIndicator(color = Vojo.fleet, strokeWidth = 2.dp)
            }
        } else {
            LazyColumn(
                Modifier.fillMaxSize(),
                contentPadding = androidx.compose.foundation.layout.PaddingValues(horizontal = 14.dp, vertical = 4.dp),
                verticalArrangement = Arrangement.spacedBy(3.dp),
            ) {
                if (query.isBlank() && (pinned.isNotEmpty() || missing.isNotEmpty())) {
                    item(key = "hdr-selected") {
                        SectionLabel("Выбранные · ${selected.size}", Modifier.padding(start = 6.dp, top = 6.dp, bottom = 6.dp))
                    }
                    items(pinned, key = { "sel:" + it.packageName }) { app ->
                        AppRow(app, true, loadIcon, cachedIcon) { on -> onToggle(app.packageName, on) }
                    }
                    items(missing, key = { "miss:$it" }) { pkg ->
                        MissingAppRow(pkg) { onToggle(pkg, false) }
                    }
                    item(key = "hdr-all") {
                        SectionLabel("Все приложения", Modifier.padding(start = 6.dp, top = 14.dp, bottom = 6.dp))
                    }
                }
                val list = if (query.isBlank()) rest else filtered
                items(list, key = { it.packageName }) { app ->
                    AppRow(app, app.packageName in selected, loadIcon, cachedIcon) { on -> onToggle(app.packageName, on) }
                }
                if (filtered.isEmpty() && query.isNotBlank()) {
                    item(key = "empty") {
                        Box(Modifier.fillMaxWidth().padding(vertical = 32.dp), contentAlignment = Alignment.Center) {
                            Text("Ничего не найдено по «$query»", color = Vojo.faint, fontSize = 14.sp)
                        }
                    }
                }
            }
        }
    }
}

@SuppressLint("ProduceStateDoesNotAssignValue") // false positive: value is assigned via suspend lambda
@Composable
private fun AppRow(
    app: AppInfo,
    checked: Boolean,
    loadIcon: suspend (String) -> ImageBitmap?,
    cachedIcon: (String) -> ImageBitmap?,
    onToggle: (Boolean) -> Unit,
) {
    // Cache hit renders instantly — no placeholder flash on fast scroll.
    val icon by produceState(initialValue = cachedIcon(app.packageName), app.packageName) {
        if (value == null) value = loadIcon(app.packageName)
    }
    Row(
        Modifier
            .fillMaxWidth()
            .clip(RoundedCornerShape(12.dp))
            .background(if (checked) Vojo.surface else Color.Transparent)
            .toggleable(value = checked, role = Role.Checkbox) { onToggle(it) }
            .padding(horizontal = 10.dp, vertical = 10.dp),
        verticalAlignment = Alignment.CenterVertically,
    ) {
        // The active-channel idiom: a 2dp accent bar marks selected rows.
        Box(
            Modifier
                .width(2.dp)
                .height(34.dp)
                .clip(RoundedCornerShape(1.dp))
                .background(if (checked) Vojo.fleet else Color.Transparent)
        )
        Spacer(Modifier.width(9.dp))
        Box(Modifier.size(40.dp).clip(RoundedCornerShape(10.dp)).background(if (checked) Vojo.surface2 else Vojo.surface), contentAlignment = Alignment.Center) {
            val img = icon
            if (img != null) {
                Image(img, contentDescription = null, modifier = Modifier.size(34.dp))
            } else {
                Text(app.label.take(1).uppercase(), color = Vojo.muted, fontSize = 15.sp)
            }
        }
        Spacer(Modifier.width(12.dp))
        Column(Modifier.weight(1f)) {
            Text(app.label, color = Vojo.text, fontSize = 15.sp, fontWeight = FontWeight.Medium, maxLines = 1, overflow = TextOverflow.Ellipsis)
            Text(app.packageName, color = Vojo.faint, fontFamily = Vojo.mono, fontSize = 11.sp, maxLines = 1, overflow = TextOverflow.Ellipsis)
        }
        Spacer(Modifier.width(10.dp))
        Checkbox(checked)
    }
}

/** A selected package that is no longer installed — visible and removable. */
@Composable
private fun MissingAppRow(packageName: String, onRemove: () -> Unit) {
    Row(
        Modifier
            .fillMaxWidth()
            .clip(RoundedCornerShape(12.dp))
            .background(Vojo.surface.copy(alpha = 0.5f))
            .clickable { onRemove() }
            .padding(horizontal = 10.dp, vertical = 10.dp),
        verticalAlignment = Alignment.CenterVertically,
    ) {
        Box(
            Modifier
                .width(2.dp)
                .height(34.dp)
                .background(Vojo.amber.copy(alpha = 0.6f))
        )
        Spacer(Modifier.width(9.dp))
        Box(Modifier.size(40.dp).clip(RoundedCornerShape(10.dp)).background(Vojo.surface), contentAlignment = Alignment.Center) {
            Text("?", color = Vojo.faint, fontSize = 15.sp)
        }
        Spacer(Modifier.width(12.dp))
        Column(Modifier.weight(1f)) {
            Text(packageName, color = Vojo.muted, fontFamily = Vojo.mono, fontSize = 13.sp, maxLines = 1, overflow = TextOverflow.Ellipsis)
            Text("не установлено · нажмите, чтобы убрать", color = Vojo.faint, fontSize = 11.sp)
        }
    }
}

@Composable
private fun Checkbox(checked: Boolean) {
    Box(
        Modifier
            .size(24.dp)
            .clip(RoundedCornerShape(7.dp))
            .background(if (checked) Vojo.fleet else Color.Transparent)
            .border(1.dp, if (checked) Vojo.fleet else Vojo.hairline, RoundedCornerShape(7.dp)),
        contentAlignment = Alignment.Center,
    ) {
        if (checked) Icon(VojoIcons.Check, contentDescription = null, tint = Color(0xFF0C0C0E), modifier = Modifier.size(14.dp))
    }
}
