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

import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.coldboreballisticsllc.scopedope.ballistics.UnitConversion
import com.coldboreballisticsllc.scopedope.domain.model.DopeEntry
import com.coldboreballisticsllc.scopedope.ui.components.ActionButton
import com.coldboreballisticsllc.scopedope.ui.components.NumericField
import com.coldboreballisticsllc.scopedope.ui.screens.tutorial.TutorialScreen
import com.coldboreballisticsllc.scopedope.ui.session.AdjUnit
import com.coldboreballisticsllc.scopedope.ui.session.MeasureSystem
import com.coldboreballisticsllc.scopedope.ui.session.SessionViewModel
import com.coldboreballisticsllc.scopedope.ui.theme.*

// Steps: 0=Welcome, 1=Tutorial, 2=SelectAmmo, 3=MeasureSystem, 4=AdjUnit, 5=AddDOPE
private const val ONBOARDING_STEPS = 5  // dot count, Tutorial excluded (has its own)

@Composable
fun OnboardingScreen(
    onNavigateAmmo: () -> Unit,
    onComplete:     () -> Unit,
    sessionVm:      SessionViewModel    = hiltViewModel(),
    onboardingVm:   OnboardingViewModel = hiltViewModel(),
) {
    val complete by onboardingVm.onboardingComplete.collectAsState()
    val state    by sessionVm.state.collectAsState()

    LaunchedEffect(complete) {
        if (complete == true) onComplete()
    }
    if (complete == null || complete == true) return

    var step by rememberSaveable { mutableStateOf(0) }

    // Auto-advance from SelectAmmo when ammo is picked
    LaunchedEffect(state.ammo) {
        if (step == 2 && state.ammo != null) step = 3
    }

    val skipToApp: () -> Unit = {
        onboardingVm.markComplete()
        onComplete()
    }

    // Tutorial (step 1) fills the screen on its own — render it without the onboarding chrome
    if (step == 1) {
        TutorialScreen(
            onDone    = { step = 2 },
            onSkipAll = skipToApp,
        )
        return
    }

    Box(
        modifier = Modifier
            .fillMaxSize()
            .background(ColorBackground)
            .systemBarsPadding(),
    ) {
        when (step) {
            0 -> StepWelcome(
                onNext      = { step = 1 },
                onSkipToApp = skipToApp,
            )
            2 -> StepSelectAmmo(
                ammoName    = state.ammo?.let { "${it.caliber} — ${it.name}" },
                onSelectAmmo = onNavigateAmmo,
                onSkipToApp = skipToApp,
            )
            3 -> StepMeasureSystem(
                current     = state.measureSystem,
                onSet       = sessionVm::setMeasureSystem,
                onNext      = { step = 4 },
                onSkipToApp = skipToApp,
            )
            4 -> StepAdjUnit(
                current     = state.adjUnit,
                onSet       = sessionVm::setAdjUnit,
                onNext      = { step = 5 },
                onSkipToApp = skipToApp,
            )
            5 -> StepAddDope(
                dopeEntries  = state.dopeEntries,
                adjUnit      = state.adjUnit,
                onAddEntry   = { sessionVm.setDopeEntry(state.dopeEntries.size, it) },
                onRemoveEntry = { sessionVm.removeDopeEntry(it) },
                onDone       = skipToApp,
                onSkipToApp  = skipToApp,
            )
        }

        // Progress dots (map step to dot index: 0→0, skip 1 (tutorial), 2→1, 3→2, 4→3, 5→4)
        val dotIndex = if (step >= 2) step - 1 else step
        Row(
            modifier              = Modifier
                .align(Alignment.TopCenter)
                .padding(top = 16.dp),
            horizontalArrangement = Arrangement.spacedBy(8.dp),
            verticalAlignment     = Alignment.CenterVertically,
        ) {
            repeat(ONBOARDING_STEPS) { i ->
                Box(
                    modifier = Modifier
                        .size(if (i == dotIndex) 10.dp else 6.dp)
                        .background(
                            color = if (i == dotIndex) ColorAmber else ColorBorder,
                            shape = CircleShape,
                        )
                )
            }
        }
    }
}

// ── Step 0: Welcome ───────────────────────────────────────────────────────────

