package app.voltplan.cable.ui.batteries

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.clickable
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
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.ArrowDropDown
import androidx.compose.material.icons.outlined.BatteryChargingFull
import androidx.compose.material.icons.outlined.Bolt
import androidx.compose.material.icons.outlined.ExpandLess
import androidx.compose.material.icons.outlined.ExpandMore
import androidx.compose.material.icons.outlined.Speed
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
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.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.data.model.Chemistry
import app.voltplan.cable.ui.batteryIconOptions
import app.voltplan.cable.ui.components.AppearanceEditorSheet
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.theme.SysBlue
import app.voltplan.cable.ui.theme.SysOrange
import app.voltplan.cable.ui.theme.SysPurple
import app.voltplan.cable.util.Fmt
import java.util.Locale
import kotlin.math.roundToInt

private enum class BField { VOLTAGE, CAPACITY, USABLE, CHARGE, CUTOFF, MIN_TEMP, MAX_TEMP }

private val V_SNAPS = listOf(6.0, 12.0, 12.8, 24.0, 25.6, 36.0, 48.0, 51.2)
private val CAP_SNAPS = listOf(10.0, 20.0, 50.0, 75.0, 100.0, 125.0, 150.0, 200.0, 300.0, 400.0, 600.0, 800.0, 1000.0)
private val CHARGE_SNAPS = listOf(13.8, 14.0, 14.2, 14.4, 14.6, 14.8, 15.0)
private val CUTOFF_SNAPS = listOf(10.0, 10.5, 11.0, 11.5, 12.0)
private val TEMP_SNAPS = listOf(-40.0, -20.0, -10.0, 0.0, 25.0, 40.0, 50.0, 60.0)

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BatteryEditorScreen(systemId: String, batteryId: String?, onBack: () -> Unit) {
    val context = LocalContext.current
    val app = context.applicationContext as CableApplication
    val vm: BatteryEditorViewModel = viewModel(
        key = "battery-${batteryId ?: "new"}",
        factory = viewModelFactory { initializer { BatteryEditorViewModel(app, systemId, batteryId) } },
    )
    val s by vm.state.collectAsStateWithLifecycle()
    var editing by remember { mutableStateOf<BField?>(null) }
    var showAppearance by remember { mutableStateOf(false) }
    var chemistryMenu by remember { mutableStateOf(false) }

    Scaffold(
        topBar = {
            TopAppBar(
                navigationIcon = {
                    IconButton(onClick = onBack) { Icon(Icons.AutoMirrored.Outlined.ArrowBack, contentDescription = stringResource(R.string.action_back)) }
                },
                title = {
                    Text(s.name, fontWeight = FontWeight.SemiBold, modifier = Modifier.clickable { showAppearance = true })
                },
            )
        },
    ) { padding ->
        Column(
            Modifier.padding(padding).fillMaxWidth().verticalScroll(rememberScrollState()).padding(16.dp),
            verticalArrangement = Arrangement.spacedBy(12.dp),
        ) {
            // Header chips
            Row(Modifier.horizontalScroll(rememberScrollState()), horizontalArrangement = Arrangement.spacedBy(12.dp)) {
                MetricBadge(stringResource(R.string.battery_badge_voltage), String.format(Locale.US, "%.1f V", s.nominalVoltage), SysOrange)
                MetricBadge(stringResource(R.string.battery_metric_capacity), String.format(Locale.US, "%.0f Ah", s.capacityAmpHours), SysBlue)
                MetricBadge(stringResource(R.string.battery_badge_energy), String.format(Locale.US, "%.0f Wh", s.energyWattHours), SysPurple)
            }

            // Chemistry picker
            Column {
                Text(stringResource(R.string.battery_field_chemistry).uppercase(), style = MaterialTheme.typography.labelMedium, color = MaterialTheme.colorScheme.onSurfaceVariant)
                Row(
                    Modifier.fillMaxWidth().clickable { chemistryMenu = true }.padding(vertical = 8.dp),
                    verticalAlignment = Alignment.CenterVertically,
                ) {
                    Text(s.chemistry.displayName, style = MaterialTheme.typography.titleLarge, fontWeight = FontWeight.Bold)
                    Icon(Icons.Outlined.ArrowDropDown, contentDescription = null)
                    DropdownMenu(expanded = chemistryMenu, onDismissRequest = { chemistryMenu = false }) {
                        Chemistry.entries.forEach { c ->
                            DropdownMenuItem(text = { Text(c.displayName) }, onClick = { vm.setChemistry(c); chemistryMenu = false })
                        }
                    }
                }
            }

            SnapSlider(
                title = stringResource(R.string.battery_slider_voltage),
                value = s.nominalVoltage,
                range = maxOf(0.0, minOf(6.0, s.nominalVoltage))..maxOf(60.0, s.nominalVoltage),
                valueText = String.format(Locale.US, "%.1f V", s.nominalVoltage),
                onValueChange = vm::setVoltage, snapValues = V_SNAPS, snapTolerance = 0.5, round = Fmt::roundToTenth,
                onEditRequest = { editing = BField.VOLTAGE },
            )
            SnapSlider(
                title = stringResource(R.string.battery_slider_capacity),
                value = s.capacityAmpHours,
                range = maxOf(0.0, minOf(5.0, s.capacityAmpHours))..maxOf(1000.0, s.capacityAmpHours),
                valueText = String.format(Locale.US, "%.0f Ah", s.capacityAmpHours),
                onValueChange = vm::setCapacity, snapValues = CAP_SNAPS, snapTolerance = 10.0, round = Fmt::roundToTenth,
                onEditRequest = { editing = BField.CAPACITY },
            )

            // Advanced
            Row(Modifier.fillMaxWidth().clickable { vm.toggleAdvanced() }, verticalAlignment = Alignment.CenterVertically) {
                Text(stringResource(R.string.battery_section_advanced).uppercase(), style = MaterialTheme.typography.labelMedium, color = MaterialTheme.colorScheme.onSurfaceVariant)
                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.battery_slider_usable_capacity),
                        value = s.usableFraction * 100,
                        range = 0.0..100.0,
                        valueText = "${(s.usableFraction * 100).roundToInt()}%",
                        onValueChange = vm::setUsablePercent,
                        snapValues = listOf(s.chemistry.usableCapacityFraction * 100),
                        snapTolerance = 1.0,
                        round = Fmt::roundToTenth,
                        onEditRequest = { editing = BField.USABLE },
                    )
                    if (s.usableOverrideFraction != null) {
                        OutlinedButton(onClick = { vm.resetUsable() }) { Text(stringResource(R.string.battery_button_reset_default)) }
                    }
                    Text(
                        if (s.usableOverrideFraction == null)
                            stringResource(R.string.battery_usable_footer_default, "${(s.chemistry.usableCapacityFraction * 100).roundToInt()}%")
                        else
                            stringResource(R.string.battery_usable_footer_override, "${(s.chemistry.usableCapacityFraction * 100).roundToInt()}%"),
                        style = MaterialTheme.typography.bodySmall,
                        color = MaterialTheme.colorScheme.onSurfaceVariant,
                    )
                    SnapSlider(
                        title = stringResource(R.string.battery_slider_charge_voltage),
                        value = s.chargeVoltage,
                        range = maxOf(0.0, minOf(10.0, s.chargeVoltage))..maxOf(60.0, s.chargeVoltage),
                        valueText = String.format(Locale.US, "%.1f V", s.chargeVoltage),
                        onValueChange = vm::setChargeVoltage, snapValues = CHARGE_SNAPS, snapTolerance = 0.2, round = Fmt::roundToTenth,
                        onEditRequest = { editing = BField.CHARGE },
                    )
                    Text(stringResource(R.string.battery_charge_helper), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant)
                    SnapSlider(
                        title = stringResource(R.string.battery_slider_cutoff_voltage),
                        value = s.cutOffVoltage,
                        range = maxOf(0.0, minOf(5.0, s.cutOffVoltage))..maxOf(60.0, s.chargeVoltage),
                        valueText = String.format(Locale.US, "%.1f V", s.cutOffVoltage),
                        onValueChange = vm::setCutoff, snapValues = CUTOFF_SNAPS, snapTolerance = 0.2, round = Fmt::roundToTenth,
                        onEditRequest = { editing = BField.CUTOFF },
                    )
                    Text(stringResource(R.string.battery_cutoff_helper), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant)
                    Text(stringResource(R.string.battery_slider_temperature_range), style = MaterialTheme.typography.labelMedium, color = MaterialTheme.colorScheme.onSurfaceVariant)
                    Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {
                        SnapSlider(
                            title = stringResource(R.string.battery_temp_min),
                            value = s.minTemp,
                            range = -60.0..minOf(s.maxTemp, 80.0),
                            valueText = String.format(Locale.US, "%.0f°C", s.minTemp),
                            onValueChange = vm::setMinTemp, snapValues = TEMP_SNAPS, snapTolerance = 1.5, round = Fmt::roundToTenth,
                            onEditRequest = { editing = BField.MIN_TEMP },
                            modifier = Modifier.weight(1f),
                        )
                        SnapSlider(
                            title = stringResource(R.string.battery_temp_max),
                            value = s.maxTemp,
                            range = maxOf(s.minTemp, -60.0)..80.0,
                            valueText = String.format(Locale.US, "%.0f°C", s.maxTemp),
                            onValueChange = vm::setMaxTemp, snapValues = TEMP_SNAPS, snapTolerance = 1.5, round = Fmt::roundToTenth,
                            onEditRequest = { editing = BField.MAX_TEMP },
                            modifier = Modifier.weight(1f),
                        )
                    }
                    Text(stringResource(R.string.battery_temp_helper), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant)
                }
            }
        }
    }

    editing?.let { field ->
        val onConfirm: (Double) -> Unit = when (field) {
            BField.VOLTAGE -> { v -> vm.setVoltage(Fmt.roundToTenth(v)) }
            BField.CAPACITY -> { v -> vm.setCapacity(Fmt.roundToTenth(v)) }
            BField.USABLE -> { v -> vm.setUsablePercent(v) }
            BField.CHARGE -> { v -> vm.setChargeVoltage(Fmt.roundToTenth(v)) }
            BField.CUTOFF -> { v -> vm.setCutoff(Fmt.roundToTenth(v)) }
            BField.MIN_TEMP -> { v -> vm.setMinTemp(Fmt.roundToTenth(v)) }
            BField.MAX_TEMP -> { v -> vm.setMaxTemp(Fmt.roundToTenth(v)) }
        }
        val title = when (field) {
            BField.VOLTAGE -> stringResource(R.string.battery_alert_voltage_title)
            BField.CAPACITY -> stringResource(R.string.battery_alert_capacity_title)
            BField.USABLE -> stringResource(R.string.battery_alert_usable_title)
            BField.CHARGE -> stringResource(R.string.battery_alert_charge_title)
            BField.CUTOFF -> stringResource(R.string.battery_alert_cutoff_title)
            BField.MIN_TEMP -> stringResource(R.string.battery_alert_min_temp_title)
            BField.MAX_TEMP -> stringResource(R.string.battery_alert_max_temp_title)
        }
        val initial = when (field) {
            BField.VOLTAGE -> s.nominalVoltage
            BField.CAPACITY -> s.capacityAmpHours
            BField.USABLE -> s.usableFraction * 100
            BField.CHARGE -> s.chargeVoltage
            BField.CUTOFF -> s.cutOffVoltage
            BField.MIN_TEMP -> s.minTemp
            BField.MAX_TEMP -> s.maxTemp
        }
        ValueEditDialog(title = title, message = null, initialValue = initial, onConfirm = onConfirm, onDismiss = { editing = null })
    }

    if (showAppearance) {
        AppearanceEditorSheet(
            title = stringResource(R.string.battery_appearance_title),
            nameLabel = stringResource(R.string.battery_field_name),
            previewSubtitle = stringResource(R.string.battery_appearance_subtitle),
            icons = batteryIconOptions,
            initialName = s.name,
            initialIcon = s.iconName,
            initialColor = s.colorName,
            onSave = { name, icon, color -> vm.setAppearance(name, icon, color) },
            onDismiss = { showAppearance = false },
        )
    }
}
