package chat.vojo.proxy.ui

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.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
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.platform.LocalClipboardManager
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import chat.vojo.proxy.core.ProxyConfig
import chat.vojo.proxy.core.ProxyType
import chat.vojo.proxy.core.SsCipher
import chat.vojo.proxy.core.parseProxyUri
import chat.vojo.proxy.core.ssRequiresPlugin
import chat.vojo.proxy.ui.theme.Vojo

private fun typeColor(type: ProxyType): Color = when (type) {
    ProxyType.SHADOWSOCKS -> Vojo.fleet
    ProxyType.SOCKS5 -> Vojo.blue
    ProxyType.HTTP -> Vojo.amber
    ProxyType.HTTPS -> Vojo.teal
}

@Composable
fun ServersScreen(
    configs: List<ProxyConfig>,
    activeId: String?,
    liveId: String?,
    onSelect: (String) -> Unit,
    onAdd: () -> Unit,
    onEdit: (ProxyConfig) -> Unit,
    onDelete: (String) -> Unit,
) {
    var confirmDelete by remember { mutableStateOf<ProxyConfig?>(null) }

    Box(Modifier.fillMaxSize()) {
        if (configs.isEmpty()) {
            EmptyServers(onAdd)
        } else {
            LazyColumn(
                Modifier.fillMaxSize().padding(horizontal = 14.dp),
                contentPadding = androidx.compose.foundation.layout.PaddingValues(top = 14.dp, bottom = 28.dp),
                verticalArrangement = Arrangement.spacedBy(10.dp),
            ) {
                item {
                    SectionLabel("Серверы · ${configs.size}", Modifier.padding(start = 4.dp, bottom = 4.dp))
                }
                items(configs, key = { it.id }) { cfg ->
                    ServerRow(
                        cfg = cfg,
                        selected = cfg.id == activeId,
                        live = cfg.id == liveId,
                        onClick = { onSelect(cfg.id) },
                        onEdit = { onEdit(cfg) },
                        onDelete = { confirmDelete = cfg },
                    )
                }
                item {
                    Row(
                        Modifier
                            .fillMaxWidth()
                            .height(54.dp)
                            .clip(RoundedCornerShape(14.dp))
                            .border(1.dp, Vojo.hairline, RoundedCornerShape(14.dp))
                            .clickable { onAdd() },
                        horizontalArrangement = Arrangement.Center,
                        verticalAlignment = Alignment.CenterVertically,
                    ) {
                        Icon(VojoIcons.Plus, contentDescription = null, tint = Vojo.fleetSoft, modifier = Modifier.size(17.dp))
                        Spacer(Modifier.width(8.dp))
                        Text("Добавить сервер", color = Vojo.fleetSoft, fontSize = 14.sp, fontWeight = FontWeight.Medium)
                    }
                }
            }
        }
    }

    confirmDelete?.let { cfg ->
        ConfirmDeleteDialog(
            config = cfg,
            onConfirm = { onDelete(cfg.id); confirmDelete = null },
            onDismiss = { confirmDelete = null },
        )
    }
}

@Composable
private fun ServerRow(
    cfg: ProxyConfig,
    selected: Boolean,
    live: Boolean,
    onClick: () -> Unit,
    onEdit: () -> Unit,
    onDelete: () -> Unit,
) {
    var menu by remember { mutableStateOf(false) }
    PanelCard(
        Modifier.fillMaxWidth(),
        onClick = onClick,
        accent = when {
            live -> Vojo.green.copy(alpha = 0.5f)
            selected -> Vojo.fleet.copy(alpha = 0.5f)
            else -> null
        },
        background = if (selected) Vojo.surface else Vojo.bgPanel,
    ) {
        Row(Modifier.padding(14.dp), verticalAlignment = Alignment.CenterVertically) {
            // Radio marks the SELECTED (active) server; the green name marks the
            // one that's actually LIVE in the tunnel right now.
            SelectRadio(selected)
            Spacer(Modifier.width(13.dp))
            ProtocolBadge(cfg.type.badge, typeColor(cfg.type), size = 42)
            Spacer(Modifier.width(13.dp))
            Column(Modifier.weight(1f)) {
                Row(verticalAlignment = Alignment.CenterVertically) {
                    Text(
                        cfg.name,
                        color = if (live) Vojo.green else Vojo.text,
                        fontSize = 15.sp, fontWeight = FontWeight.SemiBold,
                        maxLines = 1, overflow = TextOverflow.Ellipsis, modifier = Modifier.weight(1f, fill = false),
                    )
                    if (live) {
                        Spacer(Modifier.width(8.dp))
                        OnlineDot(Vojo.green, 7)
                    }
                }
                Spacer(Modifier.height(3.dp))
                Text(
                    cfg.handle,
                    color = Vojo.muted, fontFamily = Vojo.mono, fontSize = 13.sp,
                    maxLines = 1, overflow = TextOverflow.Ellipsis,
                )
            }
            Box {
                Icon(
                    VojoIcons.More,
                    contentDescription = "Меню сервера",
                    tint = Vojo.muted,
                    modifier = Modifier
                        .clip(RoundedCornerShape(10.dp))
                        .clickable { menu = true }
                        .padding(12.dp)
                        .size(20.dp),
                )
                DropdownMenu(expanded = menu, onDismissRequest = { menu = false }) {
                    DropdownMenuItem(
                        text = { Text("Изменить", color = Vojo.text) },
                        onClick = { menu = false; onEdit() },
                    )
                    DropdownMenuItem(
                        text = { Text("Удалить", color = Vojo.danger) },
                        onClick = { menu = false; onDelete() },
                    )
                }
            }
        }
    }
}

