package com.applemand.zmanim.core.location

import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.PackageManager
import android.location.Location
import android.location.LocationManager
import androidx.core.content.ContextCompat
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.suspendCancellableCoroutine
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.coroutines.resume

/**
 * Uses platform LocationManager only — no Play Services, no FusedLocationProvider.
 * Returns the most recent known fix (GPS or network provider) or null.
 * Real-time updates intentionally not exposed — the calendar does not need sub-minute precision.
 */
@Singleton
class GpsProvider @Inject constructor(
    @ApplicationContext private val context: Context,
) {
    fun hasPermission(): Boolean =
        ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) ==
                PackageManager.PERMISSION_GRANTED

    @SuppressLint("MissingPermission")
    suspend fun lastKnown(): Coord? = suspendCancellableCoroutine { cont ->
        if (!hasPermission()) {
            cont.resume(null); return@suspendCancellableCoroutine
        }
        val lm = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
        val providers = listOf(
            LocationManager.GPS_PROVIDER,
            LocationManager.NETWORK_PROVIDER,
            LocationManager.PASSIVE_PROVIDER,
        ).filter { runCatching { lm.isProviderEnabled(it) }.getOrDefault(false) }

        var best: Location? = null
        for (p in providers) {
            val fix = runCatching { lm.getLastKnownLocation(p) }.getOrNull() ?: continue
            if (best == null || fix.time > best!!.time) best = fix
        }
        cont.resume(best?.let {
            Coord(
                lat = it.latitude,
                lng = it.longitude,
                altitudeMeters = if (it.hasAltitude()) it.altitude else null,
            )
        })
    }
}

/**
 * `altitudeMeters` is the GPS-reported altitude (WGS84 ellipsoid, meters) or null
 * if the provider didn't supply it. Halachic sunrise/sunset shift by ~1 minute
 * per 100 m above sea level when the user enables elevation-aware zmanim.
 */
data class Coord(
    val lat: Double,
    val lng: Double,
    val altitudeMeters: Double? = null,
)
