package fn.compose.ui

import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import fn.compose.theme.FnColors
import fn.compose.theme.FnRadius
import fn.compose.theme.FnShadows
import fn.compose.theme.FnSpacing
import fn.compose.theme.FnTypography

// ---------------------------------------------------------------------------
// FnText
// ---------------------------------------------------------------------------

/** Body text size scale. Maps directly to [FnTypography] sp values. */
enum class FnTextSize { Xs, Sm, Md, Lg, Xl }

/**
 * Stateless body text following the registry typography scale.
 *
 * @param text    String to display.
 * @param size    One of [FnTextSize] — maps to FnTypography.xs … xl.
 * @param color   Text color. Defaults to [MaterialTheme.colorScheme.onSurface]
 *                when [Color.Unspecified] is passed.
 */
@Composable
fun FnText(
    text: String,
    modifier: Modifier = Modifier,
    size: FnTextSize = FnTextSize.Md,
    color: Color = Color.Unspecified,
) {
    val fontSize = when (size) {
        FnTextSize.Xs -> FnTypography.xs
        FnTextSize.Sm -> FnTypography.sm
        FnTextSize.Md -> FnTypography.md
        FnTextSize.Lg -> FnTypography.lg
        FnTextSize.Xl -> FnTypography.xl
    }
    val resolvedColor = if (color == Color.Unspecified) {
        MaterialTheme.colorScheme.onSurface
    } else {
        color
    }
    Text(
        text = text,
        modifier = modifier,
        color = resolvedColor,
        fontSize = fontSize,
        fontWeight = FnTypography.normal,
    )
}

// ---------------------------------------------------------------------------
// FnTitle
// ---------------------------------------------------------------------------

/**
 * Heading text from order 1 (largest) to order 6 (smallest).
 *
 * Orders 1–2 use [FontWeight.Bold]; orders 3–6 use [FontWeight.SemiBold].
 * Font size maps to [FnTypography.h1] … [FnTypography.h6].
 */
@Composable
fun FnTitle(
    text: String,
    modifier: Modifier = Modifier,
    order: Int = 1,
) {
    val clamped = order.coerceIn(1, 6)
    val fontSize = when (clamped) {
        1 -> FnTypography.h1
        2 -> FnTypography.h2
        3 -> FnTypography.h3
        4 -> FnTypography.h4
        5 -> FnTypography.h5
        else -> FnTypography.h6
    }
    val fontWeight = if (clamped <= 2) FnTypography.bold else FnTypography.semibold
    Text(
        text = text,
        modifier = modifier,
        color = MaterialTheme.colorScheme.onSurface,
        fontSize = fontSize,
        fontWeight = fontWeight,
    )
}

// ---------------------------------------------------------------------------
// FnCard
// ---------------------------------------------------------------------------

/** Visual style variant for [FnCard]. */
enum class FnCardVariant { Default, Borderless, Ghost }

/**
 * Container card with three visual variants.
 *
 * - **Default**: surface background, 1 dp border ([FnColors.border]),
 *   [FnRadius.md] corners, [FnShadows.sm] elevation, [FnSpacing.md] padding.
 * - **Borderless**: surface background, no border, no shadow,
 *   [FnSpacing.md] padding.
 * - **Ghost**: transparent background, no border, no shadow,
 *   [FnSpacing.md] padding.
 */