@Composable
private fun StepWelcome(onNext: () -> Unit, onSkipToApp: () -> Unit) {
    Column(
        modifier              = Modifier
            .fillMaxSize()
            .padding(horizontal = 32.dp)
            .verticalScroll(rememberScrollState()),
        verticalArrangement   = Arrangement.Center,
        horizontalAlignment   = Alignment.CenterHorizontally,
    ) {
        Text(
            text      = "ScopeDOPE",
            style     = MaterialTheme.typography.titleLarge,
            color     = ColorAmber,
            textAlign = TextAlign.Center,
        )
        Spacer(Modifier.height(8.dp))
        Text(
            text      = "Precision's NEW Best Friend!",
            style     = MaterialTheme.typography.titleLarge,
            color     = ColorTextPrimary,
            textAlign = TextAlign.Center,
        )
        Spacer(Modifier.height(16.dp))
        Text(
            text      = "Reality-based ballistic corrections.",
            style     = MaterialTheme.typography.bodyLarge,
            color     = ColorTextMuted,
            textAlign = TextAlign.Center,
        )
        Spacer(Modifier.height(8.dp))
        Text(
            text      = "Built from YOUR confirmed impacts.",
            style     = MaterialTheme.typography.titleMedium,
            color     = ColorAmber,
            textAlign = TextAlign.Center,
        )
        Spacer(Modifier.height(24.dp))
        Text(
            text      = "ScopeDOPE blends your real-world range data with ballistics physics to generate corrections you can trust at any distance.",
            style     = MaterialTheme.typography.bodyLarge,
            color     = ColorTextMuted,
            textAlign = TextAlign.Center,
        )
        Spacer(Modifier.height(24.dp))
        Surface(
            color          = ColorSurface,
            shape          = MaterialTheme.shapes.medium,
            modifier       = Modifier.fillMaxWidth(),
            tonalElevation = 0.dp,
        ) {
            Text(
                text      = "The only mobile Ballistic Computer that uses YOUR actual DOPE data — not just math.",
                style     = MaterialTheme.typography.bodyMedium,
                color     = ColorAmber,
                textAlign = TextAlign.Center,
                modifier  = Modifier.padding(16.dp),
            )
        }
        Spacer(Modifier.height(32.dp))
        ActionButton(
            text     = "Get Started",
            onClick  = onNext,
            modifier = Modifier.fillMaxWidth(),
        )
        Spacer(Modifier.height(8.dp))
        SkipButton(onSkipToApp)
    }
}

// ── Step 2: Select Ammo ───────────────────────────────────────────────────────

@Composable
private fun StepSelectAmmo(
    ammoName:    String?,
    onSelectAmmo: () -> Unit,
    onSkipToApp: () -> Unit,
) {
    Column(
        modifier              = Modifier
            .fillMaxSize()
            .padding(horizontal = 32.dp)
            .verticalScroll(rememberScrollState()),
        verticalArrangement   = Arrangement.Center,
        horizontalAlignment   = Alignment.CenterHorizontally,
    ) {
        Text(
            text      = "Select Your Ammo",
            style     = MaterialTheme.typography.titleLarge,
            color     = ColorTextPrimary,
            textAlign = TextAlign.Center,
        )
        Spacer(Modifier.height(16.dp))
        Text(
            text      = "Choose your ammunition from the built-in database or add a custom entry.",
            style     = MaterialTheme.typography.bodyLarge,
            color     = ColorTextMuted,
            textAlign = TextAlign.Center,
        )
        Spacer(Modifier.height(32.dp))

        if (ammoName != null) {
            Surface(
                color          = ColorSurface,
                shape          = MaterialTheme.shapes.medium,
                modifier       = Modifier.fillMaxWidth(),
                tonalElevation = 0.dp,
            ) {
                Text(
                    text      = ammoName,
                    style     = MaterialTheme.typography.bodyLarge,
                    color     = ColorTextPrimary,
                    modifier  = Modifier.padding(16.dp),
                    textAlign = TextAlign.Center,
                )
            }
            Spacer(Modifier.height(12.dp))
        }

        ActionButton(
            text     = if (ammoName == null) "Select Ammo" else "Change Ammo",
            onClick  = onSelectAmmo,
            modifier = Modifier.fillMaxWidth(),
        )

        if (ammoName != null) {
            Spacer(Modifier.height(8.dp))
            Text(
                text  = "Proceeding to next step automatically…",
                style = MaterialTheme.typography.labelMedium,
                color = ColorTextMuted,
            )
        }

        Spacer(Modifier.height(8.dp))
        SkipButton(onSkipToApp)
    }
}

// ── Step 3: Measurement System ────────────────────────────────────────────────

