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

import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.em
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import com.coldboreballisticsllc.scopedope.ballistics.BallisticsEngine
import com.coldboreballisticsllc.scopedope.domain.model.BcModel
import com.coldboreballisticsllc.scopedope.domain.model.ResultRow
import kotlin.math.absoluteValue
import com.coldboreballisticsllc.scopedope.ui.session.AdjUnit
import com.coldboreballisticsllc.scopedope.ui.session.SessionViewModel
import com.coldboreballisticsllc.scopedope.ui.theme.*

private fun clickValueDisplay(clickValue: String) = when (clickValue) {
    "0.1_mrad"  -> "0.1 MRAD"
    "0.05_mrad" -> "0.05 MRAD"
    "0.25_moa"  -> "0.25 MOA"
    "0.5_moa"   -> "0.5 MOA"
    "1_moa"     -> "1 MOA"
    else        -> clickValue.replace("_", " ").uppercase()
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ResultsScreen(
    sessionVm: SessionViewModel = hiltViewModel(),
) {
    val state by sessionVm.state.collectAsState()

    Scaffold(
        topBar = {
            Column {
                TopAppBar(
                    title = { Text("Results", style = MaterialTheme.typography.titleLarge) },
                    colors = TopAppBarDefaults.topAppBarColors(
                        containerColor    = ColorBackground,
                        titleContentColor = ColorTextPrimary,
                    ),
                )
                // Context strip
                Row(
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(38.dp)
                        .background(ColorSurface2)
                        .border(width = 1.dp, color = ColorBorder)
                        .padding(horizontal = 14.dp),
                    verticalAlignment     = Alignment.CenterVertically,
                    horizontalArrangement = Arrangement.spacedBy(12.dp),
                ) {
                    Text(
                        text  = state.adjUnit.name,
                        style = ContextStripStyle,
                        color = ColorAmber,
                    )
                    Box(Modifier.width(1.dp).height(18.dp).background(ColorBorder))
                    Text(
                        text  = clickValueDisplay(state.clickValue),
                        style = ContextStripStyle,
                        color = ColorTextMuted,
                    )
                    Box(Modifier.width(1.dp).height(18.dp).background(ColorBorder))
                    Text(
                        text     = state.ammo?.name ?: "No ammo selected",
                        style    = ContextStripStyle,
                        color    = ColorTextMuted,
                        maxLines = 1,
                        overflow = TextOverflow.Ellipsis,
                        modifier = Modifier.weight(1f),
                    )
                }
            }
        },
        containerColor = ColorBackground,
    ) { padding ->
        if (state.results.isEmpty()) {
            Box(Modifier.fillMaxSize().padding(padding), contentAlignment = Alignment.Center) {
                ResultsEmptyState()
            }
            return@Scaffold
        }

        val ammo = state.ammo
        val isSubsonicLoad = ammo != null &&
            ammo.muzzleVelFps < BallisticsEngine.speedOfSoundFps(state.conditions.temperatureF)
        val isG1Load = ammo?.bcModel == BcModel.G1

        LazyColumn(
            modifier       = Modifier.padding(padding).fillMaxSize(),
            contentPadding = PaddingValues(horizontal = 14.dp, vertical = 14.dp),
        ) {
            if (isSubsonicLoad) {
                item {
                    PhysicsWarningBanner("Subsonic load — physics prediction is approximate. Enter DOPE at each distance for accurate corrections.")
                    Spacer(Modifier.height(10.dp))
                }
            } else if (isG1Load) {
                item {
                    PhysicsWarningBanner("G1 BC — predictions degrade beyond 400 yd. Enter DOPE to correct.")
                    Spacer(Modifier.height(10.dp))
                }
            }

            val primary = state.results.firstOrNull { it.includeOnLabel }
            if (primary != null) {
                item {
                    PrimaryResultHero(row = primary, adjUnit = state.adjUnit)
                    Spacer(Modifier.height(8.dp))
                }
            }

            item {
                val includeCount = state.results.count { it.includeOnLabel }
                val maxCount     = state.labelFormat.maxEntries
                Row(
                    modifier              = Modifier.fillMaxWidth().padding(bottom = 4.dp, end = 2.dp),
                    horizontalArrangement = Arrangement.End,
                ) {
                    Text(
                        text  = "$includeCount / $maxCount ON LABEL",
                        style = BadgeStyle,
                        color = if (includeCount >= maxCount) ColorAmber else ColorTextMuted,
                    )
                }
                ResultTableHeader()
            }

            items(state.results, key = { it.distanceYards }) { row ->
                ResultTableRow(
                    row      = row,
                    adjUnit  = state.adjUnit,
                    onToggle = { sessionVm.toggleLabelInclusion(row.distanceYards) },
                )
                val hasSub = row.spinDriftMil.absoluteValue >= 0.01 ||
                             row.coriolisElevMil.absoluteValue >= 0.001 ||
                             row.coriolisWindMil.absoluteValue >= 0.001
                if (hasSub) {
                    CorrectionSubRow(row = row, adjUnit = state.adjUnit)
                }
            }

            item { Spacer(Modifier.height(80.dp)) }
        }
    }
}

// ── Empty state ───────────────────────────────────────────────────────────────

@Composable
private fun ResultsEmptyState() {
    Column(
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.spacedBy(14.dp),
        modifier            = Modifier.padding(horizontal = 28.dp),
    ) {
        ReticleIcon(size = 132.dp, color = ColorBorder)
        Text(
            text  = "AWAITING DATA",
            style = DataValueStyle.copy(fontSize = 13.sp, letterSpacing = 0.10.em),
            color = ColorTextMuted,
        )
        Text(
            text      = "Select ammo and add output distances to generate your fire solution.",
            style     = BodyStyle,
            color     = ColorTextMuted,
            textAlign = TextAlign.Center,
        )
    }
}

@Composable
private fun ReticleIcon(size: Dp, color: Color) {
    androidx.compose.foundation.Canvas(modifier = Modifier.size(size)) {
        val cx = this.size.width / 2f
        val cy = this.size.height / 2f
        val r  = cx * 0.85f
        val sw = this.size.width * 0.025f
        val gap = r * 0.2f
        drawCircle(color = color, radius = r, center = Offset(cx, cy), style = Stroke(sw))
        val tsw = sw * 0.7f
        val to = r * 0.55f
        val ti = r * 0.72f
        for (i in 0..3) {
            val xp = cx - to * 1.5f + i * (to)
            if (xp < cx - gap * 0.5f || xp > cx + gap * 0.5f) {
                drawLine(color, Offset(xp, cy - ti), Offset(xp, cy - r + sw), tsw)
            }
        }
        drawLine(color, Offset(cx - r * 0.9f, cy), Offset(cx - gap, cy), tsw)
        drawLine(color, Offset(cx + gap, cy), Offset(cx + r * 0.9f, cy), tsw)
        drawLine(color, Offset(cx, cy - r * 0.9f), Offset(cx, cy - gap), tsw)
        drawLine(color, Offset(cx, cy + gap), Offset(cx, cy + r * 0.9f), tsw)
        drawCircle(color = color, radius = sw, center = Offset(cx, cy))
    }
}

// ── Hero result card ──────────────────────────────────────────────────────────

@Composable
private fun PrimaryResultHero(row: ResultRow, adjUnit: AdjUnit) {
    val elevMil   = row.elevationMil
    val glowColor = when {
        elevMil > 0  -> ColorDataPositive
        elevMil < 0  -> ColorDataNegative
        else         -> ColorTextMuted
    }

    Box(modifier = Modifier.padding(top = 9.dp)) {
        Column(
            modifier = Modifier
                .fillMaxWidth()
                .background(ColorSurface)
                .drawBehind {
                    drawRect(
                        brush = Brush.radialGradient(
                            colors = listOf(glowColor.copy(alpha = 0.11f), Color.Transparent),
                            center = Offset(size.width * 0.5f, size.height * 0.45f),
                            radius = size.width * 0.7f,
                        ),
                    )
                    drawRect(ColorAmberDim, style = Stroke(1.dp.toPx()))
                    val cs = 16.dp.toPx()
                    val sw = 2.dp.toPx()
                    drawLine(ColorAmber, Offset(0f, cs), Offset(0f, 0f), sw)
                    drawLine(ColorAmber, Offset(0f, 0f), Offset(cs, 0f), sw)
                    drawLine(ColorAmber, Offset(size.width - cs, 0f), Offset(size.width, 0f), sw)
                    drawLine(ColorAmber, Offset(size.width, 0f), Offset(size.width, cs), sw)
                    drawLine(ColorAmber, Offset(0f, size.height - cs), Offset(0f, size.height), sw)
                    drawLine(ColorAmber, Offset(0f, size.height), Offset(cs, size.height), sw)
                    drawLine(ColorAmber, Offset(size.width, size.height - cs), Offset(size.width, size.height), sw)
                    drawLine(ColorAmber, Offset(size.width, size.height), Offset(size.width - cs, size.height), sw)
                }
                .padding(horizontal = 16.dp, vertical = 14.dp),
            horizontalAlignment = Alignment.CenterHorizontally,
        ) {
            Spacer(Modifier.height(4.dp))   // room below badge
            Text(
                text  = "${row.distanceYards} yd",
                style = ContextStripStyle.copy(letterSpacing = 0.12.em),
                color = ColorDataDist,
            )
            Spacer(Modifier.height(4.dp))
            val elevVal = if (adjUnit == AdjUnit.MOA) row.elevationMoa else row.elevationMil
            Text(
                text  = formatElev(elevVal, adjUnit == AdjUnit.MOA),
                style = HeroElevationStyle,
                color = elevColor(elevMil),
            )
            Spacer(Modifier.height(6.dp))
            Box(Modifier.width(48.dp).height(1.dp).background(ColorBorder))
            Spacer(Modifier.height(6.dp))
            if (row.windageMil != 0.0) {
                val windVal = if (adjUnit == AdjUnit.MOA) row.windageMoa else row.windageMil
                val windFmt = if (adjUnit == AdjUnit.MOA) "%.2f".format(windVal) else "%.1f".format(windVal)
                Text(
                    text  = "${windArrow(row.windageMil)} $windFmt",
                    style = HeroWindStyle,
                    color = ColorAmber,
                )
            }
            Text(
                text  = "${row.clicks} clicks",
                style = ContextStripStyle.copy(fontSize = 18.sp),
                color = ColorTextMuted,
            )
            Spacer(Modifier.height(6.dp))
            Row(horizontalArrangement = Arrangement.spacedBy(18.dp, Alignment.CenterHorizontally)) {
                if (row.spinDriftMil.absoluteValue >= 0.01) {
                    val sd = if (adjUnit == AdjUnit.MOA) "%.2f".format(row.spinDriftMoa) else "%.2f".format(row.spinDriftMil)
                    Text("SPIN DRIFT $sd", style = HeroSubStyle, color = ColorTextMuted)
                }
                if (row.coriolisElevMil.absoluteValue >= 0.001) {
                    val ce = if (adjUnit == AdjUnit.MOA) "%.3f".format(row.coriolisElevMoa) else "%.3f".format(row.coriolisElevMil)
                    Text("CORIOLIS $ce", style = HeroSubStyle, color = ColorTextMuted)
                }
            }
        }

        // FIRE SOLUTION badge centered on top border
        Box(
            Modifier
                .align(Alignment.TopCenter)
                .background(ColorSurface)
                .padding(horizontal = 10.dp),
        ) {
            Text(
                text  = "FIRE SOLUTION",
                style = BadgeStyle,
                color = ColorAmberDim,
            )
        }
    }
}

// ── Table header ──────────────────────────────────────────────────────────────

@Composable
private fun ResultTableHeader() {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .background(ColorSurface2)
            .border(width = 1.dp, color = ColorBorder)
            .padding(horizontal = 14.dp, vertical = 12.dp),
        verticalAlignment = Alignment.CenterVertically,
    ) {
        Text("Dist",  style = TableHeaderStyle, color = ColorTextMuted, modifier = Modifier.width(60.dp))
        Box(Modifier.width(1.dp).height(18.dp).background(ColorBorder))
        Text("Elev",  style = TableHeaderStyle, color = ColorTextMuted, modifier = Modifier.weight(1f).padding(start = 6.dp))
        Box(Modifier.width(1.dp).height(18.dp).background(ColorBorder))
        Text("Wind",  style = TableHeaderStyle, color = ColorTextMuted, modifier = Modifier.weight(1f).padding(start = 6.dp))
        Box(Modifier.width(1.dp).height(18.dp).background(ColorBorder))
        Text("Clks",  style = TableHeaderStyle, color = ColorTextMuted, modifier = Modifier.width(50.dp).padding(start = 6.dp), textAlign = TextAlign.End)
        Spacer(Modifier.width(44.dp))
    }
}

