package com.anypreta.bountyboard.ui.components

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.interaction.collectIsPressedAsState
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.OutlinedTextFieldDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
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.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.anypreta.bountyboard.ui.theme.BB
import com.anypreta.bountyboard.ui.theme.BBPalette
import com.anypreta.bountyboard.ui.theme.SplineMono
import com.anypreta.bountyboard.ui.theme.hardShadow
import com.anypreta.bountyboard.ui.util.formatBounty
import com.anypreta.bountyboard.ui.util.statusLabel

// ---------------------------------------------------------------------------
// Buttons
// ---------------------------------------------------------------------------

enum class BBButtonStyle { Primary, Default, Danger, Ghost }

@Composable
fun BBButton(
    text: String,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    style: BBButtonStyle = BBButtonStyle.Default,
    enabled: Boolean = true,
    loading: Boolean = false,
    leadingIcon: ImageVector? = null,
    small: Boolean = false,
) {
    val p = BB.colors
    val interaction = remember { MutableInteractionSource() }
    val pressed by interaction.collectIsPressedAsState()
    val shape = RoundedCornerShape(p.radius.dp)
    val hasShadow = style != BBButtonStyle.Ghost
    val shadowOffset = if (small) 1.dp else 2.dp

    val bg: Color
    val content: Color
    val borderColor: Color
    when (style) {
        BBButtonStyle.Primary -> {
            bg = p.accent; content = p.onAccent; borderColor = blend(p.accent, Color.Black, 0.35f)
        }
        BBButtonStyle.Danger -> {
            bg = p.err; content = Color.White; borderColor = blend(p.err, Color.Black, 0.3f)
        }
        BBButtonStyle.Ghost -> {
            bg = Color.Transparent; content = p.text; borderColor = p.border
        }
        BBButtonStyle.Default -> {
            bg = p.surface2; content = p.text; borderColor = p.border
        }
    }
    val alpha = if (enabled && !loading) 1f else 0.45f
    val pressShift = if (pressed && hasShadow) shadowOffset else 0.dp

    Box(
        modifier = modifier
            .then(if (hasShadow && !pressed) Modifier.hardShadow(p, shadowOffset, p.radius.dp) else Modifier)
            .offset(pressShift, pressShift)
            .clip(shape)
            .background(bg.copy(alpha = if (style == BBButtonStyle.Ghost) 1f else alpha))
            .border(1.dp, borderColor.copy(alpha = alpha), shape)
            .clickableNoRipple(enabled = enabled && !loading, interaction = interaction, onClick = onClick)
            .padding(
                horizontal = if (small) 12.dp else 18.dp,
                vertical = if (small) 6.dp else 10.dp,
            ),
        contentAlignment = Alignment.Center,
    ) {
        Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) {
            if (loading) {
                CircularProgressIndicator(modifier = Modifier.size(16.dp), strokeWidth = 2.dp, color = content)
            } else {
                if (leadingIcon != null) {
                    Icon(leadingIcon, contentDescription = null, tint = content.copy(alpha = alpha), modifier = Modifier.size(16.dp))
                }
                Text(
                    text.uppercase(),
                    style = if (small) MaterialTheme.typography.labelMedium else MaterialTheme.typography.labelLarge,
                    color = content.copy(alpha = alpha),
                    fontWeight = FontWeight.Bold,
                    maxLines = 1,
                )
            }
        }
    }
}

// ---------------------------------------------------------------------------
// Cards
// ---------------------------------------------------------------------------

@Composable
fun BBCard(
    modifier: Modifier = Modifier,
    onClick: (() -> Unit)? = null,
    padding: PaddingValues = PaddingValues(16.dp),
    topStrip: Boolean = false,
    content: @Composable () -> Unit,
) {
    val p = BB.colors
    val shape = RoundedCornerShape(p.radius.dp)
    val interaction = remember { MutableInteractionSource() }
    Box(
        modifier = modifier
            .hardShadow(p, 3.dp, p.radius.dp)
            .clip(shape)
            .background(p.surface)
            .border(1.dp, p.border, shape)
            .then(if (onClick != null) Modifier.clickableNoRipple(true, interaction, onClick) else Modifier),
    ) {
        Column {
            if (topStrip) {
                Box(
                    Modifier
                        .height(6.dp)
                        .background(p.accent)
                        .border(0.dp, Color.Transparent),
                )
            }
            Box(Modifier.padding(padding)) { content() }
        }
    }
}

// ---------------------------------------------------------------------------
// Badges & chips
// ---------------------------------------------------------------------------

