Pith - kiln
package com.vgmlr.kiln

import androidx.compose.foundation.Image
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.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Create
import androidx.compose.material.icons.filled.KeyboardArrowDown
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.SolidColor
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.painterResource
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.dp
import androidx.compose.ui.unit.sp
import androidx.compose.foundation.BorderStroke

internal val CBg = Color(0xFF0E0F11)
internal val CCard = Color(0xFF272A30).copy(alpha = 0.8f)
internal val CCardNo = Color(0xFF272A30)
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))

private val IMG_MENU_PAD = 10.dp
internal val ROW_H = 46.dp
internal val FS = 15.sp

private val HEAD_H = 46.dp
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

@Composable
internal fun WgSection(
    title: String,
    icon: ImageVector? = null,
    headBg: Color = CHead,
    cardBg: Color = CCard,
    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(headBg)
                .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)
            )
        }
        WgDivider()
        WgCard(
            shape = RoundedCornerShape(bottomStart = ROUND_END, bottomEnd = ROUND_END),
            bg = cardBg,
            content = content
        )
    }
    Spacer(Modifier.height(24.dp))
}

@Composable
internal fun WgSectionLabel(title: String) {
    Text(
        text = title.uppercase(),
        color = CText.copy(alpha = 0.8f),
        fontSize = 11.sp,
        fontWeight = FontWeight.Medium,
        letterSpacing = 1.4.sp,
        modifier = Modifier.padding(start = 4.dp, bottom = 8.dp)
    )
}

@Composable
internal fun WgCard(
    modifier: Modifier = Modifier,
    shape: Shape = RoundedCornerShape(ROUND_END),
    bg: Color = CCard,
    border: Color? = null,
    content: @Composable ColumnScope.() -> Unit
) {
    Column(
        modifier.fillMaxWidth()
            .clip(shape)
            .background(bg)
            .then(
                if (border == null) Modifier else Modifier.drawBehind {
                    val w = 1.dp.toPx()
                    val r = ROUND_END.toPx()
                    drawRoundRect(
                        color = border,
                        topLeft = Offset(w / 2f, -r),
                        size = Size(size.width - w, size.height + r - w / 2f),
                        cornerRadius = CornerRadius(r),
                        style = Stroke(w)
                    )
                }
            ),
        content = content
    )
}

@Composable
internal fun WgRow(
    label: String,
    bg: Color = Color.Transparent,
    edit: Boolean = false,
    content: @Composable RowScope.() -> Unit
) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .heightIn(min = ROW_H)
            .background(bg)
            .padding(horizontal = 16.dp, vertical = 8.dp),
        verticalAlignment = Alignment.CenterVertically
    ) {
        Row(
            modifier = Modifier.weight(1f),
            verticalAlignment = Alignment.CenterVertically
        ) {
            Text(
                text = label,
                color = CText.copy(alpha = 0.95f),
                fontSize = FS,
                maxLines = 1,
                overflow = TextOverflow.Ellipsis,
                modifier = Modifier.weight(1f, fill = false)
            )
            if (edit) {
                Spacer(Modifier.width(6.dp))
                Icon(
                    imageVector = Icons.Filled.Create,
                    contentDescription = null,
                    tint = CText.copy(alpha = 0.6f),
                    modifier = Modifier.size(14.dp)
                )
            }
        }
        Spacer(Modifier.width(12.dp))
        Row(
            modifier = Modifier.weight(1f),
            horizontalArrangement = Arrangement.End,
            verticalAlignment = Alignment.CenterVertically,
            content = content
        )
    }
}

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

