import 'package:geolocator/geolocator.dart'; import 'package:geocoding/geocoding.dart' as geocoding; import 'package:hive_flutter/hive_flutter.dart'; import '../local/hive_boxes.dart'; import '../local/models/app_settings.dart'; /// Location service with GPS + fallback to last known location. class LocationService { LocationService._(); static final LocationService instance = LocationService._(); /// Request permission and get current GPS location. Future getCurrentLocation() async { bool serviceEnabled = await Geolocator.isLocationServiceEnabled(); if (!serviceEnabled) return null; LocationPermission permission = await Geolocator.checkPermission(); if (permission == LocationPermission.denied) { permission = await Geolocator.requestPermission(); if (permission == LocationPermission.denied) return null; } if (permission == LocationPermission.deniedForever) return null; try { final position = await Geolocator.getCurrentPosition( locationSettings: const LocationSettings( accuracy: LocationAccuracy.medium, timeLimit: Duration(seconds: 10), ), ); // Save to settings for fallback await _saveLastKnown(position.latitude, position.longitude); return position; } catch (_) { return null; } } /// Get last known location from Hive settings. ({double lat, double lng, String? cityName})? getLastKnownLocation() { final settingsBox = Hive.box(HiveBoxes.settings); final settings = settingsBox.get('default'); if (settings?.lastLat != null && settings?.lastLng != null) { return ( lat: settings!.lastLat!, lng: settings.lastLng!, cityName: settings.lastCityName, ); } return null; } /// Reverse geocode to get city name from coordinates. Future getCityName(double lat, double lng) async { try { final placemarks = await geocoding.placemarkFromCoordinates(lat, lng); if (placemarks.isNotEmpty) { final place = placemarks.first; final city = place.locality ?? place.subAdministrativeArea ?? 'Unknown'; final country = place.country ?? ''; return '$city, $country'; } } catch (_) { // Geocoding may fail offline — return coords } return '${lat.toStringAsFixed(2)}, ${lng.toStringAsFixed(2)}'; } /// Save last known position to Hive. Future _saveLastKnown(double lat, double lng) async { final settingsBox = Hive.box(HiveBoxes.settings); final settings = settingsBox.get('default'); if (settings != null) { settings.lastLat = lat; settings.lastLng = lng; try { settings.lastCityName = await getCityName(lat, lng); } catch (_) { // Ignore geocoding errors } await settings.save(); } } }