package app.voltplan.cable.ui.loads

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.ArrowBack
import androidx.compose.material.icons.outlined.ExpandLess
import androidx.compose.material.icons.outlined.ExpandMore
import androidx.compose.material.icons.outlined.ShoppingCart
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import app.voltplan.cable.CableApplication
import app.voltplan.cable.R
import app.voltplan.cable.analytics.Analytics
import app.voltplan.cable.calc.ElectricalCalculations
import app.voltplan.cable.data.UnitSystem
import app.voltplan.cable.ui.LocalUnitSettings
import app.voltplan.cable.ui.bom.LoadBillOfMaterialsSheet
import app.voltplan.cable.ui.components.AppearanceEditorSheet
import app.voltplan.cable.ui.components.LoadIcon
import app.voltplan.cable.ui.components.MetricBadge
import app.voltplan.cable.ui.components.SnapSlider
import app.voltplan.cable.ui.components.ValueEditDialog
import app.voltplan.cable.ui.loadIconOptions
import app.voltplan.cable.ui.theme.SysBlue
import app.voltplan.cable.ui.theme.SysOrange
import app.voltplan.cable.ui.theme.componentColor
import app.voltplan.cable.util.Fmt
import java.util.Locale

private enum class EditField { VOLTAGE, CURRENT, POWER, LENGTH, DUTY, USAGE }