@Composable
internal fun WgValue(
    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
internal fun WgTextField(
    value: String,
    placeholder: String = "",
    onValueChange: (String) -> Unit
) {
    BasicTextField(
        value = value,
        onValueChange = onValueChange,
        singleLine = true,
        modifier = Modifier.fillMaxWidth(),
        textStyle = TextStyle(
            color = CText,
            fontSize = FS,
            fontFamily = FontFamily.Monospace,
            textAlign = TextAlign.End
        ),
        cursorBrush = SolidColor(CText),
        decorationBox = { inner ->
            Box(contentAlignment = Alignment.CenterEnd) {
                if (value.isEmpty()) WgValue(placeholder, mono = true, color = CMuted)
                inner()
            }
        }
    )
}

@Composable
internal fun WgDropdown(
    value: String,
    options: List<String>,
    placeholder: String = "",
    disabledOptions: List<String> = emptyList(),
    onSelect: (String) -> Unit
) {
    var expanded by remember { mutableStateOf(false) }

    Box {
        Row(
            modifier = Modifier.clickable(
                interactionSource = remember { MutableInteractionSource() },
                indication = null
            ) { expanded = true },
            verticalAlignment = Alignment.CenterVertically
        ) {
            Text(
                text = value.ifBlank { placeholder },
                color = if (value.isBlank()) CMuted else CText,
                fontSize = FS,
                fontFamily = FontFamily.Monospace,
                maxLines = 1,
                overflow = TextOverflow.Ellipsis,
                modifier = Modifier.weight(1f, fill = false)
            )
            Icon(
                imageVector = Icons.Default.KeyboardArrowDown,
                contentDescription = null,
                tint = CMuted,
                modifier = Modifier.size(18.dp)
            )
        }
        DropdownMenu(
            expanded = expanded,
            onDismissRequest = { expanded = false },
            containerColor = Color(0xFF1F2226),
            shape = RoundedCornerShape(ROUND_END),
            tonalElevation = 0.dp,
            shadowElevation = 0.dp
        ) {
            options.forEach { opt ->
                val disabled = opt in disabledOptions
                DropdownMenuItem(
                    enabled = !disabled,
                    text = {
                        Text(
                            text = opt,
                            color = when {
                                disabled -> CMuted.copy(alpha = 0.4f)
                                opt == value -> CMuted
                                else -> CText
                            },
                            fontSize = FS,
                            fontFamily = FontFamily.Monospace,
                            maxLines = 1,
                            overflow = TextOverflow.Ellipsis
                        )
                    },
                    onClick = { onSelect(opt); expanded = false },
                    contentPadding = PaddingValues(horizontal = 14.dp)
                )
            }
        }
    }
}

@Composable
internal fun WgImageDropdown(
    value: Int,
    options: List<Int>,
    size: Dp = 34.dp,
    onSelect: (Int) -> Unit
) {
    var expanded by remember { mutableStateOf(false) }

    Box {
        Row(
            modifier = Modifier.clickable(
                interactionSource = remember { MutableInteractionSource() },
                indication = null
            ) { expanded = true },
            verticalAlignment = Alignment.CenterVertically
        ) {
            Image(painterResource(value), null, Modifier.size(size))
            Icon(
                imageVector = Icons.Default.KeyboardArrowDown,
                contentDescription = null,
                tint = CMuted,
                modifier = Modifier.size(18.dp)
            )
        }
        DropdownMenu(
            expanded = expanded,
            onDismissRequest = { expanded = false },
            containerColor = Color(0xFF1F2226),
            shape = RoundedCornerShape(ROUND_END),
            tonalElevation = 0.dp,
            shadowElevation = 0.dp
        ) {
            options.forEachIndexed { i, res ->
                DropdownMenuItem(
                    modifier = Modifier.width(size + IMG_MENU_PAD * 2),
                    text = {
                        Box(Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
                            Image(
                                painterResource(res),
                                null,
                                Modifier.size(size),
                                alpha = if (res == value) 0.45f else 1f
                            )
                        }
                    },
                    onClick = { onSelect(i); expanded = false },
                    contentPadding = PaddingValues(0.dp)
                )
            }
        }
    }
}

@Composable
internal fun WgChip(
    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 WgRadio(
    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 ->
            WgChip(
                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) }
            )
        }
    }
}