package dev.ulfrx.recipe.ui.components.controls

import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.RepeatMode
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicText
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.composables.icons.lucide.LoaderCircle
import com.composables.icons.lucide.Lucide
import com.composeunstyled.UnstyledButton
import com.composeunstyled.UnstyledIcon
import com.composeunstyled.UnstyledProgressIndicator
import dev.ulfrx.recipe.ui.theme.RecipeTheme

@Composable
fun RecipePrimaryButton(
    text: String,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    loading: Boolean = false,
) {
    RecipeButtonFrame(
        onClick = onClick,
        enabled = enabled && !loading,
        backgroundColor = if (enabled) RecipeTheme.colors.accent else RecipeTheme.colors.separator,
        contentColor = RecipeTheme.colors.surface,
        modifier = modifier,
    ) {
        if (loading) {
            RecipeLoadingIndicator(
                size = 16.dp,
                color = RecipeTheme.colors.surface,
            )
        } else {
            BasicText(
                text = text,
                style = RecipeTheme.typography.label.copy(color = RecipeTheme.colors.surface),
            )
        }
    }
}

@Composable
fun RecipeOutlinedButton(
    text: String,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
) {
    val contentColor = if (enabled) RecipeTheme.colors.content else RecipeTheme.colors.contentMuted
    RecipeButtonFrame(
        onClick = onClick,
        enabled = enabled,
        backgroundColor = Color.Transparent,
        contentColor = contentColor,
        borderColor = RecipeTheme.colors.separator,
        modifier = modifier,
    ) {
        BasicText(
            text = text,
            style = RecipeTheme.typography.label.copy(color = contentColor),
        )
    }
}

@Composable
fun RecipeLoadingIndicator(
    modifier: Modifier = Modifier,
    size: Dp = 24.dp,
    color: Color = RecipeTheme.colors.accent,
) {
    val transition = rememberInfiniteTransition(label = "RecipeLoadingIndicator")
    val rotation =
        transition.animateFloat(
            initialValue = 0f,
            targetValue = 360f,
            animationSpec =
                infiniteRepeatable(
                    animation = tween(durationMillis = 900, easing = LinearEasing),
                    repeatMode = RepeatMode.Restart,
                ),
            label = "loading icon rotation",
        )

    UnstyledProgressIndicator(
        modifier = modifier.size(size),
        contentColor = color,
    ) {
        UnstyledIcon(
            imageVector = Lucide.LoaderCircle,
            contentDescription = null,
            tint = color,
            modifier =
                Modifier
                    .size(size)
                    .rotate(rotation.value),
        )
    }
}

@Composable
private fun RecipeButtonFrame(
    onClick: () -> Unit,
    enabled: Boolean,
    backgroundColor: Color,
    contentColor: Color,
    modifier: Modifier = Modifier,
    borderColor: Color = Color.Unspecified,
    content: @Composable RowScope.() -> Unit,
) {
    UnstyledButton(
        onClick = onClick,
        enabled = enabled,
        shape = RoundedCornerShape(24.dp),
        backgroundColor = backgroundColor,
        contentColor = contentColor,
        borderColor = borderColor,
        borderWidth = if (borderColor == Color.Unspecified) 0.dp else 1.dp,
        contentPadding = PaddingValues(horizontal = 18.dp, vertical = 12.dp),
        modifier = modifier.defaultMinSize(minHeight = 48.dp),
        content = content,
    )
}
