package app.voltplan.cable.library

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import app.voltplan.cable.CableApplication
import app.voltplan.cable.analytics.Analytics
import app.voltplan.cable.data.model.ElectricalSystem
import app.voltplan.cable.data.model.SavedLoad
import app.voltplan.cable.ui.systems.SystemIconMapper
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

data class LibraryUiState(
    val loading: Boolean = true,
    val error: String? = null,
    val items: List<ComponentLibraryItem> = emptyList(),
    val query: String = "",
) {
    val filtered: List<ComponentLibraryItem>
        get() {
            val q = query.trim()
            if (q.isEmpty()) return items
            return items.filter {
                it.localizedName.contains(q, ignoreCase = true) || it.name.contains(q, ignoreCase = true)
            }
        }
}

class ComponentLibraryViewModel(
    private val app: CableApplication,
    private val libraryRepo: ComponentLibraryRepository = ComponentLibraryRepository(),
) : ViewModel() {
    private val repo = app.repository
    private val _state = MutableStateFlow(LibraryUiState())
    val state: StateFlow<LibraryUiState> = _state.asStateFlow()

    init { load() }

    fun load() {
        _state.value = _state.value.copy(loading = true, error = null)
        viewModelScope.launch {
            runCatching { libraryRepo.fetchAll() }
                .onSuccess { _state.value = _state.value.copy(loading = false, items = it) }
                .onFailure { _state.value = _state.value.copy(loading = false, error = it.message ?: "Error") }
        }
    }

    fun refresh() = load()
    fun setQuery(q: String) { _state.value = _state.value.copy(query = q) }

    /** Adds the chosen component as a load. Returns (via [onDone]) the system id to open, or null to just go back. */
    fun select(item: ComponentLibraryItem, targetSystemId: String?, onDone: (String?) -> Unit) {
        viewModelScope.launch {
            val systemId: String
            val createdNewSystem: Boolean
            if (targetSystemId != null) {
                systemId = targetSystemId
                createdNewSystem = false
            } else {
                val name = repo.uniqueSystemName("New System")
                val system = ElectricalSystem(name = name, iconName = SystemIconMapper.iconFor(name), colorName = SystemIconMapper.colorOptions.random())
                repo.upsertSystem(system)
                Analytics.log("System Created", mapOf("name" to name, "source" to "library"))
                systemId = system.id
                createdNewSystem = true
            }

            val baseName = item.localizedName.ifBlank { "Library Load" }
            val loadName = repo.uniqueComponentName(systemId, baseName)
            val voltage = item.displayVoltage ?: 12.0
            val power = item.watt ?: (item.current?.let { it * voltage } ?: 0.0)
            val current = item.current ?: if (voltage > 0) power / voltage else 0.0
            val affiliate = item.primaryAffiliateLink

            val load = SavedLoad(
                name = loadName,
                voltage = voltage,
                current = current,
                power = power,
                length = 10.0,
                crossSection = 1.0,
                iconName = "lightbulb",
                colorName = "blue",
                isWattMode = item.watt != null,
                dutyCyclePercent = item.normalizedDutyCyclePercent ?: 100.0,
                dailyUsageHours = item.defaultDailyUsageHours ?: 1.0,
                systemId = systemId,
                remoteIconURLString = item.iconURL,
                affiliateURLString = affiliate?.url,
                affiliateCountryCode = affiliate?.country,
            )
            repo.upsertLoad(load)
            Analytics.log("Library Load Added", mapOf("id" to item.id, "name" to item.localizedName, "system" to systemId))

            onDone(if (createdNewSystem) systemId else null)
        }
    }
}