@Composable
private fun StepMeasureSystem(
    current:    MeasureSystem,
    onSet:      (MeasureSystem) -> Unit,
    onNext:     () -> Unit,
    onSkipToApp: () -> Unit,
) {
    Column(
        modifier              = Modifier
            .fillMaxSize()
            .padding(horizontal = 32.dp)
            .verticalScroll(rememberScrollState()),
        verticalArrangement   = Arrangement.Center,
        horizontalAlignment   = Alignment.CenterHorizontally,
    ) {
        Text(
            text      = "Measurement System",
            style     = MaterialTheme.typography.titleLarge,
            color     = ColorTextPrimary,
            textAlign = TextAlign.Center,
        )
        Spacer(Modifier.height(8.dp))
        Text(
            text      = "This sets the default units for distance, temperature, pressure, and wind speed. You can override individual units in Advanced Settings.",
            style     = MaterialTheme.typography.bodyLarge,
            color     = ColorTextMuted,
            textAlign = TextAlign.Center,
        )
        Spacer(Modifier.height(32.dp))

        MeasureSystem.entries.forEach { sys ->
            val selected = current == sys
            Row(
                modifier          = Modifier
                    .fillMaxWidth()
                    .clickable { onSet(sys) }
                    .padding(vertical = 8.dp),
                verticalAlignment = Alignment.CenterVertically,
                horizontalArrangement = Arrangement.spacedBy(12.dp),
            ) {
                RadioButton(
                    selected = selected,
                    onClick  = { onSet(sys) },
                    colors   = RadioButtonDefaults.colors(selectedColor = ColorAmber),
                )
                Column {
                    Text(
                        text  = when (sys) {
                            MeasureSystem.US_CUSTOMARY -> "US Customary"
                            MeasureSystem.METRIC       -> "Metric"
                        },
                        style = MaterialTheme.typography.bodyLarge,
                        color = ColorTextPrimary,
                    )
                    Text(
                        text  = when (sys) {
                            MeasureSystem.US_CUSTOMARY -> "yd, ft, °F, inHg, mph"
                            MeasureSystem.METRIC       -> "m, °C, hPa, km/h"
                        },
                        style = MaterialTheme.typography.bodyMedium,
                        color = ColorTextMuted,
                    )
                }
            }
        }

        Spacer(Modifier.height(32.dp))
        ActionButton(text = "Continue", onClick = onNext, modifier = Modifier.fillMaxWidth())
        Spacer(Modifier.height(8.dp))
        SkipButton(onSkipToApp)
    }
}

// ── Step 4: Adjustment Unit ───────────────────────────────────────────────────

@Composable
private fun StepAdjUnit(
    current:    AdjUnit,
    onSet:      (AdjUnit) -> Unit,
    onNext:     () -> Unit,
    onSkipToApp: () -> Unit,
) {
    Column(
        modifier              = Modifier
            .fillMaxSize()
            .padding(horizontal = 32.dp)
            .verticalScroll(rememberScrollState()),
        verticalArrangement   = Arrangement.Center,
        horizontalAlignment   = Alignment.CenterHorizontally,
    ) {
        Text(
            text      = "Scope Adjustment Units",
            style     = MaterialTheme.typography.titleLarge,
            color     = ColorTextPrimary,
            textAlign = TextAlign.Center,
        )
        Spacer(Modifier.height(8.dp))
        Text(
            text      = "Match this to your scope's turret denomination. You can change it any time in Settings.",
            style     = MaterialTheme.typography.bodyLarge,
            color     = ColorTextMuted,
            textAlign = TextAlign.Center,
        )
        Spacer(Modifier.height(32.dp))

        AdjUnit.entries.forEach { unit ->
            val selected = current == unit
            Row(
                modifier          = Modifier
                    .fillMaxWidth()
                    .clickable { onSet(unit) }
                    .padding(vertical = 8.dp),
                verticalAlignment = Alignment.CenterVertically,
                horizontalArrangement = Arrangement.spacedBy(12.dp),
            ) {
                RadioButton(
                    selected = selected,
                    onClick  = { onSet(unit) },
                    colors   = RadioButtonDefaults.colors(selectedColor = ColorAmber),
                )
                Column {
                    Text(
                        text  = unit.name,
                        style = MaterialTheme.typography.bodyLarge,
                        color = ColorTextPrimary,
                    )
                    Text(
                        text  = when (unit) {
                            AdjUnit.MIL -> "Milliradians — 1 decimal place (e.g. 3.5)"
                            AdjUnit.MOA -> "MOA — 2 decimal places (e.g. 12.50)"
                        },
                        style = MaterialTheme.typography.bodyMedium,
                        color = ColorTextMuted,
                    )
                }
            }
        }

        Spacer(Modifier.height(32.dp))
        ActionButton(text = "Continue", onClick = onNext, modifier = Modifier.fillMaxWidth())
        Spacer(Modifier.height(8.dp))
        SkipButton(onSkipToApp)
    }
}