private val VOLTAGE_SNAPS = listOf(3.3, 5.0, 6.0, 9.0, 12.0, 13.8, 24.0, 28.0, 48.0)
private val CURRENT_SNAPS = listOf(0.5, 1.0, 2.0, 3.0, 4.0, 5.0, 7.5, 10.0, 12.0, 15.0, 20.0, 25.0, 30.0, 40.0, 50.0, 60.0, 75.0, 80.0, 100.0)
private val POWER_SNAPS = listOf(5.0, 10.0, 15.0, 20.0, 25.0, 30.0, 40.0, 50.0, 60.0, 75.0, 100.0, 125.0, 150.0, 200.0, 250.0, 300.0, 400.0, 500.0, 600.0, 750.0, 1000.0, 1250.0, 1500.0, 2000.0)
private val LENGTH_SNAPS_METRIC = listOf(0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 6.0, 7.5, 10.0, 12.0, 15.0, 20.0)
private val LENGTH_SNAPS_IMPERIAL = listOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 8.0, 10.0, 12.0, 15.0, 20.0, 25.0, 30.0, 40.0, 50.0, 60.0)

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CalculatorScreen(systemId: String, loadId: String?, onBack: () -> Unit) {
    val context = LocalContext.current
    val app = context.applicationContext as CableApplication
    val vm: CalculatorViewModel = viewModel(
        key = "calc-${loadId ?: "new"}",
        factory = viewModelFactory { initializer { CalculatorViewModel(app, systemId, loadId) } },
    )
    val s by vm.state.collectAsStateWithLifecycle()
    val unit by LocalUnitSettings.current.unitSystem.collectAsStateWithLifecycle()

    var editing by remember { mutableStateOf<EditField?>(null) }
    var showAppearance by remember { mutableStateOf(false) }
    var showBom by remember { mutableStateOf(false) }

    val factor = if (unit == UnitSystem.IMPERIAL) ElectricalCalculations.FEET_PER_METER else 1.0
    val displayLength = s.length * factor

    val crossSection = ElectricalCalculations.recommendedCrossSection(s.length, s.current, s.voltage, unit)
    val vDropPct = ElectricalCalculations.voltageDropPercentage(s.length, s.current, s.voltage, unit)
    val vDrop = ElectricalCalculations.voltageDrop(s.length, s.current, s.voltage, unit)
    val pLoss = ElectricalCalculations.powerLoss(s.length, s.current, s.voltage, unit)

    Scaffold(
        topBar = {
            TopAppBar(
                navigationIcon = {
                    IconButton(onClick = onBack) {
                        Icon(Icons.AutoMirrored.Outlined.ArrowBack, contentDescription = stringResource(R.string.action_back))
                    }
                },
                title = {
                    Row(
                        verticalAlignment = Alignment.CenterVertically,
                        modifier = Modifier.clickable { showAppearance = true },
                    ) {
                        LoadIcon(s.remoteIconURLString, s.iconName, componentColor(s.colorName), 24.dp)
                        Text(s.loadName, fontWeight = FontWeight.SemiBold, modifier = Modifier.padding(start = 8.dp))
                    }
                },
            )
        },
    ) { padding ->
        Column(
            Modifier.padding(padding).fillMaxWidth().verticalScroll(rememberScrollState()).padding(16.dp),
            verticalArrangement = Arrangement.spacedBy(16.dp),
        ) {
            // Badges
            Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {
                MetricBadge("Fuse", "${s.recommendedFuseFormatted}A", SysOrange, Modifier.weight(1f))
                val wire = if (unit == UnitSystem.METRIC)
                    String.format(Locale.US, "%.1fm @ %.1fmm²", displayLength, crossSection)
                else
                    String.format(Locale.US, "%.1fft @ %s AWG", displayLength, ElectricalCalculations.formatAWG(crossSection))
                MetricBadge("Wire", wire, SysBlue, Modifier.weight(2f))
            }

            // Results row
            Row(horizontalArrangement = Arrangement.spacedBy(12.dp), modifier = Modifier.fillMaxWidth()) {
                val gauge = if (unit == UnitSystem.METRIC) String.format(Locale.US, "%.1f mm²", crossSection)
                else "${ElectricalCalculations.formatAWG(crossSection)} AWG"
                Text(gauge, color = SysBlue, style = MaterialTheme.typography.bodyMedium)
                Text("•", color = MaterialTheme.colorScheme.onSurfaceVariant)
                Text(
                    if (unit == UnitSystem.METRIC) String.format(Locale.US, "%.1f m", displayLength)
                    else String.format(Locale.US, "%.1f ft", displayLength),
                    style = MaterialTheme.typography.bodyMedium,
                    modifier = Modifier.clickable { editing = EditField.LENGTH },
                )
                Text("•", color = MaterialTheme.colorScheme.onSurfaceVariant)
                Text(
                    String.format(Locale.US, "%.1fV (%.1f%%)", vDrop, vDropPct),
                    color = if (vDropPct > 5) SysOrange else MaterialTheme.colorScheme.onSurface,
                    style = MaterialTheme.typography.bodyMedium,
                )
                Text("•", color = MaterialTheme.colorScheme.onSurfaceVariant)
                Text(String.format(Locale.US, "%.1fW", pLoss), style = MaterialTheme.typography.bodyMedium)
            }

            // Voltage slider
            SnapSlider(
                title = stringResource(R.string.slider_voltage_title),
                value = s.voltage,
                range = 0.0..maxOf(48.0, s.voltage),
                valueText = String.format(Locale.US, "%.1fV", s.voltage),
                onValueChange = vm::setVoltage,
                snapValues = VOLTAGE_SNAPS,
                snapTolerance = 0.3,
                round = Fmt::roundToTenth,
                onEditRequest = { editing = EditField.VOLTAGE },
            )

            // Current / Power slider with mode toggle
            if (s.isWattMode) {
                SnapSlider(
                    title = stringResource(R.string.slider_power_title),
                    value = s.power,
                    range = 0.0..maxOf(2000.0, s.power),
                    valueText = String.format(Locale.US, "%.0fW", s.power),
                    onValueChange = vm::setPower,
                    snapValues = POWER_SNAPS,
                    snapTolerance = 2.5,
                    round = Fmt::roundToNearestFive,
                    onEditRequest = { editing = EditField.POWER },
                    trailing = { TextButton(onClick = { vm.setWattMode(false) }) { Text(stringResource(R.string.slider_button_ampere)) } },
                )
            } else {
                SnapSlider(
                    title = stringResource(R.string.slider_current_title),
                    value = s.current,
                    range = 0.0..maxOf(100.0, s.current),
                    valueText = String.format(Locale.US, "%.1fA", s.current),
                    onValueChange = vm::setCurrent,
                    snapValues = CURRENT_SNAPS,
                    snapTolerance = 0.3,
                    round = Fmt::roundToTenth,
                    onEditRequest = { editing = EditField.CURRENT },
                    trailing = { TextButton(onClick = { vm.setWattMode(true) }) { Text(stringResource(R.string.slider_button_watt)) } },
                )
            }

            // Length slider (display units)
            val lengthSnaps = if (unit == UnitSystem.METRIC) LENGTH_SNAPS_METRIC else LENGTH_SNAPS_IMPERIAL
            val lengthMax = if (unit == UnitSystem.METRIC) maxOf(20.0, displayLength) else maxOf(60.0, displayLength)
            SnapSlider(
                title = stringResource(R.string.slider_length_title, unit.lengthUnit),
                value = displayLength,
                range = 0.0..lengthMax,
                valueText = String.format(Locale.US, "%.1f %s", displayLength, unit.lengthUnit),
                onValueChange = { vm.setLengthMeters(it / factor) },
                snapValues = lengthSnaps,
                snapTolerance = 0.5,
                round = Fmt::roundToTenth,
                onEditRequest = { editing = EditField.LENGTH },
            )

            // Advanced section
            Row(
                Modifier.fillMaxWidth().clickable { vm.toggleAdvanced() },
                verticalAlignment = Alignment.CenterVertically,
            ) {
                Text(
                    stringResource(R.string.calculator_advanced_section_title).uppercase(),
                    style = MaterialTheme.typography.labelMedium,
                    color = MaterialTheme.colorScheme.onSurfaceVariant,
                )
                androidx.compose.foundation.layout.Spacer(Modifier.weight(1f))
                Icon(
                    if (s.advancedExpanded) Icons.Outlined.ExpandLess else Icons.Outlined.ExpandMore,
                    contentDescription = null,
                )
            }
            AnimatedVisibility(visible = s.advancedExpanded) {
                Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
                    SnapSlider(
                        title = stringResource(R.string.calculator_advanced_duty_title),
                        value = s.dutyCyclePercent,
                        range = 0.0..100.0,
                        valueText = "${Fmt.number(s.dutyCyclePercent)}%",
                        onValueChange = vm::setDuty,
                        round = Fmt::roundToTenth,
                        onEditRequest = { editing = EditField.DUTY },
                    )
                    Text(
                        stringResource(R.string.calculator_advanced_duty_helper),
                        style = MaterialTheme.typography.bodySmall,
                        color = MaterialTheme.colorScheme.onSurfaceVariant,
                    )
                    SnapSlider(
                        title = stringResource(R.string.calculator_advanced_usage_title),
                        value = s.dailyUsageHours,
                        range = 0.0..24.0,
                        valueText = "${Fmt.number(s.dailyUsageHours)} ${stringResource(R.string.calculator_advanced_usage_unit)}",
                        onValueChange = vm::setUsage,
                        round = Fmt::roundToTenth,
                        onEditRequest = { editing = EditField.USAGE },
                    )
                    Text(
                        stringResource(R.string.calculator_advanced_usage_helper),
                        style = MaterialTheme.typography.bodySmall,
                        color = MaterialTheme.colorScheme.onSurfaceVariant,
                    )
                }
            }

            // Review parts
            Row(
                Modifier.fillMaxWidth().clip(RoundedCornerShape(12.dp))
                    .background(MaterialTheme.colorScheme.primary.copy(alpha = 0.12f))
                    .clickable {
                        Analytics.log(
                            "Review Parts Tapped",
                            mapOf("load" to (loadId ?: "new"), "has_affiliate" to (s.affiliateURLString != null)),
                        )
                        showBom = true
                    }
                    .padding(horizontal = 16.dp, vertical = 12.dp),
                verticalAlignment = Alignment.CenterVertically,
                horizontalArrangement = Arrangement.spacedBy(8.dp),
            ) {
                Icon(Icons.Outlined.ShoppingCart, contentDescription = null, tint = MaterialTheme.colorScheme.primary)
                Text(
                    stringResource(R.string.affiliate_button_review_parts),
                    color = MaterialTheme.colorScheme.primary,
                    fontWeight = FontWeight.SemiBold,
                )
            }
            Text(
                stringResource(
                    if (s.affiliateURLString != null) R.string.affiliate_description_with_link
                    else R.string.affiliate_description_without_link,
                ),
                style = MaterialTheme.typography.bodySmall,
                color = MaterialTheme.colorScheme.onSurfaceVariant,
            )
        }
    }

    // Field edit dialogs
    editing?.let { field ->
        val (title, message, initial, onConfirm) = editFieldConfig(field, s, displayLength, unit, vm, factor)
        ValueEditDialog(
            title = title,
            message = message,
            initialValue = initial,
            onConfirm = onConfirm,
            onDismiss = { editing = null },
        )
    }

    if (showAppearance) {
        AppearanceEditorSheet(
            title = stringResource(R.string.editor_load_title),
            nameLabel = stringResource(R.string.editor_load_name),
            previewSubtitle = stringResource(R.string.editor_load_preview),
            icons = loadIconOptions,
            initialName = s.loadName,
            initialIcon = s.iconName,
            initialColor = s.colorName,
            onSave = { name, icon, color -> vm.setAppearance(name, icon, color) },
            onDismiss = { showAppearance = false },
        )
    }

    if (showBom) {
        LoadBillOfMaterialsSheet(state = s, unitSystem = unit, onDismiss = { showBom = false })
    }
}