@Composable
fun BBBadge(
    text: String,
    modifier: Modifier = Modifier,
    color: Color = BB.colors.muted,
    filled: Boolean = false,
) {
    val p = BB.colors
    val shape = RoundedCornerShape(p.radius.dp)
    Box(
        modifier = modifier
            .clip(shape)
            .background(if (filled) color else Color.Transparent)
            .border(1.dp, color.copy(alpha = if (filled) 1f else 0.7f), shape)
            .padding(horizontal = 8.dp, vertical = 2.dp),
    ) {
        Text(
            text.uppercase(),
            style = MaterialTheme.typography.labelMedium,
            color = if (filled) p.surface else color,
        )
    }
}

@Composable
fun StatusBadge(status: String, modifier: Modifier = Modifier) {
    BBBadge(statusLabel(status), modifier = modifier, color = statusColor(status, BB.colors))
}

@Composable
fun BountyChip(value: Double, modifier: Modifier = Modifier, large: Boolean = false) {
    val p = BB.colors
    val shape = RoundedCornerShape(p.radius.dp)
    Box(
        modifier = modifier
            .clip(shape)
            .background(p.surface)
            .border(1.5.dp, p.accent, shape)
            .padding(horizontal = if (large) 12.dp else 9.dp, vertical = if (large) 5.dp else 3.dp),
    ) {
        Text(
            "◈ ${formatBounty(value)}",
            fontFamily = SplineMono,
            fontWeight = FontWeight.Bold,
            color = p.accent,
            style = if (large) MaterialTheme.typography.titleMedium else MaterialTheme.typography.bodyMedium,
        )
    }
}

// ---------------------------------------------------------------------------
// Text fields
// ---------------------------------------------------------------------------

@Composable
fun BBTextField(
    value: String,
    onValueChange: (String) -> Unit,
    label: String,
    modifier: Modifier = Modifier,
    placeholder: String? = null,
    singleLine: Boolean = true,
    keyboardType: KeyboardType = KeyboardType.Text,
    isPassword: Boolean = false,
    enabled: Boolean = true,
    leadingIcon: ImageVector? = null,
    minLines: Int = 1,
    supportingText: String? = null,
    isError: Boolean = false,
) {
    val p = BB.colors
    Column(modifier) {
        Text(
            label,
            style = MaterialTheme.typography.titleSmall,
            color = p.text,
            modifier = Modifier.padding(bottom = 6.dp),
        )
        OutlinedTextField(
            value = value,
            onValueChange = onValueChange,
            modifier = Modifier.fillMaxWidth(),
            placeholder = placeholder?.let { { Text(it, color = p.muted, style = MaterialTheme.typography.bodyMedium) } },
            singleLine = singleLine,
            minLines = minLines,
            enabled = enabled,
            isError = isError,
            shape = RoundedCornerShape(p.radius.dp),
            leadingIcon = leadingIcon?.let { { Icon(it, null, tint = p.muted, modifier = Modifier.size(18.dp)) } },
            visualTransformation = if (isPassword) PasswordVisualTransformation() else VisualTransformation.None,
            keyboardOptions = androidx.compose.foundation.text.KeyboardOptions(
                keyboardType = if (isPassword) KeyboardType.Password else keyboardType,
            ),
            supportingText = supportingText?.let { { Text(it, style = MaterialTheme.typography.bodySmall, color = if (isError) p.err else p.muted) } },
            textStyle = MaterialTheme.typography.bodyLarge,
            colors = OutlinedTextFieldDefaults.colors(
                focusedBorderColor = p.accent,
                unfocusedBorderColor = p.border,
                errorBorderColor = p.err,
                focusedContainerColor = p.bg,
                unfocusedContainerColor = p.bg,
                disabledContainerColor = p.surface2,
                cursorColor = p.accent,
                focusedTextColor = p.text,
                unfocusedTextColor = p.text,
            ),
        )
    }
}

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

fun statusColor(status: String, p: BBPalette): Color = when (status) {
    "approved" -> p.ok
    "changes_requested" -> p.warn
    "in_review" -> p.accent
    "archived" -> p.err
    else -> p.muted
}

fun blend(a: Color, b: Color, t: Float): Color = Color(
    red = a.red * (1 - t) + b.red * t,
    green = a.green * (1 - t) + b.green * t,
    blue = a.blue * (1 - t) + b.blue * t,
    alpha = a.alpha,
)

private fun Modifier.clickableNoRipple(
    enabled: Boolean,
    interaction: MutableInteractionSource,
    onClick: () -> Unit,
): Modifier = this.clickable(
    interactionSource = interaction,
    indication = null,
    enabled = enabled,
    onClick = onClick,
)