// ── Table row ─────────────────────────────────────────────────────────────────

@Composable
private fun ResultTableRow(
    row:      ResultRow,
    adjUnit:  AdjUnit,
    onToggle: () -> Unit,
) {
    val elevVal = if (adjUnit == AdjUnit.MOA) row.elevationMoa else row.elevationMil
    val windVal = if (adjUnit == AdjUnit.MOA) row.windageMoa   else row.windageMil
    val elevStr = if (adjUnit == AdjUnit.MOA) "%.2f".format(elevVal) else "%.1f".format(elevVal)
    val windStr = if (adjUnit == AdjUnit.MOA) "%.2f".format(windVal) else "%.1f".format(windVal)

    Row(
        modifier = Modifier
            .fillMaxWidth()
            .clickable(onClick = onToggle)
            .background(if (row.includeOnLabel) ColorAmber.copy(alpha = 0.07f) else ColorBackground)
            .drawBehind {
                if (row.includeOnLabel) {
                    drawRect(
                        color   = ColorAmber,
                        topLeft = Offset(0f, 0f),
                        size    = androidx.compose.ui.geometry.Size(3.dp.toPx(), size.height),
                    )
                }
                drawLine(
                    color       = ColorBorder.copy(alpha = 0.5f),
                    start       = Offset(0f, size.height - 0.5f),
                    end         = Offset(size.width, size.height - 0.5f),
                    strokeWidth = 1.dp.toPx(),
                )
            }
            .padding(horizontal = 14.dp)
            .heightIn(min = 60.dp),
        verticalAlignment = Alignment.CenterVertically,
    ) {
        Text(
            text     = "${row.distanceYards}",
            style    = DataValueStyle,
            color    = ColorDataDist,
            modifier = Modifier.width(60.dp),
        )
        Text(
            text     = elevStr,
            style    = DataValueStyle,
            color    = elevColor(row.elevationMil),
            modifier = Modifier.weight(1f).padding(start = 6.dp),
        )
        Text(
            text     = "${windArrow(row.windageMil)}$windStr",
            style    = DataValueStyle,
            color    = if (row.windageMil != 0.0) ColorAmber else ColorTextMuted,
            modifier = Modifier.weight(1f).padding(start = 6.dp),
        )
        Text(
            text      = "${row.clicks}",
            style     = DataValueStyle,
            color     = ColorTextPrimary,
            modifier  = Modifier.width(50.dp).padding(start = 6.dp),
            textAlign = TextAlign.End,
        )
        // Checkbox — 33×33dp amber when checked
        Box(
            modifier         = Modifier.size(44.dp),
            contentAlignment = Alignment.Center,
        ) {
            Box(
                modifier = Modifier
                    .size(33.dp)
                    .background(
                        color = if (row.includeOnLabel) ColorAmber else ColorBackground,
                        shape = MaterialTheme.shapes.extraSmall,
                    )
                    .border(1.dp, if (row.includeOnLabel) ColorAmber else ColorBorder, MaterialTheme.shapes.extraSmall),
                contentAlignment = Alignment.Center,
            ) {
                if (row.includeOnLabel) {
                    Text("✓", style = DataValueStyle.copy(fontSize = 14.sp), color = Color.Black)
                }
            }
        }
    }
}