private data class EditConfig(
    val title: String,
    val message: String?,
    val initial: Double,
    val onConfirm: (Double) -> Unit,
)

@Composable
private fun editFieldConfig(
    field: EditField,
    s: CalcState,
    displayLength: Double,
    unit: UnitSystem,
    vm: CalculatorViewModel,
    factor: Double,
): EditConfig = when (field) {
    EditField.VOLTAGE -> EditConfig(stringResource(R.string.slider_voltage_title), stringResource(R.string.charger_alert_voltage_message), s.voltage) { vm.setVoltage(Fmt.roundToTenth(it)) }
    EditField.CURRENT -> EditConfig(stringResource(R.string.slider_current_title), stringResource(R.string.charger_alert_current_message), s.current) { vm.setCurrent(Fmt.roundToTenth(it)) }
    EditField.POWER -> EditConfig(stringResource(R.string.slider_power_title), stringResource(R.string.charger_alert_power_message), s.power) { vm.setPower(Fmt.roundToNearestFive(it)) }
    EditField.LENGTH -> EditConfig(stringResource(R.string.slider_length_title, unit.lengthUnit), null, displayLength) { vm.setLengthMeters(Fmt.roundToTenth(it) / factor) }
    EditField.DUTY -> EditConfig(stringResource(R.string.calculator_alert_duty_title), stringResource(R.string.calculator_alert_duty_message), s.dutyCyclePercent) { vm.setDuty(Fmt.roundToTenth(it)) }
    EditField.USAGE -> EditConfig(stringResource(R.string.calculator_alert_usage_title), stringResource(R.string.calculator_alert_usage_message), s.dailyUsageHours) { vm.setUsage(Fmt.roundToTenth(it)) }
}