@Composable
private fun SelectRadio(selected: Boolean) {
    Box(
        Modifier
            .size(22.dp)
            .clip(CircleShape)
            .border(2.dp, if (selected) Vojo.fleet else Vojo.hairline, CircleShape),
        contentAlignment = Alignment.Center,
    ) {
        if (selected) Box(Modifier.size(11.dp).clip(CircleShape).background(Vojo.fleet))
    }
}

/** Deleting a server (and its password) is destructive — confirm explicitly. */
@Composable
private fun ConfirmDeleteDialog(config: ProxyConfig, onConfirm: () -> Unit, onDismiss: () -> Unit) {
    Dialog(onDismissRequest = onDismiss) {
        Column(
            Modifier
                .fillMaxWidth()
                .clip(RoundedCornerShape(18.dp))
                .background(Vojo.bgPanel)
                .border(1.dp, Vojo.hairline, RoundedCornerShape(18.dp))
                .padding(20.dp),
        ) {
            Text("Удалить сервер?", color = Vojo.text, fontSize = 18.sp, fontWeight = FontWeight.SemiBold)
            Spacer(Modifier.height(8.dp))
            Text(
                "«${config.name}» и его пароль будут удалены безвозвратно.",
                color = Vojo.muted, fontSize = 14.sp,
            )
            Spacer(Modifier.height(4.dp))
            Text(config.handle, color = Vojo.faint, fontFamily = Vojo.mono, fontSize = 13.sp)
            Spacer(Modifier.height(20.dp))
            Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) {
                Box(
                    Modifier.weight(1f).height(48.dp).clip(RoundedCornerShape(12.dp))
                        .border(1.dp, Vojo.hairline, RoundedCornerShape(12.dp))
                        .clickable { onDismiss() },
                    contentAlignment = Alignment.Center,
                ) { Text("Отмена", color = Vojo.muted, fontSize = 15.sp) }
                Box(
                    Modifier.weight(1f).height(48.dp).clip(RoundedCornerShape(12.dp))
                        .background(Vojo.danger)
                        .clickable { onConfirm() },
                    contentAlignment = Alignment.Center,
                ) { Text("Удалить", color = Color(0xFF0C0C0E), fontWeight = FontWeight.SemiBold, fontSize = 15.sp) }
            }
        }
    }
}

@Composable
private fun EmptyServers(onAdd: () -> Unit) {
    Column(
        Modifier.fillMaxSize().padding(32.dp),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally,
    ) {
        Text("Нет серверов", color = Vojo.text, fontSize = 20.sp, fontWeight = FontWeight.SemiBold)
        Spacer(Modifier.height(8.dp))
        Text(
            "Добавьте Shadowsocks, SOCKS5 или HTTP(S) прокси, чтобы начать.",
            color = Vojo.muted, fontSize = 14.sp,
            modifier = Modifier.padding(horizontal = 16.dp),
            textAlign = TextAlign.Center,
        )
        Spacer(Modifier.height(20.dp))
        Row(
            Modifier
                .clip(RoundedCornerShape(13.dp))
                .background(Vojo.fleet)
                .clickable { onAdd() }
                .padding(horizontal = 24.dp, vertical = 14.dp),
            verticalAlignment = Alignment.CenterVertically,
        ) {
            Icon(VojoIcons.Plus, contentDescription = null, tint = Color(0xFF0C0C0E), modifier = Modifier.size(17.dp))
            Spacer(Modifier.width(8.dp))
            Text("Добавить сервер", color = Color(0xFF0C0C0E), fontWeight = FontWeight.SemiBold, fontSize = 15.sp)
        }
    }
}