@Composable
fun FnCard(
    modifier: Modifier = Modifier,
    variant: FnCardVariant = FnCardVariant.Default,
    content: @Composable ColumnScope.() -> Unit,
) {
    val shape = RoundedCornerShape(FnRadius.md)

    when (variant) {
        FnCardVariant.Default -> {
            Surface(
                modifier = modifier,
                shape = shape,
                color = MaterialTheme.colorScheme.surface,
                shadowElevation = FnShadows.sm,
                tonalElevation = 0.dp,
            ) {
                Column(
                    modifier = Modifier
                        .border(width = 1.dp, color = FnColors.border, shape = shape)
                        .padding(FnSpacing.md),
                    content = content,
                )
            }
        }

        FnCardVariant.Borderless -> {
            Surface(
                modifier = modifier,
                shape = shape,
                color = MaterialTheme.colorScheme.surface,
                shadowElevation = 0.dp,
                tonalElevation = 0.dp,
            ) {
                Column(
                    modifier = Modifier.padding(FnSpacing.md),
                    content = content,
                )
            }
        }

        FnCardVariant.Ghost -> {
            Surface(
                modifier = modifier,
                shape = shape,
                color = Color.Transparent,
                shadowElevation = 0.dp,
                tonalElevation = 0.dp,
            ) {
                Column(
                    modifier = Modifier.padding(FnSpacing.md),
                    content = content,
                )
            }
        }
    }
}

// ---------------------------------------------------------------------------
// FnBadge
// ---------------------------------------------------------------------------

/** Semantic color options for [FnBadge]. */
enum class FnBadgeColor { Brand, Gray, Green, Red, Yellow, Blue }

/**
 * Pill-shaped label using a semitransparent background derived from the base
 * color (alpha 0.18) and the base color as text color.
 *
 * Color mapping:
 * - Brand  → [FnColors.primary]
 * - Gray   → [FnColors.textMuted]
 * - Green  → [FnColors.success]
 * - Red    → [FnColors.error]
 * - Yellow → [FnColors.warning]
 * - Blue   → [FnColors.info]
 */
@Composable
fun FnBadge(
    text: String,
    modifier: Modifier = Modifier,
    color: FnBadgeColor = FnBadgeColor.Brand,
) {
    val baseColor = when (color) {
        FnBadgeColor.Brand  -> FnColors.primary
        FnBadgeColor.Gray   -> FnColors.textMuted
        FnBadgeColor.Green  -> FnColors.success
        FnBadgeColor.Red    -> FnColors.error
        FnBadgeColor.Yellow -> FnColors.warning
        FnBadgeColor.Blue   -> FnColors.info
    }
    val bgColor = baseColor.copy(alpha = 0.18f)
    val shape = RoundedCornerShape(FnRadius.full)

    Box(
        modifier = modifier
            .background(color = bgColor, shape = shape)
            .padding(horizontal = 8.dp, vertical = 3.dp),
        contentAlignment = Alignment.Center,
    ) {
        Text(
            text = text,
            color = baseColor,
            fontSize = FnTypography.xs,
            fontWeight = FnTypography.medium,
        )
    }
}

// ---------------------------------------------------------------------------
// FnAvatar
// ---------------------------------------------------------------------------

/** Size variants for [FnAvatar]. */
enum class FnAvatarSize { Sm, Md, Lg }

/**
 * Circular avatar displaying up to two initials on a [FnColors.primary]
 * background.
 *
 * Size mapping:
 * - Sm → 28 dp
 * - Md → 40 dp
 * - Lg → 56 dp
 *
 * Text size scales proportionally (xs / sm / md) so the initials always fit.
 */
@Composable
fun FnAvatar(
    initials: String,
    modifier: Modifier = Modifier,
    size: FnAvatarSize = FnAvatarSize.Md,
) {
    val sizeDp = when (size) {
        FnAvatarSize.Sm -> 28.dp
        FnAvatarSize.Md -> 40.dp
        FnAvatarSize.Lg -> 56.dp
    }
    val fontSize = when (size) {
        FnAvatarSize.Sm -> FnTypography.xs
        FnAvatarSize.Md -> FnTypography.sm
        FnAvatarSize.Lg -> FnTypography.md
    }
    // Truncate to at most two characters so the avatar never overflows.
    val label = initials.take(2).uppercase()

    Box(
        modifier = modifier
            .size(sizeDp)
            .background(color = FnColors.primary, shape = CircleShape),
        contentAlignment = Alignment.Center,
    ) {
        Text(
            text = label,
            color = FnColors.white,
            fontSize = fontSize,
            fontWeight = FnTypography.semibold,
            textAlign = TextAlign.Center,
        )
    }
}
