import '../../../core/api/api_client.dart'; import 'models/place_model.dart'; import 'models/route_model.dart'; /// نقطة وصول وحيدة لبيانات الخرائط — كل نداء يمرّ عبر سيرفرنا /// (docs/23 §4) لحماية المفتاح وتفعيل التخزين المؤقت على Redis. class MapsRepository { final ApiClient _api; MapsRepository(this._api); /// بحث مكاني — يمرّ عبر `GET /maps/geocode`. Future> autocomplete(String query) async { if (query.trim().length < 2) return []; final r = await _api.dio.get( '/maps/geocode', queryParameters: {'q': query.trim(), 'country': 'JO'}, ); final items = (r.data['items'] ?? r.data ?? []) as List; return items .map((e) => PlaceModel.fromJson(e as Map)) .toList(); } /// بحث حرّ (geocode). Future> geocode(String query) async { if (query.trim().length < 2) return []; final r = await _api.dio.get( '/maps/geocode', queryParameters: {'q': query.trim(), 'country': 'JO'}, ); final items = (r.data['items'] ?? r.data ?? []) as List; return items .map((e) => PlaceModel.fromJson(e as Map)) .toList(); } /// تفكيك عنوان عكسي (إحداثيات → نص). Future reverseGeocode(double lat, double lng) async { final r = await _api.dio.get( '/maps/reverse', queryParameters: {'lat': lat, 'lng': lng}, ); final j = r.data as Map; return PlaceModel.fromJson({ 'name': j['formattedAddress'] ?? '', 'address': j['formattedAddress'], 'lat': lat, 'lng': lng, }); } /// تفاصيل مكان بالـ placeId — يمرّ عبر geocode. Future placeDetails(String placeId) async { final r = await _api.dio.get( '/maps/geocode', queryParameters: {'q': placeId, 'country': 'JO'}, ); final items = (r.data['items'] ?? r.data ?? []) as List; if (items.isEmpty) { throw Exception('Place not found'); } return PlaceModel.fromJson(items.first as Map); } /// حساب المسار بين نقطتين. Future getRoute({ required double fromLat, required double fromLng, required double toLat, required double toLng, }) async { final r = await _api.dio.get( '/maps/route', queryParameters: { 'fromLat': fromLat, 'fromLng': fromLng, 'toLat': toLat, 'toLng': toLng, }, ); return RouteModel.fromJson(r.data as Map); } }