package chat.vojo.proxy.ui

import androidx.compose.foundation.BorderStroke
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.Row
import androidx.compose.foundation.layout.fillMaxHeight
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.pager.PagerState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.boundsInParent
import androidx.compose.ui.layout.layout
import androidx.compose.ui.layout.onGloballyPositioned
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 androidx.compose.ui.util.lerp
import chat.vojo.proxy.ui.theme.Vojo
import kotlin.math.ceil
import kotlin.math.floor
import kotlin.math.roundToInt

/** Darkens a colour for the avatar gradient, mirroring the design's `shade(c, -22)`. */
fun Color.shade(amount: Float = 0.78f): Color = Color(red * amount, green * amount, blue * amount, alpha)

/** Square protocol tile with a 2-letter badge and a soft diagonal gradient. */
@Composable
fun ProtocolBadge(badge: String, color: Color, size: Int = 38) {
    Box(
        modifier = Modifier
            .size(size.dp)
            .clip(RoundedCornerShape((size * 0.32f).dp))
            .background(Brush.linearGradient(listOf(color, color.shade()))),
        contentAlignment = Alignment.Center,
    ) {
        Text(
            badge,
            color = Color(0xFF0C0C0E),
            fontWeight = FontWeight.Bold,
            fontSize = (size * 0.36f).sp,
        )
    }
}

/** Uppercase, letter-spaced section label — the design's one monospace chrome accent. */
@Composable
fun SectionLabel(text: String, modifier: Modifier = Modifier) {
    Text(
        text.uppercase(),
        modifier = modifier,
        color = Vojo.faint,
        fontFamily = Vojo.mono,
        fontSize = 11.sp,
        fontWeight = FontWeight.SemiBold,
        letterSpacing = 1.4.sp,
    )
}

/**
 * The whole top chrome: the four tabs sit on the static backdrop (the row does
 * NOT move with the panes). Tabs are sized to their content and distributed with
 * even gaps — equal-width quarters left the centred labels with ragged spacing.
 * The active tab carries a violet underline that slides AND resizes between the
 * measured tab bounds; both the bounds and the pager position are read in the
 * layout phase so a swipe glides the line without recomposing the row.
 */
@Composable
fun SegmentTabs(
    tabs: List<String>,
    pagerState: PagerState,
    onSelect: (Int) -> Unit,
    modifier: Modifier = Modifier,
) {
    // [left, width] of each tab in px, captured in the layout phase. Updated only
    // on real change so onGloballyPositioned can't drive an endless relayout.
    val bounds = remember(tabs.size) {
        mutableStateListOf<IntArray>().apply { repeat(tabs.size) { add(intArrayOf(0, 0)) } }
    }
    Box(modifier.background(Vojo.bgPanel)) {
        Row(
            Modifier.fillMaxWidth().height(54.dp),
            horizontalArrangement = Arrangement.SpaceEvenly,
            verticalAlignment = Alignment.CenterVertically,
        ) {
            tabs.forEachIndexed { i, label ->
                val active = pagerState.currentPage == i
                Box(
                    Modifier
                        .onGloballyPositioned { c ->
                            val r = c.boundsInParent()
                            val x = r.left.roundToInt()
                            val w = r.width.roundToInt()
                            val cur = bounds[i]
                            if (cur[0] != x || cur[1] != w) bounds[i] = intArrayOf(x, w)
                        }
                        .fillMaxHeight()
                        .clip(RoundedCornerShape(10.dp))
                        .clickable { onSelect(i) }
                        .padding(horizontal = 14.dp),
                    contentAlignment = Alignment.Center,
                ) {
                    Text(
                        label,
                        color = if (active) Vojo.text else Vojo.muted,
                        fontSize = 14.5.sp,
                        fontWeight = if (active) FontWeight.SemiBold else FontWeight.Medium,
                        maxLines = 1,
                        overflow = TextOverflow.Ellipsis,
                    )
                }
            }
        }
        // Underline spanning the active tab, interpolated toward the next tab by
        // the live swipe fraction. The outer node fills the width so the inner bar
        // can be placed at any x; both reads happen in the layout phase.
        Box(
            Modifier
                .align(Alignment.BottomStart)
                .fillMaxWidth()
                .height(2.5.dp),
        ) {
            Box(
                Modifier
                    .layout { measurable, constraints ->
                        val last = tabs.lastIndex.coerceAtLeast(0)
                        val posF = (pagerState.currentPage + pagerState.currentPageOffsetFraction)
                            .coerceIn(0f, last.toFloat())
                        val lo = floor(posF).toInt().coerceIn(0, last)
                        val hi = ceil(posF).toInt().coerceIn(0, last)
                        val t = posF - lo
                        val from = bounds[lo]
                        val to = bounds[hi]
                        val barW = lerp(from[1].toFloat(), to[1].toFloat(), t).roundToInt().coerceAtLeast(0)
                        val left = lerp(from[0].toFloat(), to[0].toFloat(), t).roundToInt()
                        val placeable = measurable.measure(constraints.copy(minWidth = barW, maxWidth = barW))
                        layout(constraints.maxWidth, placeable.height) {
                            placeable.place(left, 0)
                        }
                    }
                    .height(2.5.dp)
                    .clip(RoundedCornerShape(topStart = 2.dp, topEnd = 2.dp))
                    .background(Vojo.fleet),
            )
        }
    }
}

/** A flat Fleet-style card: panel surface, hairline border, rounded. */
@Composable
fun PanelCard(
    modifier: Modifier = Modifier,
    onClick: (() -> Unit)? = null,
    accent: Color? = null,
    background: Color = Vojo.bgPanel,
    content: @Composable () -> Unit,
) {
    val shape = RoundedCornerShape(14.dp)
    var m = modifier
        .clip(shape)
        .background(background)
        .border(BorderStroke(1.dp, accent ?: Vojo.divider), shape)
    if (onClick != null) m = m.clickable { onClick() }
    Box(m) { content() }
}

@Composable
fun OnlineDot(color: Color, size: Int = 8) {
    Box(
        Modifier
            .size(size.dp)
            .clip(CircleShape)
            .background(color)
    )
}
