package app.voltplan.cable.ui.chargers

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import app.voltplan.cable.CableApplication
import app.voltplan.cable.analytics.Analytics
import app.voltplan.cable.data.LocaleDefaults
import app.voltplan.cable.data.model.PowerSourceType
import app.voltplan.cable.data.model.SavedCharger
import app.voltplan.cable.util.Fmt
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import java.util.UUID

enum class PowerEntryMode { CURRENT, POWER }

data class ChargerState(
    val name: String = "New Charger",
    val sourceType: PowerSourceType = PowerSourceType.SHORE,
    val inputVoltage: Double = 230.0,
    val outputVoltage: Double = 14.2,
    val maxCurrentAmps: Double = 30.0,
    val maxPowerWatts: Double = 0.0,
    val powerEntryMode: PowerEntryMode = PowerEntryMode.CURRENT,
    val lastManualPowerWatts: Double = 0.0,
    val iconName: String = "bolt.fill",
    val colorName: String = "orange",
) {
    val effectivePowerWatts: Double get() = if (maxPowerWatts > 0) maxPowerWatts else outputVoltage * maxCurrentAmps
    val displayedPower: Double
        get() = when {
            maxPowerWatts > 0 -> maxPowerWatts
            lastManualPowerWatts > 0 -> lastManualPowerWatts
            else -> maxOf(0.0, outputVoltage * maxCurrentAmps)
        }
}

class ChargerEditorViewModel(
    app: CableApplication,
    private val systemId: String,
    chargerId: String?,
) : ViewModel() {
    private val repo = app.repository
    private var id: String = chargerId ?: UUID.randomUUID().toString()
    private val isNew = chargerId == null
    private var loggedCreate = false

    private val _state = MutableStateFlow(ChargerState(inputVoltage = LocaleDefaults.mainsVoltage))
    val state: StateFlow<ChargerState> = _state.asStateFlow()

    init {
        viewModelScope.launch {
            if (chargerId != null) {
                repo.getCharger(chargerId)?.let { c ->
                    val mode = if (c.maxPowerWatts > 0) PowerEntryMode.POWER else PowerEntryMode.CURRENT
                    val current = if (c.maxPowerWatts > 0 && c.outputVoltage > 0) Fmt.roundToTenth(c.maxPowerWatts / c.outputVoltage) else c.maxCurrentAmps
                    _state.value = ChargerState(
                        name = c.name,
                        sourceType = PowerSourceType.fromRaw(c.powerSourceType),
                        inputVoltage = c.inputVoltage,
                        outputVoltage = c.outputVoltage,
                        maxCurrentAmps = current,
                        maxPowerWatts = c.maxPowerWatts,
                        powerEntryMode = mode,
                        lastManualPowerWatts = if (c.maxPowerWatts <= 0) c.outputVoltage * c.maxCurrentAmps else c.maxPowerWatts,
                        iconName = c.iconName,
                        colorName = c.colorName,
                    )
                }
            } else {
                val color = repo.getSystem(systemId)?.colorName ?: "orange"
                val name = repo.uniqueComponentName(systemId, "New Charger")
                _state.value = _state.value.copy(name = name, colorName = color)
            }
            Analytics.log("Charger Editor Opened", mapOf("source" to if (isNew) "create" else "edit"))
        }
    }

    private fun update(transform: (ChargerState) -> ChargerState) {
        _state.value = transform(_state.value)
        persist()
    }

    fun setName(v: String) = update { it.copy(name = v) }
    fun setSource(t: PowerSourceType) = update { it.copy(sourceType = t) }
    fun setInputVoltage(v: Double) = update { it.copy(inputVoltage = v.coerceAtLeast(0.0)) }

    fun setOutputVoltage(v: Double) = update { s ->
        val nv = v.coerceAtLeast(0.0)
        if (s.powerEntryMode == PowerEntryMode.POWER && s.maxPowerWatts > 0) {
            val voltage = maxOf(nv, 0.1)
            s.copy(outputVoltage = nv, maxCurrentAmps = Fmt.roundToTenth(s.maxPowerWatts / voltage))
        } else {
            s.copy(outputVoltage = nv, lastManualPowerWatts = nv * s.maxCurrentAmps)
        }
    }

    fun setCurrent(a: Double) = update { s ->
        val na = a.coerceAtLeast(0.0)
        s.copy(maxCurrentAmps = na, maxPowerWatts = 0.0, lastManualPowerWatts = s.outputVoltage * na)
    }

    fun setPower(w: Double) = update { s ->
        val nw = w.coerceAtLeast(0.0)
        val voltage = maxOf(s.outputVoltage, 0.1)
        s.copy(maxPowerWatts = nw, maxCurrentAmps = if (nw > 0) Fmt.roundToTenth(nw / voltage) else 0.0)
    }

    fun switchToPowerMode() = update { s ->
        val candidate = if (s.lastManualPowerWatts > 0) s.lastManualPowerWatts else s.outputVoltage * s.maxCurrentAmps
        val power = if (s.maxPowerWatts <= 0) candidate else s.maxPowerWatts
        val voltage = maxOf(s.outputVoltage, 0.1)
        s.copy(powerEntryMode = PowerEntryMode.POWER, maxPowerWatts = power, maxCurrentAmps = if (power > 0) Fmt.roundToTenth(power / voltage) else 0.0)
    }

    fun switchToCurrentMode() = update { s ->
        val lastManual = if (s.maxPowerWatts > 0) s.maxPowerWatts else s.lastManualPowerWatts
        s.copy(powerEntryMode = PowerEntryMode.CURRENT, maxPowerWatts = 0.0, lastManualPowerWatts = maxOf(lastManual, s.outputVoltage * s.maxCurrentAmps))
    }

    fun setAppearance(name: String, icon: String, color: String) = update { it.copy(name = name, iconName = icon, colorName = color) }

    private fun persist() {
        val s = _state.value
        val charger = SavedCharger(
            id = id,
            name = s.name,
            inputVoltage = s.inputVoltage,
            outputVoltage = s.outputVoltage,
            maxCurrentAmps = s.maxCurrentAmps,
            maxPowerWatts = s.maxPowerWatts,
            iconName = s.iconName,
            colorName = s.colorName,
            systemId = systemId,
            timestamp = System.currentTimeMillis(),
            powerSourceType = s.sourceType.rawValue,
        )
        viewModelScope.launch {
            repo.upsertCharger(charger)
            if (isNew && !loggedCreate) {
                loggedCreate = true
                Analytics.log("Charger Created", mapOf("name" to s.name, "output_voltage" to s.outputVoltage, "max_current" to s.maxCurrentAmps, "max_power" to s.maxPowerWatts))
            }
        }
    }
}
