Pith - kerf
package com.vgmlr.kerf

import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.outlined.Public
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.draw.drawBehind
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.PlatformTextStyle
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.LineHeightStyle
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.platform.LocalUriHandler
import androidx.compose.foundation.BorderStroke

internal val CBg = Color(0xFF0E0F11)
internal val CCard = Color(0xFF272A30).copy(alpha = 0.8f)
internal val CText = Color(0xFFE8EAED)
internal val CMuted = Color(0xFF868D97)
internal val CChip = Color(0xFF3A4048)
internal val CHead = Color(0xFF33373E).copy(alpha = 0.8f)
internal val EDGE = BorderStroke(1.dp, CMuted.copy(alpha = 0.30f))

internal val ROW_H = 46.dp
private val HEAD_H = 46.dp
internal val FS = 15.sp

private val HEAD_INK = CText.copy(alpha = 0.75f)
private val HEAD_ICON = 16.dp
private val HEAD_ICON_GAP = 10.dp
private val HEAD_TEXT_DY = 1.dp
private val HEAD_FS = 12.sp

private val FINE_INK = CMuted.copy(alpha = 0.6f)
private val FINE_FS = 11.sp
private val FINE_GAP = 8.dp

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SettingsScreen(vm: KerfViewModel, onBack: () -> Unit) {
    val sanitizeEnabled by vm.sanitizeEnabled.collectAsState()
    val extractUrlEnabled by vm.extractUrlEnabled.collectAsState()

    Scaffold(
        topBar = {
            TopAppBar(
                title = { },
                colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent),
                actions = {
                    Row(
                        modifier = Modifier
                            .fillMaxWidth()
                            .height(TOP_BAR_H)
                            .padding(start = 12.dp, end = 8.dp),
                        verticalAlignment = Alignment.CenterVertically
                    ) {
                        KerfButton(Icons.AutoMirrored.Filled.ArrowBack, "Back", onClick = onBack)
                        Spacer(Modifier.width(BAR_GAP))
                        KerfBlankButton(
                            Modifier.weight(1f),
                            label = "Settings",
                            labelAlignment = Alignment.CenterStart
                        )
                    }
                }
            )
        },
        containerColor = CBg
    ) { p ->
        Column(
            Modifier
                .padding(p)
                .fillMaxSize()
                .background(CBg)
                .padding(horizontal = BAR_EDGE)
                .verticalScroll(rememberScrollState())
        ) {
            Spacer(Modifier.height(4.dp))

            KfSection(
                "Global",
                Icons.Outlined.Public,
                footer = {
                    KfFinePrint(
                        "ClearURLs Rules: ",
                        "github.com/ClearURLs/Rules",
                        "https://github.com/ClearURLs/Rules"
                    )
                }
            ) {
                KfRow("Sanitize URL") {
                    KfRadio(
                        value = if (sanitizeEnabled) "True" else "False",
                        options = listOf("True", "False")
                    ) { vm.setSanitize(it == "True") }
                }
                KfDivider()
                KfRow("Extract URL") {
                    KfRadio(
                        value = if (extractUrlEnabled) "True" else "False",
                        options = listOf("True", "False")
                    ) { vm.setExtractUrl(it == "True") }
                }
            }
            Spacer(Modifier.height(24.dp))
        }
    }
}

@Composable
internal fun KfSection(
    title: String,
    icon: ImageVector? = null,
    footer: (@Composable () -> Unit)? = null,
    content: @Composable ColumnScope.() -> Unit
) {
    val shape = RoundedCornerShape(ROUND_END)
    Column(
        Modifier
            .fillMaxWidth()
            .clip(shape)
            .border(EDGE, shape)
    ) {
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .heightIn(min = HEAD_H)
                .clip(RoundedCornerShape(topStart = ROUND_END, topEnd = ROUND_END))
                .background(CHead)
                .padding(horizontal = 16.dp, vertical = 8.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            if (icon != null) {
                Icon(
                    imageVector = icon,
                    contentDescription = null,
                    tint = HEAD_INK,
                    modifier = Modifier.size(HEAD_ICON)
                )
                Spacer(Modifier.width(HEAD_ICON_GAP))
            }
            Text(
                text = title,
                color = HEAD_INK,
                fontWeight = FontWeight.Medium,
                letterSpacing = 1.4.sp,
                style = TextStyle(
                    fontSize = HEAD_FS,
                    lineHeight = HEAD_FS,
                    platformStyle = PlatformTextStyle(includeFontPadding = false),
                    lineHeightStyle = LineHeightStyle(
                        alignment = LineHeightStyle.Alignment.Center,
                        trim = LineHeightStyle.Trim.Both
                    )
                ),
                modifier = Modifier.offset(y = HEAD_TEXT_DY)
            )
        }
        KfDivider()
        KfCard(
            shape = RoundedCornerShape(bottomStart = ROUND_END, bottomEnd = ROUND_END),
            borderColor = Color.Transparent,
            content = content
        )
    }
    if (footer != null) {
        Spacer(Modifier.height(FINE_GAP))
        footer()
    }
    Spacer(Modifier.height(24.dp))
}

