package dev.kaizen.app.ui.shape

import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Outline
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import kotlin.math.abs
import kotlin.math.cos
import kotlin.math.min
import kotlin.math.pow
import kotlin.math.sign
import kotlin.math.sin

/**
 * iOS-style continuous superellipse ("squircle").
 *
 * Unlike [RoundedCornerShape] which is a rectangle with quarter-circle arcs,
 * a squircle has G2-continuous corners (curvature matches, not just position).
 * The visual difference is subtle at small radii but unmistakable at 16+ dp —
 * corners ease into the straight edges instead of snapping.
 *
 * The superellipse equation: |x/a|^n + |y/b|^n = 1
 *   n = 2    → circle/ellipse
 *   n = 4–5  → iOS icon / Apple Liquid Glass sweet spot
 *   n → ∞    → rectangle
 *
 * [smoothness] controls the `n` exponent. Default 4.5 matches iOS 26.
 * [samplesPerCorner] controls path resolution. 32 is invisible at any
 * screen density; reduce to 16 for small shapes (< 32 dp).
 */
class SquircleShape(
    private val radius: Dp,
    private val smoothness: Float = 4.5f,
    private val samplesPerCorner: Int = 32,
) : androidx.compose.ui.graphics.Shape {

    override fun createOutline(
        size: Size,
        layoutDirection: LayoutDirection,
        density: Density,
    ): Outline {
        val r = with(density) { radius.toPx() }
            .coerceAtMost(min(size.width, size.height) / 2f)

        if (r <= 0f) return Outline.Rectangle(
            androidx.compose.ui.geometry.Rect(0f, 0f, size.width, size.height)
        )

        val path = Path().apply {
            buildSquirclePath(size.width, size.height, r, smoothness, samplesPerCorner)
        }
        return Outline.Generic(path)
    }

    override fun toString(): String = "SquircleShape(radius=$radius, smoothness=$smoothness)"
}

/**
 * Builds a closed squircle path into [this] Path.
 *
 * Traces the superellipse corner arcs and straight edges clockwise
 * starting from the top-left corner's right edge.
 */
private fun Path.buildSquirclePath(
    w: Float,
    h: Float,
    r: Float,
    n: Float,
    samples: Int,
) {
    val step = (Math.PI / 2.0) / samples

    fun superX(angle: Double): Float {
        val cosA = cos(angle)
        return (abs(cosA).pow(2.0 / n) * sign(cosA) * r).toFloat()
    }

    fun superY(angle: Double): Float {
        val sinA = sin(angle)
        return (abs(sinA).pow(2.0 / n) * sign(sinA) * r).toFloat()
    }

    // Start at top edge, right of top-left corner
    moveTo(r, 0f)

    // Top edge → top-right corner
    lineTo(w - r, 0f)
    for (i in 0..samples) {
        val angle = Math.PI / 2.0 - step * i
        val sx = superX(angle)
        val sy = superY(angle)
        lineTo(w - r + sx, r - sy)
    }

    // Right edge → bottom-right corner
    lineTo(w, h - r)
    for (i in 0..samples) {
        val angle = -step * i
        val sx = superX(angle)
        val sy = superY(angle)
        lineTo(w - r + sx, h - r - sy)
    }

    // Bottom edge → bottom-left corner
    lineTo(r, h)
    for (i in 0..samples) {
        val angle = -(Math.PI / 2.0) - step * i
        val sx = superX(angle)
        val sy = superY(angle)
        lineTo(r + sx, h - r - sy)
    }

    // Left edge → top-left corner
    lineTo(0f, r)
    for (i in 0..samples) {
        val angle = Math.PI - step * i
        val sx = superX(angle)
        val sy = superY(angle)
        lineTo(r + sx, r - sy)
    }

    close()
}
