package com.applemand.zmanim.feature.locationpicker

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.applemand.zmanim.core.location.CandleLightingDefaults
import com.applemand.zmanim.core.location.CityEntity
import com.applemand.zmanim.core.location.GpsProvider
import com.applemand.zmanim.core.location.LocationRepository
import com.applemand.zmanim.core.location.TimezoneResolver
import com.applemand.zmanim.core.settings.SettingsRepository
import com.applemand.zmanim.core.settings.proto.Location
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.launch
import javax.inject.Inject

data class LocationPickerState(
    val query: String = "",
    val results: List<CityEntity> = emptyList(),
    val gpsBusy: Boolean = false,
    val error: String? = null,
)

@OptIn(FlowPreview::class)
@HiltViewModel
class LocationPickerViewModel @Inject constructor(
    private val repo: LocationRepository,
    private val gps: GpsProvider,
    private val settings: SettingsRepository,
    private val tzResolver: TimezoneResolver,
) : ViewModel() {

    private val _state = MutableStateFlow(LocationPickerState())
    val state: StateFlow<LocationPickerState> = _state.asStateFlow()

    init {
        viewModelScope.launch {
            _state.value = _state.value.copy(results = repo.search("", 50))
        }
    }

    fun setQuery(q: String) {
        _state.value = _state.value.copy(query = q)
        viewModelScope.launch {
            val r = repo.search(q)
            _state.value = _state.value.copy(results = r)
        }
    }

    fun useGps() {
        _state.value = _state.value.copy(gpsBusy = true, error = null)
        viewModelScope.launch {
            val coord = gps.lastKnown()
            if (coord == null) {
                _state.value = _state.value.copy(gpsBusy = false, error = "No recent GPS fix")
                return@launch
            }
            val city = repo.nearest(coord.lat, coord.lng)
            if (city != null) {
                applyCity(city, gpsAltitudeMeters = coord.altitudeMeters)
            } else {
                val tz = tzResolver.resolve(coord.lat, coord.lng) ?: java.util.TimeZone.getDefault().id
                settings.setLocation(
                    Location.newBuilder()
                        .setNameEn("Current location")
                        .setLat(coord.lat).setLng(coord.lng).setTzid(tz)
                        .setElevationM(coord.altitudeMeters ?: 0.0)
                        .build()
                )
            }
            _state.value = _state.value.copy(gpsBusy = false)
        }
    }

    fun pick(city: CityEntity) {
        viewModelScope.launch { applyCity(city, gpsAltitudeMeters = null) }
    }

    private suspend fun applyCity(city: CityEntity, gpsAltitudeMeters: Double?) {
        // Prefer GPS altitude over DB elevation when the GPS fix supplied one —
        // DB elevation is a DEM lookup at city centroid (often zero or coarse).
        val elevation = gpsAltitudeMeters ?: city.elevationM
        settings.setLocation(
            Location.newBuilder()
                .setId(city.id)
                .setNameEn(city.nameEn)
                .setNameHe(city.nameHe ?: "")
                .setLat(city.lat)
                .setLng(city.lng)
                .setTzid(city.tzid)
                .setCountry(city.country)
                .setAdmin(city.admin1 ?: "")
                .setElevationM(elevation)
                .build()
        )
        // Apply the community's established candle-lighting minhag if known.
        // User can still override via Settings → "Candle lighting" slider.
        settings.setCandleLightingMinutes(
            CandleLightingDefaults.minutesFor(city.id, city.country)
        )
    }
}
