package fn.compose.ui

import androidx.compose.foundation.Canvas
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.HorizontalDivider
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.geometry.Offset
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.StrokeJoin
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import fn.compose.theme.FnColors
import fn.compose.theme.FnRadius
import fn.compose.theme.FnSpacing
import fn.compose.theme.FnTypography

/**
 * Page-level header with title, optional subtitle and trailing action slot.
 *
 * Layout: SpaceBetween Row with CenterVertically alignment.
 * Left side: Column with title + optional subtitle.
 * Right side: optional actions lambda.
 */
@Composable
fun FnPageHeader(
    title: String,
    modifier: Modifier = Modifier,
    subtitle: String? = null,
    actions: (@Composable () -> Unit)? = null,
) {
    Row(
        modifier = modifier.fillMaxWidth(),
        horizontalArrangement = Arrangement.SpaceBetween,
        verticalAlignment = Alignment.CenterVertically,
    ) {
        Column(modifier = Modifier.weight(1f)) {
            Text(
                text = title,
                fontSize = FnTypography.lg,
                fontWeight = FnTypography.bold,
                color = MaterialTheme.colorScheme.onSurface,
            )
            if (subtitle != null) {
                Text(
                    text = subtitle,
                    fontSize = FnTypography.sm,
                    fontWeight = FnTypography.normal,
                    color = FnColors.textMuted,
                )
            }
        }
        if (actions != null) {
            actions()
        }
    }
}

/**
 * KPI metric card: label, large value, optional delta badge and optional
 * inline sparkline drawn with Canvas (no external dependency).
 *
 * The [modifier] is forwarded to the outermost Surface so callers can pass
 * `Modifier.weight(1f)` inside a Row (as the gallery does).
 */
@Composable
fun FnKpiCard(
    label: String,
    value: String,
    modifier: Modifier = Modifier,
    delta: String? = null,
    deltaPositive: Boolean = true,
    sparklineData: List<Float>? = null,
) {
    Surface(
        modifier = modifier
            .border(
                width = 1.dp,
                color = FnColors.border,
                shape = RoundedCornerShape(FnRadius.md),
            ),
        shape = RoundedCornerShape(FnRadius.md),
        color = MaterialTheme.colorScheme.surface,
        tonalElevation = 0.dp,
        shadowElevation = 0.dp,
    ) {
        Column(
            modifier = Modifier.padding(FnSpacing.md),
            verticalArrangement = Arrangement.spacedBy(FnSpacing.xs / 2),
        ) {
            // Label
            Text(
                text = label,
                fontSize = FnTypography.sm,
                fontWeight = FnTypography.normal,
                color = FnColors.textMuted,
            )

            // Primary value
            Text(
                text = value,
                fontSize = FnTypography.xl,
                fontWeight = FnTypography.bold,
                color = MaterialTheme.colorScheme.onSurface,
            )

            // Delta badge
            if (delta != null) {
                Text(
                    text = delta,
                    fontSize = FnTypography.xs,
                    fontWeight = FnTypography.medium,
                    color = if (deltaPositive) FnColors.success else FnColors.error,
                )
            }

            // Inline sparkline — drawn with Canvas, no external component
            if (!sparklineData.isNullOrEmpty()) {
                val primaryColor = FnColors.primary
                Canvas(
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(32.dp),
                ) {
                    val data = sparklineData
                    if (data.size < 2) return@Canvas

                    val minVal = data.min()
                    val maxVal = data.max()
                    val range = (maxVal - minVal).let { if (it == 0f) 1f else it }

                    val w = size.width
                    val h = size.height
                    val stepX = w / (data.size - 1).toFloat()

                    // Build path points
                    val points = data.mapIndexed { index, v ->
                        val x = index * stepX
                        // Normalize: high value -> low y (top of canvas)
                        val y = h - ((v - minVal) / range) * h
                        Offset(x, y)
                    }

                    // Draw polyline segment by segment
                    for (i in 0 until points.size - 1) {
                        drawLine(
                            color = primaryColor,
                            start = points[i],
                            end = points[i + 1],
                            strokeWidth = 2.dp.toPx(),
                            cap = StrokeCap.Round,
                        )
                    }
                }
            }
        }
    }
}

/**
 * Column descriptor for [FnDataTable].
 *
 * @param T row data type.
 * @param header Column header label.
 * @param weight Relative width weight passed to [Modifier.weight].
 * @param cell Composable that renders a single cell for a given row value.
 */
data class FnTableColumn<T>(
    val header: String,
    val weight: Float,
    val cell: @Composable (T) -> Unit,
)

/**
 * Static data table.
 *
 * Uses a non-lazy [Column] so it can be embedded inside a parent
 * `verticalScroll` (as the gallery does). Do not wrap in LazyColumn.
 *
 * Layout:
 * - Header row: one Text per column, weighted, bold, muted color.
 * - [HorizontalDivider] below the header.
 * - One Row per data entry: one [Box] per column, weighted.
 * - [HorizontalDivider] between data rows (not after the last).
 */
@Composable
fun <T> FnDataTable(
    rows: List<T>,
    columns: List<FnTableColumn<T>>,
    modifier: Modifier = Modifier,
) {
    Column(modifier = modifier) {
        // Header row
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(
                    horizontal = FnSpacing.sm,
                    vertical = FnSpacing.xs,
                ),
            verticalAlignment = Alignment.CenterVertically,
        ) {
            columns.forEach { col ->
                Text(
                    text = col.header,
                    modifier = Modifier.weight(col.weight),
                    fontSize = FnTypography.sm,
                    fontWeight = FontWeight.Bold,
                    color = FnColors.textMuted,
                )
            }
        }

        HorizontalDivider(color = FnColors.border, thickness = 1.dp)

        // Data rows
        rows.forEachIndexed { rowIndex, row ->
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(
                        horizontal = FnSpacing.sm,
                        vertical = FnSpacing.xs,
                    ),
                verticalAlignment = Alignment.CenterVertically,
            ) {
                columns.forEach { col ->
                    Box(modifier = Modifier.weight(col.weight)) {
                        col.cell(row)
                    }
                }
            }
            // Divider between rows, not after the last
            if (rowIndex < rows.lastIndex) {
                HorizontalDivider(color = FnColors.border, thickness = 1.dp)
            }
        }
    }
}
