package wang.yaojia.webterm.designsystem

import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import wang.yaojia.webterm.wire.ClaudeStatus

/**
 * # Primitives — reusable Compose building blocks (mirrors iOS `Primitives.swift`).
 *
 * `StatusBadge`, `TelemetryChip`, `WebTermCard`. Each pulls ALL constants from the
 * design tokens — no inline magic. Untrusted server strings render as INERT
 * [Text] (no Markdown / linkify / AnnotatedString autolink), per plan §8.
 */

/**
 * The visual states a status indicator can show — a superset of the wire
 * [ClaudeStatus] plus two App-layer emphasis states (mirrors iOS `DisplayStatus`):
 * `PendingApproval` ("needs me", outranks status) and `Exited` (read-only).
 */
public enum class DisplayStatus {
    Working, Waiting, Idle, Stuck, Unknown, PendingApproval, Exited;

    public companion object {
        /** Bridge from the wire enum (no pending/exited emphasis — callers add). */
        public fun from(status: ClaudeStatus): DisplayStatus = when (status) {
            ClaudeStatus.WORKING -> Working
            ClaudeStatus.WAITING -> Waiting
            ClaudeStatus.IDLE -> Idle
            ClaudeStatus.STUCK -> Stuck
            ClaudeStatus.UNKNOWN -> Unknown
        }
    }
}

/**
 * Resolved visuals for one status: a semantic [color], a DISTINCT [symbol] glyph
 * (so shape alone disambiguates — color-blind safe), and a Chinese [label] (also
 * the accessibility description). Pure + deterministic (mirrors iOS `StatusStyle`).
 */
public data class StatusStyle(
    val color: Color,
    val symbol: String,
    val label: String,
) {
    public companion object {
        public fun of(status: DisplayStatus): StatusStyle = when (status) {
            DisplayStatus.Working -> StatusStyle(WebTermColors.statusWorking, "●", "运行中")
            DisplayStatus.Waiting -> StatusStyle(WebTermColors.statusWaiting, "◔", "等待中")
            DisplayStatus.Idle -> StatusStyle(WebTermColors.statusIdle, "○", "空闲")
            DisplayStatus.Stuck -> StatusStyle(WebTermColors.statusStuck, "▲", "卡住")
            DisplayStatus.Unknown -> StatusStyle(WebTermColors.statusUnknown, "?", "未知")
            DisplayStatus.PendingApproval -> StatusStyle(WebTermColors.statusWaiting, "!", "等待审批")
            DisplayStatus.Exited -> StatusStyle(WebTermColors.statusIdle, "⚑", "已退出")
        }

        public fun of(status: ClaudeStatus): StatusStyle = of(DisplayStatus.from(status))
    }
}

/**
 * Color + distinct glyph (+ optional Chinese label) for one status. Status is
 * conveyed by shape, color AND the semantics label — never color alone.
 */
@Composable
public fun StatusBadge(
    status: DisplayStatus,
    modifier: Modifier = Modifier,
    showsLabel: Boolean = false,
) {
    val style = StatusStyle.of(status)
    Row(
        modifier = modifier.semantics { contentDescription = style.label },
        horizontalArrangement = Arrangement.spacedBy(Spacing.xs4),
        verticalAlignment = Alignment.CenterVertically,
    ) {
        Text(text = style.symbol, color = style.color, style = MaterialTheme.typography.labelMedium)
        if (showsLabel) {
            Text(
                text = style.label,
                color = MaterialTheme.colorScheme.onSurfaceVariant,
                style = MaterialTheme.typography.labelSmall,
            )
        }
    }
}

/**
 * One pill of monospaced-tabular telemetry (context %, $cost, model, PR…). Greys
 * out when [isStale]; switches to the waiting/amber color when [isWarning].
 */
@Composable
public fun TelemetryChip(
    text: String,
    modifier: Modifier = Modifier,
    isStale: Boolean = false,
    isWarning: Boolean = false,
) {
    val fg = if (isWarning) WebTermColors.statusWaiting else MaterialTheme.colorScheme.onSurfaceVariant
    Text(
        text = text,
        style = WebTermType.metaMono,
        color = fg,
        maxLines = 1,
        overflow = TextOverflow.Ellipsis,
        modifier = modifier
            .alpha(if (isStale) Opacity.stale else 1f)
            .background(MaterialTheme.colorScheme.surfaceVariant, RoundedCornerShape(Radius.pill))
            .padding(horizontal = Spacing.sm8, vertical = Spacing.xs2),
    )
}

/**
 * Standard card container: card surface + hairline border + `md12` radius +
 * standard padding. The uniform card spec for rows, grid cells and panels.
 */
@Composable
public fun WebTermCard(
    modifier: Modifier = Modifier,
    padding: androidx.compose.ui.unit.Dp = Spacing.md12,
    content: @Composable () -> Unit,
) {
    androidx.compose.foundation.layout.Box(
        modifier = modifier
            .background(MaterialTheme.colorScheme.surfaceVariant, RoundedCornerShape(Radius.md12))
            .border(Stroke.hairline, MaterialTheme.colorScheme.outline, RoundedCornerShape(Radius.md12))
            .padding(padding),
    ) {
        content()
    }
}

// ── Previews ────────────────────────────────────────────────────────────────

@Preview(name = "StatusBadge")
@Composable
private fun StatusBadgePreview() {
    WebTermTheme {
        Row(horizontalArrangement = Arrangement.spacedBy(Spacing.md12)) {
            DisplayStatus.entries.forEach { StatusBadge(status = it, showsLabel = true) }
        }
    }
}

@Preview(name = "TelemetryChip")
@Composable
private fun TelemetryChipPreview() {
    WebTermTheme {
        Row(horizontalArrangement = Arrangement.spacedBy(Spacing.sm8)) {
            TelemetryChip(text = "ctx 92%", isWarning = true)
            TelemetryChip(text = "$0.1234")
            TelemetryChip(text = "PR #7", isStale = true)
        }
    }
}

@Preview(name = "Card")
@Composable
private fun CardPreview() {
    WebTermTheme {
        WebTermCard {
            Text(text = "web-terminal · 161×50", style = WebTermType.metaMono)
        }
    }
}
