package dev.agentdeck.terrarium.creature

import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.graphics.drawscope.withTransform
import androidx.compose.ui.graphics.vector.PathParser
import dev.agentdeck.terrarium.CrayfishVisualState
import dev.agentdeck.terrarium.CreatureGeometry
import dev.agentdeck.terrarium.TerrariumColors
import dev.agentdeck.terrarium.TerrariumLayout
import dev.agentdeck.terrarium.TerrariumTiming
import kotlin.math.PI
import kotlin.math.cos
import kotlin.math.sin

/**
 * OpenClaw — front-facing lobster SVG mascot.
 * Based on openclaw.svg (viewBox 0 0 120 120) with gradient body,
 * articulated claws (pivot rotation) and wiggling antennae.
 *
 * SITTING/DORMANT: completely still on the rocks (no floating).
 * ROUTING: full animation — claw rotation, signal waves, eye flash, antenna wiggle.
 */
class CrayfishCreature(
    private val centerXFraction: Float = TerrariumLayout.CRAYFISH_CENTER_X_FRACTION,
    private val centerYFraction: Float = TerrariumLayout.CRAYFISH_CENTER_Y_FRACTION,
    private val scaleFactor: Float = 1f,
) : Creature {

    private var visualState by mutableStateOf(CrayfishVisualState.SITTING)
    private var time by mutableFloatStateOf(0f)
    private var transitionProgress by mutableFloatStateOf(1f)

    // Lazy-init parsed SVG paths (parsed once at first use)
    private val bodyPath by lazy { parseSvgPath(BODY_PATH_DATA) }
    private val leftClawPath by lazy { parseSvgPath(LEFT_CLAW_PATH_DATA) }
    private val rightClawPath by lazy { parseSvgPath(RIGHT_CLAW_PATH_DATA) }
    private val leftAntennaPath by lazy { parseSvgPath(LEFT_ANTENNA_PATH_DATA) }
    private val rightAntennaPath by lazy { parseSvgPath(RIGHT_ANTENNA_PATH_DATA) }

    fun setState(newState: CrayfishVisualState) {
        if (newState != visualState) {
            visualState = newState
            transitionProgress = 0f
        }
    }

    /** Current center position in fraction coords (for DataParticleSystem targeting). */
    fun currentPosition(): Pair<Float, Float> = currentXFraction to currentYFraction

    /** Whether the crayfish is actively routing (orchestrating). */
    fun isRouting(): Boolean = visualState == CrayfishVisualState.ROUTING

    private var currentXFraction = centerXFraction
    private var currentYFraction = centerYFraction
    private var heartbeatPhase = 0f

    override fun update(dt: Float) {
        time += dt
        if (transitionProgress < 1f) {
            transitionProgress = (transitionProgress + dt * 2f).coerceAtMost(1f)
        }
        // Track heartbeat phase for SITTING pulse (~4 second cycle)
        heartbeatPhase += dt
    }

    override fun draw(scope: DrawScope) {
        val w = scope.size.width
        val h = scope.size.height
        val baseWidth = minOf(w, h * 2f)

        val cx = w * centerXFraction
        val cy = h * centerYFraction
        val bodyWidth = baseWidth * TerrariumLayout.CRAYFISH_WIDTH_FRACTION * scaleFactor

        val alpha = when (visualState) {
            CrayfishVisualState.DORMANT -> 0.4f
            CrayfishVisualState.SICK -> 0.7f
            else -> 1f
        }

        val effectiveCX: Float
        val effectiveCY: Float
        when (visualState) {
            CrayfishVisualState.DORMANT -> {
                effectiveCX = cx
                effectiveCY = cy + bodyWidth * 0.3f
            }
            CrayfishVisualState.ROUTING -> {
                effectiveCX = cx
                effectiveCY = cy + sin(time * 3f) * bodyWidth * 0.05f
            }
            CrayfishVisualState.SITTING -> {
                effectiveCX = cx
                effectiveCY = cy + sin(time * 0.5f) * bodyWidth * 0.008f
            }
            CrayfishVisualState.SICK -> {
                // Slow labored breathing — droops slightly lower
                effectiveCX = cx
                effectiveCY = cy + bodyWidth * 0.08f + sin(time * 0.7f) * bodyWidth * 0.02f
            }
            else -> {
                effectiveCX = cx
                effectiveCY = cy
            }
        }

        // Track current position for DataParticleSystem targeting
        currentXFraction = effectiveCX / w
        currentYFraction = effectiveCY / h

        // ROUTING: draw signal waves BEHIND creature
        if (visualState == CrayfishVisualState.ROUTING) {
            drawSignalWaves(scope, effectiveCX, effectiveCY, bodyWidth, baseWidth)
        }

        // ROUTING: shell glow pulse underneath
        if (visualState == CrayfishVisualState.ROUTING) {
            val glowPulse = (sin(time * 4f) * 0.5f + 0.5f)
            val glowRadius = bodyWidth * (0.4f + glowPulse * 0.15f)
            scope.drawCircle(
                color = TerrariumColors.CrayfishEye.copy(alpha = 0.15f * glowPulse),
                radius = glowRadius,
                center = Offset(effectiveCX, effectiveCY),
            )
        }

        // SITTING: subtle heartbeat glow every ~4 seconds
        if (visualState == CrayfishVisualState.SITTING) {
            val cycle = heartbeatPhase % 4f
            // Double-pulse heartbeat: two quick pulses then rest
            val pulse = if (cycle < 0.15f) sin(cycle / 0.15f * PI.toFloat())
                else if (cycle in 0.25f..0.40f) sin((cycle - 0.25f) / 0.15f * PI.toFloat()) * 0.6f
                else 0f
            if (pulse > 0.01f) {
                val glowRadius = bodyWidth * (0.25f + pulse * 0.08f)
                scope.drawCircle(
                    color = TerrariumColors.CrayfishEye.copy(alpha = 0.08f * pulse),
                    radius = glowRadius,
                    center = Offset(effectiveCX, effectiveCY),
                )
            }
        }

        // Draw SVG-based creature
        drawSvgCreature(scope, effectiveCX, effectiveCY, bodyWidth, alpha)
    }

    private fun drawSvgCreature(
        scope: DrawScope,
        cx: Float, cy: Float,
        bodyWidth: Float,
        alpha: Float,
    ) {
        val scale = bodyWidth / SVG_VIEWBOX
        // SVG center is at (60, 60) — translate so it maps to (cx, cy)
        val offsetX = cx - SVG_VIEWBOX / 2f * scale
        val offsetY = cy - SVG_VIEWBOX / 2f * scale

        val brush = bodyBrush()

        val sickTilt = if (visualState == CrayfishVisualState.SICK) -12f else 0f

        scope.withTransform({
            translate(left = offsetX, top = offsetY)
            scale(scaleX = scale, scaleY = scale, pivot = Offset.Zero)
            if (sickTilt != 0f) {
                rotate(sickTilt, pivot = Offset(SVG_VIEWBOX / 2f, SVG_VIEWBOX / 2f))
            }
        }) {
            // 1. Body with gradient
            drawPath(bodyPath, brush = brush, alpha = alpha)

            // 2. Left claw with pivot rotation
            val leftAngle = clawAngleForState(side = -1f)
            withTransform({
                rotate(leftAngle, pivot = Offset(20f, 45f))
            }) {
                drawPath(leftClawPath, brush = brush, alpha = alpha)
            }

            // 3. Right claw with pivot rotation
            val rightAngle = clawAngleForState(side = 1f)
            withTransform({
                rotate(rightAngle, pivot = Offset(100f, 45f))
            }) {
                drawPath(rightClawPath, brush = brush, alpha = alpha)
            }

            // 4. Antennae with wiggle
            val antennaColor = shellColorForState().copy(alpha = alpha)
            val antennaStroke = Stroke(width = 3f, cap = StrokeCap.Round)

            val wiggleX = when (visualState) {
                CrayfishVisualState.ROUTING -> sin(time * 7f) * 4f
                CrayfishVisualState.SITTING -> sin(time * 0.8f) * 0.7f
                CrayfishVisualState.SICK -> sin(time * 0.3f) * 0.4f
                else -> 0f
            }
            val wiggleY = when (visualState) {
                CrayfishVisualState.ROUTING -> sin(time * 5f) * 3f
                CrayfishVisualState.SITTING -> sin(time * 0.5f) * 0.4f
                CrayfishVisualState.SICK -> 2f + sin(time * 0.4f) * 0.5f  // antennae droop down
                else -> 0f
            }

            withTransform({ translate(left = wiggleX, top = -wiggleY) }) {
                drawPath(leftAntennaPath, color = antennaColor, style = antennaStroke)
            }
            withTransform({ translate(left = -wiggleX, top = -wiggleY) }) {
                drawPath(rightAntennaPath, color = antennaColor, style = antennaStroke)
            }

            // 5. Eyes — dark circles with teal highlights
            val eyeDark = Color(0xFF050810).copy(alpha = alpha)
            drawCircle(eyeDark, radius = 6f, center = Offset(45f, 35f))
            drawCircle(eyeDark, radius = 6f, center = Offset(75f, 35f))

            val highlightColor = eyeColorForState().copy(alpha = alpha)
            drawCircle(highlightColor, radius = 2.5f, center = Offset(46f, 34f))
            drawCircle(highlightColor, radius = 2.5f, center = Offset(76f, 34f))
        }
    }

    private fun bodyBrush(): Brush {
        return when (visualState) {
            CrayfishVisualState.ROUTING -> {
                val pulse = (sin(time * 4f) * 0.5f + 0.5f) * 0.3f
                val startColor = lerpColor(TerrariumColors.CrayfishShell, TerrariumColors.CrayfishBodyLight, pulse)
                val endColor = lerpColor(TerrariumColors.CrayfishDark, TerrariumColors.CrayfishShell, pulse)
                Brush.linearGradient(
                    colors = listOf(startColor, endColor),
                    start = Offset(0f, 0f),
                    end = Offset(SVG_VIEWBOX, SVG_VIEWBOX),
                )
            }
            CrayfishVisualState.SICK -> {
                // Desaturated — gray-pinkish tint
                val sickStart = lerpColor(TerrariumColors.CrayfishShell, Color(0xFF8B7B7B), 0.55f)
                val sickEnd = lerpColor(TerrariumColors.CrayfishDark, Color(0xFF5A4A4A), 0.55f)
                Brush.linearGradient(
                    colors = listOf(sickStart, sickEnd),
                    start = Offset(0f, 0f),
                    end = Offset(SVG_VIEWBOX, SVG_VIEWBOX),
                )
            }
            else -> {
                Brush.linearGradient(
                    colors = listOf(TerrariumColors.CrayfishShell, TerrariumColors.CrayfishDark),
                    start = Offset(0f, 0f),
                    end = Offset(SVG_VIEWBOX, SVG_VIEWBOX),
                )
            }
        }
    }

    private fun shellColorForState(): Color {
        return when (visualState) {
            CrayfishVisualState.ROUTING -> {
                val pulse = (sin(time * 4f) * 0.5f + 0.5f) * 0.3f
                lerpColor(TerrariumColors.CrayfishShell, TerrariumColors.CrayfishBodyLight, pulse)
            }
            CrayfishVisualState.SICK -> lerpColor(TerrariumColors.CrayfishShell, Color(0xFF8B7B7B), 0.55f)
            else -> TerrariumColors.CrayfishShell
        }
    }

    private fun clawAngleForState(side: Float): Float {
        return when (visualState) {
            CrayfishVisualState.ROUTING -> {
                val phase = time * 2f * PI.toFloat() / (TerrariumTiming.CLAW_CLAP_PERIOD_MS / 1000f)
                val clap = sin(phase + side * 0.3f)
                side * clap * 28f
            }
            CrayfishVisualState.SITTING -> {
                side * sin(time * 0.4f) * 1.5f
            }
            CrayfishVisualState.WAITING -> side * 15f
            CrayfishVisualState.OBSERVING -> side * (3f + sin(time * 2f) * 5f)
            CrayfishVisualState.SICK -> side * (-8f + sin(time * 0.5f) * 2f)  // claws droop
            else -> 0f
        }
    }

    private fun eyeColorForState(): Color {
        return when (visualState) {
            CrayfishVisualState.ROUTING -> {
                val flash = sin(time * 2f * PI.toFloat() / (TerrariumTiming.EYE_FLASH_PERIOD_MS / 1000f))
                val intensity = flash * 0.5f + 0.5f
                lerpColor(TerrariumColors.CrayfishEye, Color.White, intensity * 0.5f)
            }
            CrayfishVisualState.SITTING -> {
                val breath = sin(time * 0.6f) * 0.15f + 0.85f
                TerrariumColors.CrayfishEye.copy(alpha = breath)
            }
            CrayfishVisualState.SICK -> {
                // Dim, flickering eyes
                val flicker = sin(time * 1.2f) * 0.1f + 0.45f
                TerrariumColors.CrayfishEye.copy(alpha = flicker)
            }
            else -> TerrariumColors.CrayfishEye
        }
    }

    private fun drawSignalWaves(scope: DrawScope, cx: Float, cy: Float, bodyWidth: Float, canvasWidth: Float) {
        val waveSpeed = time * 2f
        val maxRadius = canvasWidth * 0.15f

        for (i in 0 until 4) {
            val progress = ((waveSpeed + i * 0.25f) % 1f)
            val radius = bodyWidth * 0.3f + progress * maxRadius
            val waveAlpha = (1f - progress) * 0.35f

            scope.drawArc(
                color = TerrariumColors.CrayfishEye.copy(alpha = waveAlpha),
                startAngle = 120f,
                sweepAngle = 120f,
                useCenter = false,
                topLeft = Offset(cx - radius, cy - radius),
                size = Size(radius * 2, radius * 2),
                style = Stroke(width = 3f + (1f - progress) * 2f),
            )
        }

        for (i in 0 until 6) {
            val dotProgress = ((time * 3f + i * 0.16f) % 1f)
            val dotRadius = bodyWidth * 0.3f + dotProgress * maxRadius
            val dotAngle = (150f + dotProgress * 40f) * PI.toFloat() / 180f
            val dotX = cx + cos(dotAngle) * dotRadius
            val dotY = cy + sin(dotAngle) * dotRadius
            val dotAlpha = (1f - dotProgress) * 0.6f

            scope.drawCircle(
                color = TerrariumColors.TetraNeon.copy(alpha = dotAlpha),
                radius = bodyWidth * 0.015f,
                center = Offset(dotX, dotY),
            )
        }
    }

    private fun lerpColor(a: Color, b: Color, t: Float): Color {
        return Color(
            red = a.red + (b.red - a.red) * t,
            green = a.green + (b.green - a.green) * t,
            blue = a.blue + (b.blue - a.blue) * t,
            alpha = a.alpha + (b.alpha - a.alpha) * t,
        )
    }

    private fun parseSvgPath(data: String): Path {
        return PathParser().parsePathString(data).toPath()
    }

    companion object {
        // Canonical 120×120 OpenClaw crayfish geometry (see CreatureGeometry).
        private const val SVG_VIEWBOX = CreatureGeometry.CRAYFISH_VIEWBOX
        private const val BODY_PATH_DATA = CreatureGeometry.CRAYFISH_BODY_PATH_DATA
        private const val LEFT_CLAW_PATH_DATA = CreatureGeometry.CRAYFISH_LEFT_CLAW_PATH_DATA
        private const val RIGHT_CLAW_PATH_DATA = CreatureGeometry.CRAYFISH_RIGHT_CLAW_PATH_DATA
        private const val LEFT_ANTENNA_PATH_DATA = CreatureGeometry.CRAYFISH_LEFT_ANTENNA_PATH_DATA
        private const val RIGHT_ANTENNA_PATH_DATA = CreatureGeometry.CRAYFISH_RIGHT_ANTENNA_PATH_DATA
    }
}