// ── Step 5: Add DOPE ──────────────────────────────────────────────────────────

@Composable
private fun StepAddDope(
    dopeEntries:  List<DopeEntry>,
    adjUnit:      AdjUnit,
    onAddEntry:   (DopeEntry) -> Unit,
    onRemoveEntry: (Int) -> Unit,
    onDone:       () -> Unit,
    onSkipToApp:  () -> Unit,
) {
    val milToAdj  = if (adjUnit == AdjUnit.MOA) UnitConversion.MIL_TO_MOA else 1.0
    val adjSuffix = if (adjUnit == AdjUnit.MOA) "MOA" else "MIL"

    var distStr     by remember { mutableStateOf("") }
    var adjStr      by remember { mutableStateOf("") }
    var adjNegative by remember { mutableStateOf(false) }
    val distFocusRequester = remember { FocusRequester() }

    val effectiveAdj: Double? = adjStr.toDoubleOrNull()?.let { v ->
        if (adjNegative) -kotlin.math.abs(v) else kotlin.math.abs(v)
    }
    val valid = distStr.toIntOrNull() != null && effectiveAdj != null

    val imeBottom = WindowInsets.ime.asPaddingValues().calculateBottomPadding()
    Column(
        modifier              = Modifier
            .fillMaxSize()
            .verticalScroll(rememberScrollState())
            .padding(start = 24.dp, end = 24.dp, bottom = imeBottom),
        verticalArrangement   = Arrangement.spacedBy(12.dp),
    ) {
        Spacer(Modifier.height(48.dp))

        Text(
            text  = "Add Your Confirmed Impacts",
            style = MaterialTheme.typography.titleLarge,
            color = ColorTextPrimary,
        )
        Text(
            text  = "ScopeDOPE needs at least 3 confirmed impacts to build your ballistic curve. " +
                    "These are real corrections you've verified at the range — not estimates. " +
                    "The more you add, the more accurate your corrections become.",
            style = MaterialTheme.typography.bodyMedium,
            color = ColorTextMuted,
        )

        // Existing entries
        if (dopeEntries.isNotEmpty()) {
            Column(verticalArrangement = Arrangement.spacedBy(6.dp)) {
                dopeEntries.forEachIndexed { index, entry ->
                    val adjVal   = entry.adjustmentMil * milToAdj
                    val adjColor = when {
                        entry.adjustmentMil > 0 -> ColorDataPositive
                        entry.adjustmentMil < 0 -> ColorDataNegative
                        else                    -> ColorTextPrimary
                    }
                    Row(
                        modifier              = Modifier
                            .fillMaxWidth()
                            .background(ColorSurface)
                            .border(1.dp, ColorBorder)
                            .padding(horizontal = 12.dp)
                            .heightIn(min = 48.dp),
                        horizontalArrangement = Arrangement.SpaceBetween,
                        verticalAlignment     = Alignment.CenterVertically,
                    ) {
                        Text(
                            text     = "${entry.distanceYards} yd",
                            style    = DataValueStyle,
                            color    = ColorDataDist,
                            modifier = Modifier.weight(1f),
                        )
                        Text(
                            text     = "%s%.1f $adjSuffix".format(if (entry.adjustmentMil >= 0) "+" else "", adjVal),
                            style    = DataValueStyle,
                            color    = adjColor,
                            modifier = Modifier.weight(1f),
                        )
                        IconButton(onClick = { onRemoveEntry(index) }) {
                            Text("✕", style = MaterialTheme.typography.bodyLarge, color = ColorError)
                        }
                    }
                }
            }
        }

        // Add entry row
        Row(
            modifier              = Modifier.fillMaxWidth(),
            horizontalArrangement = Arrangement.spacedBy(8.dp),
            verticalAlignment     = Alignment.Bottom,
        ) {
            // Distance field
            NumericField(
                value          = distStr,
                onValueChange  = { distStr = it },
                label          = "Distance",
                suffix         = "yd",
                modifier       = Modifier.weight(1f),
                focusRequester = distFocusRequester,
            )

            // Sign toggle + Adjustment field
            Column(modifier = Modifier.weight(1f)) {
                Text(
                    text  = "ADJUSTMENT",
                    style = FieldLabelStyle,
                    color = ColorTextMuted,
                )
                Spacer(Modifier.height(4.dp))
                Row(
                    verticalAlignment     = Alignment.CenterVertically,
                    horizontalArrangement = Arrangement.spacedBy(6.dp),
                ) {
                    // +/- sign toggle — active sign is colored, inactive is muted
                    Box(
                        modifier = Modifier
                            .size(56.dp)
                            .background(ColorSurface2)
                            .border(1.dp, ColorBorder)
                            .clickable { adjNegative = !adjNegative },
                        contentAlignment = Alignment.Center,
                    ) {
                        Text(
                            text = buildAnnotatedString {
                                withStyle(SpanStyle(
                                    color      = if (!adjNegative) ColorDataPositive else ColorTextDisabled,
                                    fontFamily = DataValueStyle.fontFamily,
                                    fontWeight = DataValueStyle.fontWeight,
                                    fontSize   = DataValueStyle.fontSize,
                                )) { append("+") }
                                withStyle(SpanStyle(
                                    color      = ColorTextDisabled,
                                    fontFamily = DataValueStyle.fontFamily,
                                    fontWeight = DataValueStyle.fontWeight,
                                    fontSize   = DataValueStyle.fontSize,
                                )) { append("/") }
                                withStyle(SpanStyle(
                                    color      = if (adjNegative) ColorDataNegative else ColorTextDisabled,
                                    fontFamily = DataValueStyle.fontFamily,
                                    fontWeight = DataValueStyle.fontWeight,
                                    fontSize   = DataValueStyle.fontSize,
                                )) { append("-") }
                            },
                        )
                    }
                    OutlinedTextField(
                        value         = adjStr,
                        onValueChange = { new ->
                            // Accept only digits and a single decimal point
                            adjStr = new.filter { it.isDigit() || it == '.' }
                                .let { s ->
                                    val dotIdx = s.indexOf('.')
                                    if (dotIdx < 0) s
                                    else s.substring(0, dotIdx + 1) + s.substring(dotIdx + 1).filter { it.isDigit() }
                                }
                        },
                        singleLine    = true,
                        suffix        = { Text(adjSuffix.lowercase(), style = FieldLabelStyle, color = ColorTextMuted) },
                        colors        = OutlinedTextFieldDefaults.colors(
                            focusedBorderColor      = ColorAmber,
                            unfocusedBorderColor    = ColorBorder,
                            focusedContainerColor   = ColorBackground,
                            unfocusedContainerColor = ColorBackground,
                            focusedTextColor        = if (adjNegative) ColorDataNegative else ColorDataPositive,
                            unfocusedTextColor      = if (adjNegative) ColorDataNegative else ColorDataPositive,
                            cursorColor             = ColorAmber,
                        ),
                        textStyle     = DataValueStyle,
                        keyboardOptions = androidx.compose.foundation.text.KeyboardOptions(
                            keyboardType = androidx.compose.ui.text.input.KeyboardType.Decimal,
                            imeAction    = androidx.compose.ui.text.input.ImeAction.Done,
                        ),
                        modifier      = Modifier.weight(1f).heightIn(min = 56.dp),
                    )
                }
            }

            // [+] button — minimum width so it stays square
            ActionButton(
                text     = "+",
                enabled  = valid,
                height   = 56.dp,
                notch    = 6.dp,
                modifier = Modifier
                    .widthIn(min = 56.dp)
                    .padding(top = 22.dp),
                onClick  = {
                    onAddEntry(DopeEntry(distStr.toInt(), effectiveAdj!!))
                    distStr = ""; adjStr = ""; adjNegative = false
                    distFocusRequester.requestFocus()
                },
            )
        }

        Spacer(Modifier.height(4.dp))

        ActionButton(
            text     = "Done",
            onClick  = onDone,
            modifier = Modifier.fillMaxWidth(),
        )
        SkipButton(onSkipToApp)
        Spacer(Modifier.height(24.dp))
    }
}

// ── Shared skip button ────────────────────────────────────────────────────────

@Composable
private fun SkipButton(onSkip: () -> Unit) {
    TextButton(
        onClick  = onSkip,
        modifier = Modifier.fillMaxWidth(),
    ) {
        Text(
            text  = "Start using the app",
            color = ColorAmberDim,
            style = MaterialTheme.typography.bodyMedium,
        )
    }
}