// ── Correction sub-row ────────────────────────────────────────────────────────

@Composable
private fun CorrectionSubRow(row: ResultRow, adjUnit: AdjUnit) {
    val parts = buildList {
        if (row.spinDriftMil.absoluteValue >= 0.01) {
            val sd = if (adjUnit == AdjUnit.MOA) "%.2f".format(row.spinDriftMoa) else "%.2f".format(row.spinDriftMil)
            add("SPIN DRIFT ${windArrow(row.spinDriftMil)}$sd")
        }
        if (row.coriolisElevMil.absoluteValue >= 0.001) {
            val ce = if (adjUnit == AdjUnit.MOA) "%.3f".format(row.coriolisElevMoa) else "%.3f".format(row.coriolisElevMil)
            val arr = if (row.coriolisElevMil >= 0) "↑" else "↓"
            add("CORIOLIS $arr$ce")
        }
        if (row.coriolisWindMil.absoluteValue >= 0.001) {
            val cw = if (adjUnit == AdjUnit.MOA) "%.3f".format(row.coriolisWindMoa) else "%.3f".format(row.coriolisWindMil)
            add("COR.WIND ${windArrow(row.coriolisWindMil)}$cw")
        }
    }
    if (parts.isEmpty()) return

    Box(
        modifier = Modifier
            .fillMaxWidth()
            .background(if (row.includeOnLabel) ColorAmber.copy(alpha = 0.07f) else ColorBackground)
            .drawBehind {
                if (row.includeOnLabel) {
                    drawRect(
                        color   = ColorAmber,
                        topLeft = Offset(0f, 0f),
                        size    = androidx.compose.ui.geometry.Size(3.dp.toPx(), size.height),
                    )
                }
            }
            .padding(start = 14.dp, end = 58.dp, bottom = 10.dp),
    ) {
        Text(
            text  = parts.joinToString(" · "),
            style = FieldLabelStyle.copy(letterSpacing = 0.04.em),
            color = ColorTextMuted,
        )
    }
}

