package app.voltplan.cable.data

import android.content.Context
import app.voltplan.cable.data.db.CableDatabase
import app.voltplan.cable.data.model.ElectricalSystem
import app.voltplan.cable.data.model.SavedBattery
import app.voltplan.cable.data.model.SavedCharger
import app.voltplan.cable.data.model.SavedLoad
import kotlinx.coroutines.flow.Flow

/** Single point of access to the persistence layer. */
class CableRepository(context: Context) {
    private val db = CableDatabase.get(context)
    private val systemDao = db.systemDao()
    private val loadDao = db.loadDao()
    private val batteryDao = db.batteryDao()
    private val chargerDao = db.chargerDao()

    // Systems
    fun observeSystems(): Flow<List<ElectricalSystem>> = systemDao.observeAll()
    fun observeSystem(id: String): Flow<ElectricalSystem?> = systemDao.observe(id)
    suspend fun getSystem(id: String) = systemDao.get(id)
    suspend fun systemCount() = systemDao.count()
    suspend fun upsertSystem(system: ElectricalSystem) = systemDao.upsert(system)
    suspend fun deleteSystem(system: ElectricalSystem) {
        // Cascade delete children, mirroring the iOS deleteSystems behaviour.
        loadDao.deleteForSystem(system.id)
        batteryDao.deleteForSystem(system.id)
        chargerDao.deleteForSystem(system.id)
        systemDao.delete(system)
    }

    // Loads
    fun observeAllLoads(): Flow<List<SavedLoad>> = loadDao.observeAll()
    fun observeLoads(systemId: String): Flow<List<SavedLoad>> = loadDao.observeForSystem(systemId)
    suspend fun getLoad(id: String) = loadDao.get(id)
    suspend fun upsertLoad(load: SavedLoad) = loadDao.upsert(load)
    suspend fun deleteLoad(load: SavedLoad) = loadDao.delete(load)

    // Batteries
    fun observeBatteries(systemId: String): Flow<List<SavedBattery>> = batteryDao.observeForSystem(systemId)
    suspend fun getBattery(id: String) = batteryDao.get(id)
    suspend fun upsertBattery(battery: SavedBattery) = batteryDao.upsert(battery)
    suspend fun deleteBattery(battery: SavedBattery) = batteryDao.delete(battery)

    // Chargers
    fun observeChargers(systemId: String): Flow<List<SavedCharger>> = chargerDao.observeForSystem(systemId)
    suspend fun getCharger(id: String) = chargerDao.get(id)
    suspend fun upsertCharger(charger: SavedCharger) = chargerDao.upsert(charger)
    suspend fun deleteCharger(charger: SavedCharger) = chargerDao.delete(charger)

    /** Picks a unique component name within a system. Mirrors `SystemComponentsPersistence.uniqueName`. */
    suspend fun uniqueComponentName(systemId: String, baseName: String): String {
        val existing = buildSet {
            loadDao.listForSystem(systemId).forEach { add(it.name) }
            batteryDao.listForSystem(systemId).forEach { add(it.name) }
            chargerDao.listForSystem(systemId).forEach { add(it.name) }
        }
        if (baseName !in existing) return baseName
        var counter = 2
        var candidate = "$baseName $counter"
        while (candidate in existing) {
            counter++
            candidate = "$baseName $counter"
        }
        return candidate
    }

    /** Picks a unique system name. Mirrors the iOS `makeSystem` naming loop. */
    suspend fun uniqueSystemName(baseName: String): String {
        val names = systemDao.allNames().toSet()
        if (baseName !in names) return baseName
        var counter = 2
        var candidate = "$baseName $counter"
        while (candidate in names) {
            counter++
            candidate = "$baseName $counter"
        }
        return candidate
    }
}