@Composable
private fun KfFinePrint(label: String, link: String, url: String) {
    val uriHandler = LocalUriHandler.current
    Row(
        modifier = Modifier.fillMaxWidth(),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.Center
    ) {
        Text(label, color = FINE_INK, fontSize = FINE_FS)
        Text(
            link,
            color = FINE_INK,
            fontSize = FINE_FS,
            modifier = Modifier.clickable { uriHandler.openUri(url) }
        )
    }
}

@Composable
internal fun KfCard(
    shape: Shape = RoundedCornerShape(ROUND_END),
    bg: Color = CCard,
    borderColor: Color = CHead,
    content: @Composable ColumnScope.() -> Unit
) {
    val radiusPx = with(LocalDensity.current) { ROUND_END.toPx() }
    Column(
        Modifier
            .fillMaxWidth()
            .clip(shape)
            .background(bg)
            .drawBehind {
                val w = 1.dp.toPx()
                drawRoundRect(
                    color = borderColor,
                    topLeft = Offset(w / 2f, -radiusPx),
                    size = Size(size.width - w, size.height + radiusPx - w / 2f),
                    cornerRadius = CornerRadius(radiusPx),
                    style = Stroke(w)
                )
            },
        content = content
    )
}

@Composable
internal fun KfRow(label: String, content: @Composable RowScope.() -> Unit) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .heightIn(min = ROW_H)
            .padding(horizontal = 16.dp, vertical = 8.dp),
        verticalAlignment = Alignment.CenterVertically
    ) {
        Text(
            text = label,
            color = CText.copy(alpha = 0.95f),
            fontSize = FS,
            maxLines = 1,
            modifier = Modifier.widthIn(min = 92.dp)
        )
        Spacer(Modifier.width(12.dp))
        Row(
            modifier = Modifier.weight(1f),
            horizontalArrangement = Arrangement.End,
            verticalAlignment = Alignment.CenterVertically,
            content = content
        )
    }
}

@Composable
internal fun KfDivider() {
    HorizontalDivider(thickness = 1.dp, color = CBg)
}

@Composable
internal fun KfValue(
    text: String,
    modifier: Modifier = Modifier,
    mono: Boolean = false,
    color: Color = CText,
    maxLines: Int = 1
) {
    Text(
        text = text,
        color = color,
        fontSize = FS,
        fontFamily = if (mono) FontFamily.Monospace else FontFamily.Default,
        textAlign = TextAlign.End,
        maxLines = maxLines,
        overflow = TextOverflow.Ellipsis,
        modifier = modifier
    )
}

@Composable
private fun KfChip(
    label: String,
    selected: Boolean,
    enabled: Boolean = true,
    shape: Shape = RoundedCornerShape(6.dp),
    border: Boolean = true,
    leftLine: Color? = null,
    rightLine: Color? = null,
    onClick: () -> Unit
) {
    val filled = selected && enabled

    Box(
        modifier = Modifier
            .height(28.dp)
            .clip(shape)
            .background(if (filled) CChip else Color.Transparent)
            .then(
                if (leftLine != null || rightLine != null) Modifier.drawBehind {
                    val w = 1.dp.toPx()
                    leftLine?.let { drawLine(it, Offset(w / 2f, 0f), Offset(w / 2f, size.height), w) }
                    rightLine?.let {
                        val x = size.width - w / 2f
                        drawLine(it, Offset(x, 0f), Offset(x, size.height), w)
                    }
                } else Modifier
            )
            .then(
                if (border) Modifier.border(
                    width = 1.dp,
                    color = if (filled) CChip else CMuted.copy(alpha = 0.30f),
                    shape = shape
                ) else Modifier
            )
            .clickable(
                enabled = enabled,
                interactionSource = remember { MutableInteractionSource() },
                indication = null,
                onClick = onClick
            )
            .padding(horizontal = 16.dp),
        contentAlignment = Alignment.Center
    ) {
        Text(
            text = label,
            color = when {
                !enabled -> CMuted.copy(alpha = 0.4f)
                selected -> CText
                else -> CMuted
            },
            fontSize = 13.sp,
            fontFamily = FontFamily.Monospace,
            maxLines = 1
        )
    }
}

@Composable
internal fun KfRadio(
    value: String,
    options: List<String>,
    disabledOptions: List<String> = emptyList(),
    onSelect: (String) -> Unit
) {
    val shape = RoundedCornerShape(6.dp)
    val outline = CMuted.copy(alpha = 0.30f)
    
    Row(
        modifier = Modifier
            .height(28.dp)
            .clip(shape)
            .border(1.dp, outline, shape),
        verticalAlignment = Alignment.CenterVertically
    ) {
        options.forEachIndexed { i, opt ->
            KfChip(
                label = opt,
                selected = opt == value,
                enabled = opt !in disabledOptions,
                shape = RectangleShape,
                border = false,
                leftLine = if (i > 0 && options[i - 1] != value) outline else null,
                rightLine = if (i < options.lastIndex && opt == value) outline else null,
                onClick = { onSelect(opt) }
            )
        }
    }
}