/** Add / edit form rendered as a dialog. */
@Composable
fun ServerEditorDialog(
    initial: ProxyConfig?,
    onSave: (ProxyConfig) -> Unit,
    onDismiss: () -> Unit,
) {
    var name by rememberSaveable { mutableStateOf(initial?.name ?: "") }
    var type by rememberSaveable { mutableStateOf(initial?.type ?: ProxyType.SHADOWSOCKS) }
    var host by rememberSaveable { mutableStateOf(initial?.host ?: "") }
    var port by rememberSaveable { mutableStateOf(initial?.port?.toString() ?: "") }
    var username by rememberSaveable { mutableStateOf(initial?.username ?: "") }
    var password by rememberSaveable { mutableStateOf(initial?.password ?: "") }
    var cipher by rememberSaveable { mutableStateOf(initial?.cipher ?: SsCipher.AES_256_GCM) }
    var errorText by rememberSaveable { mutableStateOf<String?>(null) }
    val clipboard = LocalClipboardManager.current

    Dialog(
        onDismissRequest = onDismiss,
        // Typed-in credentials must survive an accidental tap outside.
        properties = DialogProperties(dismissOnClickOutside = false),
    ) {
        Column(
            Modifier
                .fillMaxWidth()
                .clip(RoundedCornerShape(18.dp))
                .background(Vojo.bgPanel)
                .border(1.dp, Vojo.hairline, RoundedCornerShape(18.dp))
                .padding(20.dp)
                .verticalScroll(rememberScrollState()),
        ) {
            Row(verticalAlignment = Alignment.CenterVertically) {
                Text(
                    if (initial == null) "Новый сервер" else "Изменить сервер",
                    color = Vojo.text, fontSize = 19.sp, fontWeight = FontWeight.SemiBold,
                    modifier = Modifier.weight(1f),
                )
                // Most SS configs travel as ss:// links — fill the form from one.
                Row(
                    Modifier
                        .clip(RoundedCornerShape(8.dp))
                        .clickable {
                            val text = clipboard.getText()?.text ?: ""
                            val parsed = parseProxyUri(text)
                            when {
                                parsed != null -> {
                                    name = parsed.name
                                    type = parsed.type
                                    host = parsed.host
                                    port = parsed.port.toString()
                                    username = parsed.username
                                    password = parsed.password
                                    cipher = parsed.cipher
                                    errorText = null
                                }
                                ssRequiresPlugin(text) ->
                                    errorText = "Ссылка ss:// требует плагин (obfs/v2ray) — он не поддерживается"
                                else ->
                                    errorText = "В буфере нет ссылки ss:// / socks5:// / http(s)://"
                            }
                        }
                        .padding(horizontal = 8.dp, vertical = 8.dp),
                    verticalAlignment = Alignment.CenterVertically,
                ) {
                    Icon(VojoIcons.Clipboard, contentDescription = null, tint = Vojo.fleetSoft, modifier = Modifier.size(15.dp))
                    Spacer(Modifier.width(6.dp))
                    Text("вставить", color = Vojo.fleetSoft, fontSize = 13.sp)
                }
            }
            Spacer(Modifier.height(18.dp))

            VojoTextField(name, { name = it }, "Имя", "Мой сервер")
            Spacer(Modifier.height(14.dp))

            VojoDropdown(
                label = "Протокол",
                options = ProxyType.entries,
                selected = type,
                optionLabel = { it.label },
                onSelect = { type = it },
            )
            Spacer(Modifier.height(14.dp))

            Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) {
                VojoTextField(host, { host = it }, "Адрес", "example.com", Modifier.weight(2f), mono = true)
                VojoTextField(port, { port = it.filter(Char::isDigit).take(5) }, "Порт", "8388", Modifier.weight(1f), keyboardType = androidx.compose.ui.text.input.KeyboardType.Number, mono = true)
            }
            Spacer(Modifier.height(14.dp))

            when (type) {
                ProxyType.SHADOWSOCKS -> {
                    VojoDropdown(
                        label = "Шифр",
                        options = SsCipher.entries,
                        selected = cipher,
                        optionLabel = { it.id },
                        onSelect = { cipher = it },
                    )
                    Spacer(Modifier.height(14.dp))
                    VojoTextField(password, { password = it }, "Пароль", "пароль Shadowsocks", isPassword = true, mono = true)
                }
                else -> {
                    VojoTextField(username, { username = it }, "Логин (необязательно)", "user", mono = true)
                    Spacer(Modifier.height(14.dp))
                    VojoTextField(password, { password = it }, "Пароль (необязательно)", "••••", isPassword = true, mono = true)
                }
            }

            if (errorText != null) {
                Spacer(Modifier.height(12.dp))
                Text(errorText!!, color = Vojo.danger, fontSize = 13.sp)
            }

            Spacer(Modifier.height(22.dp))
            Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) {
                Box(
                    Modifier.weight(1f).height(50.dp).clip(RoundedCornerShape(12.dp))
                        .border(1.dp, Vojo.hairline, RoundedCornerShape(12.dp))
                        .clickable { onDismiss() },
                    contentAlignment = Alignment.Center,
                ) { Text("Отмена", color = Vojo.muted, fontSize = 15.sp) }
                Box(
                    Modifier.weight(1f).height(50.dp).clip(RoundedCornerShape(12.dp))
                        .background(Vojo.fleet)
                        .clickable {
                            val cfg = ProxyConfig(
                                id = initial?.id ?: java.util.UUID.randomUUID().toString(),
                                name = name.trim(),
                                type = type,
                                host = host.trim(),
                                port = port.toIntOrNull() ?: 0,
                                username = username.trim(),
                                password = password,
                                cipher = cipher,
                            )
                            val err = cfg.validationError()
                            if (err != null) errorText = err else onSave(cfg)
                        },
                    contentAlignment = Alignment.Center,
                ) { Text("Сохранить", color = Color(0xFF0C0C0E), fontWeight = FontWeight.SemiBold, fontSize = 15.sp) }
            }
        }
    }
}
