// Copyright (C) 2026 Jason M. Schwefel. All Rights Reserved.
package com.coldboreballisticsllc.scopedope.ui.components

import androidx.compose.foundation.Canvas
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.size
import androidx.compose.material3.MaterialTheme
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.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.input.pointer.pointerInput
import androidx.compose.ui.text.TextMeasurer
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.drawText
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.rememberTextMeasurer
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlin.math.atan2
import kotlin.math.cos
import kotlin.math.sin
import com.coldboreballisticsllc.scopedope.ui.theme.ColorAmber
import com.coldboreballisticsllc.scopedope.ui.theme.ColorBorder
import com.coldboreballisticsllc.scopedope.ui.theme.ColorDataDist
import com.coldboreballisticsllc.scopedope.ui.theme.ColorError
import com.coldboreballisticsllc.scopedope.ui.theme.ColorSurface
import com.coldboreballisticsllc.scopedope.ui.theme.ColorTextMuted
import com.coldboreballisticsllc.scopedope.ui.theme.InterSans

private fun compassDesc(deg: Double): String {
    val d = ((deg % 360) + 360) % 360
    return when {
        d < 22.5  || d >= 337.5 -> "North"
        d < 67.5               -> "NE"
        d < 112.5              -> "East"
        d < 157.5              -> "SE"
        d < 202.5              -> "South"
        d < 247.5              -> "SW"
        d < 292.5              -> "West"
        else                   -> "NW"
    }
}

private fun windDesc(deg: Double): String {
    val d = ((deg % 360) + 360) % 360
    return when {
        d < 22.5  || d >= 337.5 -> "Headwind"
        d < 67.5               -> "Head / R→L"
        d < 112.5              -> "R→L"
        d < 157.5              -> "R→L / Tail"
        d < 202.5              -> "Tailwind"
        d < 247.5              -> "Tail / L→R"
        d < 292.5              -> "L→R"
        else                   -> "L→R / Head"
    }
}

@Composable
fun WindDirectionDial(
    angleDeg:      Double,
    onAngleChange: (Double) -> Unit,
    modifier:      Modifier = Modifier,
) {
    val angle        = ((angleDeg % 360) + 360) % 360
    val textMeasurer = rememberTextMeasurer()

    Column(
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.spacedBy(4.dp),
        modifier            = modifier,
    ) {
        Canvas(
            modifier = Modifier
                .size(120.dp)
                .pointerInput(Unit) {
                    detectTapGestures { offset ->
                        val cx  = size.width / 2f
                        val cy  = size.height / 2f
                        val dx  = (offset.x - cx).toDouble()
                        val dy  = (offset.y - cy).toDouble()
                        val deg = Math.toDegrees(atan2(dx, -dy))
                        onAngleChange(((deg % 360) + 360) % 360)
                    }
                },
        ) {
            drawCompassDial(angle.toFloat(), textMeasurer)
        }
        Text(
            text  = "${"%.0f".format(angle)}°  ${windDesc(angle)}",
            style = MaterialTheme.typography.labelMedium.copy(
                fontFamily = InterSans,
                color      = ColorAmber,
            ),
        )
        Text(
            text  = "Tap to set",
            style = MaterialTheme.typography.labelMedium,
            color = ColorTextMuted,
        )
    }
}

private fun DrawScope.drawCompassDial(angleDeg: Float, textMeasurer: TextMeasurer) {
    val cx    = size.width / 2f
    val cy    = size.height / 2f
    val r     = size.minDimension / 2f
    val ringR = r * 0.90f

    // Background + ring
    drawCircle(color = ColorSurface, radius = ringR)
    drawCircle(color = ColorBorder,  radius = ringR, style = Stroke(width = 1.5f))

    // Tick marks at 0°, 90°, 180°, 270°
    for (tickDeg in listOf(0f, 90f, 180f, 270f)) {
        val rad  = Math.toRadians(tickDeg.toDouble())
        val sinT = sin(rad).toFloat()
        val cosT = cos(rad).toFloat()
        drawLine(
            color       = ColorBorder,
            start       = Offset(cx + sinT * ringR,          cy - cosT * ringR),
            end         = Offset(cx + sinT * ringR * 0.83f,  cy - cosT * ringR * 0.83f),
            strokeWidth = 1.5f,
        )
    }

    // "TARGET" label — sits just inside the top of the ring
    val targetStyle = TextStyle(
        fontFamily = InterSans,
        fontWeight = FontWeight.SemiBold,
        fontSize   = 7.sp,
        color      = ColorDataDist,
    )
    val targetLayout = textMeasurer.measure("TARGET", targetStyle)
    drawText(
        textLayoutResult = targetLayout,
        topLeft          = Offset(
            x = cx - targetLayout.size.width / 2f,
            y = cy - ringR * 0.78f,
        ),
    )

    // Arrow: tail at the outer ring toward angleDeg, arrowhead pointing at center
    val rad  = Math.toRadians(angleDeg.toDouble())
    val sinA = sin(rad).toFloat()
    val cosA = cos(rad).toFloat()

    val outerR   = ringR * 0.78f
    val baseR    = ringR * 0.24f
    val tipR     = ringR * 0.09f
    val wingSize = ringR * 0.13f

    drawLine(
        color       = ColorAmber,
        start       = Offset(cx + sinA * outerR, cy - cosA * outerR),
        end         = Offset(cx + sinA * baseR,  cy - cosA * baseR),
        strokeWidth = 3f,
        cap         = StrokeCap.Round,
    )

    // Arrowhead triangle (tip toward center)
    val tip   = Offset(cx + sinA * tipR,  cy - cosA * tipR)
    val wing1 = Offset(cx + sinA * baseR + cosA * wingSize, cy - cosA * baseR + sinA * wingSize)
    val wing2 = Offset(cx + sinA * baseR - cosA * wingSize, cy - cosA * baseR - sinA * wingSize)
    drawPath(
        path  = Path().apply {
            moveTo(tip.x,   tip.y)
            lineTo(wing1.x, wing1.y)
            lineTo(wing2.x, wing2.y)
            close()
        },
        color = ColorAmber,
    )

    // Shooter dot at center
    drawCircle(color = ColorError, radius = 4f)
}

