package dev.kaizen.app.ui.effect

import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Paint
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp

/**
 * A single layer in a multi-layer shadow stack.
 *
 * Premium UI uses 3–5 overlapping shadow layers at increasing blur radii
 * and decreasing opacity, producing a soft, realistic falloff that a
 * single [Modifier.shadow] cannot match.
 */
data class ShadowLayer(
    val offsetY: Dp,
    val blur: Dp,
    val spread: Dp = 0.dp,
    val alpha: Float,
)

/**
 * A complete shadow stack of multiple [ShadowLayer]s.
 */
data class ShadowStack(val layers: List<ShadowLayer>)

/**
 * Predefined shadow levels — use these everywhere instead of ad-hoc
 * `Modifier.shadow(elevation = ...)`.
 */
object KaizenShadows {

    val level0 = ShadowStack(emptyList())

    val level1 = ShadowStack(
        listOf(
            ShadowLayer(1.dp, 2.dp, 0.dp, 0.04f),
            ShadowLayer(1.dp, 4.dp, 0.dp, 0.02f),
        )
    )

    val level2 = ShadowStack(
        listOf(
            ShadowLayer(2.dp, 4.dp, 0.dp, 0.05f),
            ShadowLayer(4.dp, 12.dp, 0.dp, 0.04f),
            ShadowLayer(8.dp, 24.dp, 0.dp, 0.03f),
        )
    )

    val level3 = ShadowStack(
        listOf(
            ShadowLayer(2.dp, 4.dp, 0.dp, 0.06f),
            ShadowLayer(8.dp, 16.dp, 0.dp, 0.05f),
            ShadowLayer(16.dp, 32.dp, 0.dp, 0.04f),
            ShadowLayer(24.dp, 48.dp, 0.dp, 0.03f),
        )
    )

    val level4 = ShadowStack(
        listOf(
            ShadowLayer(4.dp, 8.dp, 0.dp, 0.07f),
            ShadowLayer(12.dp, 24.dp, 0.dp, 0.06f),
            ShadowLayer(24.dp, 48.dp, 0.dp, 0.05f),
            ShadowLayer(48.dp, 96.dp, 0.dp, 0.04f),
        )
    )
}

/**
 * Draws a multi-layer shadow stack behind the content.
 *
 * [darkMultiplier] scales shadow alpha in dark mode (shadows need to be
 * stronger on dark surfaces to read). Default 1.8× matches the DESIGN.md spec.
 */
@Composable
fun Modifier.kaizenShadow(
    stack: ShadowStack,
    cornerRadius: Dp = 16.dp,
    darkMultiplier: Float = 1.8f,
): Modifier {
    val isDark = isSystemInDarkTheme()
    val effectiveMultiplier = if (isDark) darkMultiplier else 1f
    val layers = remember(stack, effectiveMultiplier) {
        stack.layers.map { layer ->
            layer.copy(alpha = (layer.alpha * effectiveMultiplier).coerceAtMost(1f))
        }
    }
    return this.drawBehind {
        drawShadowLayers(layers, cornerRadius)
    }
}

private fun DrawScope.drawShadowLayers(layers: List<ShadowLayer>, cornerRadius: Dp) {
    val cr = cornerRadius.toPx()
    drawIntoCanvas { canvas ->
        layers.forEach { layer ->
            val paint = Paint().apply {
                val framework = asFrameworkPaint()
                framework.color = Color.Black.copy(alpha = layer.alpha).toArgb()
                framework.setShadowLayer(
                    layer.blur.toPx(),
                    0f,
                    layer.offsetY.toPx(),
                    Color.Black.copy(alpha = layer.alpha).toArgb(),
                )
            }
            val spreadPx = layer.spread.toPx()
            canvas.drawRoundRect(
                left = -spreadPx,
                top = -spreadPx,
                right = size.width + spreadPx,
                bottom = size.height + spreadPx,
                radiusX = cr,
                radiusY = cr,
                paint = paint,
            )
        }
    }
}

/**
 * Inner top highlight — 1dp inset white line that simulates "light from above."
 * Together with the drop shadow, this makes glass surfaces look lit.
 */
@Composable
fun Modifier.innerTopHighlight(): Modifier {
    val isDark = isSystemInDarkTheme()
    val highlightAlpha = if (isDark) 0.08f else 0.95f
    return this.drawBehind {
        drawLine(
            color = Color.White.copy(alpha = highlightAlpha),
            start = Offset(0f, 1f),
            end = Offset(size.width, 1f),
            strokeWidth = 1.dp.toPx(),
        )
    }
}