// ── Warning banner ────────────────────────────────────────────────────────────

@Composable
private fun PhysicsWarningBanner(text: String) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .background(ColorAmber.copy(alpha = 0.08f))
            .border(1.dp, ColorAmber.copy(alpha = 0.28f))
            .drawBehind {
                drawRect(
                    color   = ColorAmber,
                    topLeft = Offset(0f, 0f),
                    size    = androidx.compose.ui.geometry.Size(3.dp.toPx(), size.height),
                )
            }
            .padding(horizontal = 12.dp, vertical = 11.dp),
        verticalAlignment     = Alignment.Top,
        horizontalArrangement = Arrangement.spacedBy(10.dp),
    ) {
        Text("⚠", style = BodySubStyle, color = ColorAmber)
        Text(text, style = BodySubStyle, color = ColorAmber)
    }
}

// ── Helpers ───────────────────────────────────────────────────────────────────

private fun elevColor(mil: Double) = when {
    mil > 0  -> ColorDataPositive
    mil < 0  -> ColorDataNegative
    else     -> ColorTextPrimary
}

private fun windArrow(mil: Double) = when {
    mil > 0.05  -> ">"
    mil < -0.05 -> "<"
    else        -> ""
}

private fun formatElev(value: Double, isMoa: Boolean): String {
    val sign = if (value > 0) "+" else ""
    return if (isMoa) "$sign${"%.2f".format(value)}" else "$sign${"%.1f".format(value)}"
}