// ── Firing azimuth dial ───────────────────────────────────────────────────────

@Composable
fun FiringAzimuthDial(
    angleDeg:      Double,
    onAngleChange: (Double) -> Unit,
    modifier:      Modifier = Modifier,
) {
    val angle        = ((angleDeg % 360) + 360) % 360
    val textMeasurer = rememberTextMeasurer()

    Column(
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.spacedBy(4.dp),
        modifier            = modifier,
    ) {
        Canvas(
            modifier = Modifier
                .size(120.dp)
                .pointerInput(Unit) {
                    detectTapGestures { offset ->
                        val cx  = size.width / 2f
                        val cy  = size.height / 2f
                        val dx  = (offset.x - cx).toDouble()
                        val dy  = (offset.y - cy).toDouble()
                        val deg = Math.toDegrees(atan2(dx, -dy))
                        onAngleChange(((deg % 360) + 360) % 360)
                    }
                },
        ) {
            drawAzimuthDial(angle.toFloat(), textMeasurer)
        }
        Text(
            text  = "${"%.0f".format(angle)}°  ${compassDesc(angle)}",
            style = MaterialTheme.typography.labelMedium.copy(
                fontFamily = InterSans,
                color      = ColorAmber,
            ),
        )
        Text(
            text  = "Tap to set",
            style = MaterialTheme.typography.labelMedium,
            color = ColorTextMuted,
        )
    }
}

private fun DrawScope.drawAzimuthDial(angleDeg: Float, textMeasurer: TextMeasurer) {
    val cx    = size.width / 2f
    val cy    = size.height / 2f
    val r     = size.minDimension / 2f
    val ringR = r * 0.90f

    // Background + ring
    drawCircle(color = ColorSurface, radius = ringR)
    drawCircle(color = ColorBorder,  radius = ringR, style = Stroke(width = 1.5f))

    // Tick marks at N/E/S/W
    for (tickDeg in listOf(0f, 90f, 180f, 270f)) {
        val rad  = Math.toRadians(tickDeg.toDouble())
        val sinT = sin(rad).toFloat()
        val cosT = cos(rad).toFloat()
        drawLine(
            color       = ColorBorder,
            start       = Offset(cx + sinT * ringR,          cy - cosT * ringR),
            end         = Offset(cx + sinT * ringR * 0.83f,  cy - cosT * ringR * 0.83f),
            strokeWidth = 1.5f,
        )
    }

    // "N" label at top
    val nStyle = TextStyle(
        fontFamily = InterSans,
        fontWeight = FontWeight.SemiBold,
        fontSize   = 7.sp,
        color      = ColorDataDist,
    )
    val nLayout = textMeasurer.measure("N", nStyle)
    drawText(
        textLayoutResult = nLayout,
        topLeft          = Offset(
            x = cx - nLayout.size.width / 2f,
            y = cy - ringR * 0.78f,
        ),
    )

    // Arrow: points FROM center TOWARD angleDeg (arrowhead at outer ring)
    val rad  = Math.toRadians(angleDeg.toDouble())
    val sinA = sin(rad).toFloat()
    val cosA = cos(rad).toFloat()

    val outerR   = ringR * 0.78f
    val baseR    = ringR * 0.24f
    val tipR     = ringR * 0.09f
    val wingSize = ringR * 0.13f

    // Shaft from center outward
    drawLine(
        color       = ColorAmber,
        start       = Offset(cx + sinA * tipR,  cy - cosA * tipR),
        end         = Offset(cx + sinA * baseR, cy - cosA * baseR),
        strokeWidth = 3f,
        cap         = StrokeCap.Round,
    )

    // Arrowhead at outer ring (tip points away from center)
    val tip   = Offset(cx + sinA * outerR,                        cy - cosA * outerR)
    val wing1 = Offset(cx + sinA * baseR + cosA * wingSize,       cy - cosA * baseR + sinA * wingSize)
    val wing2 = Offset(cx + sinA * baseR - cosA * wingSize,       cy - cosA * baseR - sinA * wingSize)
    drawPath(
        path  = Path().apply {
            moveTo(tip.x,   tip.y)
            lineTo(wing1.x, wing1.y)
            lineTo(wing2.x, wing2.y)
            close()
        },
        color = ColorAmber,
    )

    // Shooter dot at center
    drawCircle(color = ColorError, radius = 4f)
}
