import 'dart:convert'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:http/http.dart' as http; import 'package:em2rp/config/api_config.dart'; import 'package:em2rp/models/depot_model.dart'; import 'package:em2rp/models/route_result_model.dart'; import 'package:em2rp/utils/debug_log.dart'; class TravelService { final FirebaseFirestore _db = FirebaseFirestore.instance; // ─── Auth token ─────────────────────────────────────────── Future _getToken() async { final user = FirebaseAuth.instance.currentUser; return await user?.getIdToken(); } Future> _headers() async { final token = await _getToken(); return { 'Content-Type': 'application/json', if (token != null) 'Authorization': 'Bearer $token', }; } // ─── Autocomplétion d'adresses ──────────────────────────── Future> autocompleteAddress(String query) async { if (query.trim().length < 3) return []; try { final headers = await _headers(); final url = Uri.parse('${ApiConfig.baseUrl}/googleMapsAutocomplete'); final response = await http.post( url, headers: headers, body: jsonEncode({'data': {'query': query}}), ); if (response.statusCode != 200) return []; final data = jsonDecode(response.body) as Map; final predictions = data['predictions'] as List? ?? []; return predictions .map((p) => (p['description'] ?? '').toString()) .where((s) => s.isNotEmpty) .toList(); } catch (e) { DebugLog.error('[Travel] autocompleteAddress error', e); return []; } } // ─── Calcul des itinéraires ─────────────────────────────── Future> computeRoutes({ required String origin, required String destination, int vehicleTollCategory = 2, }) async { try { final headers = await _headers(); final url = Uri.parse('${ApiConfig.baseUrl}/googleMapsComputeRoute'); final response = await http.post( url, headers: headers, body: jsonEncode({ 'data': { 'origin': origin, 'destination': destination, 'vehicleTollCategory': vehicleTollCategory, }, }), ); if (response.statusCode != 200) { final err = jsonDecode(response.body); throw Exception('googleMapsComputeRoute: ${err['error']}'); } final data = jsonDecode(response.body) as Map; final routes = data['routes'] as List? ?? []; return routes .map((r) => RouteResult.fromMap(r as Map)) .toList(); } catch (e) { DebugLog.error('[Travel] computeRoutes error', e); rethrow; } } // ─── Prix des carburants ─────────────────────────────────── Future getFuelPrices() async { try { final doc = await _db.collection('app_config').doc('fuel_prices').get(); if (!doc.exists) return const FuelPrices(); return FuelPrices.fromMap(doc.data()!); } catch (e) { return const FuelPrices(); } } Future saveFuelPrices(FuelPrices prices) async { await _db.collection('app_config').doc('fuel_prices').set(prices.toMap()); } // ─── Dépôts ─────────────────────────────────────────────── Future> getDepots() async { final snap = await _db.collection('depots').orderBy('name').get(); return snap.docs.map((d) => DepotModel.fromFirestore(d)).toList(); } Stream> watchDepots() { return _db .collection('depots') .orderBy('name') .snapshots() .map((s) => s.docs.map((d) => DepotModel.fromFirestore(d)).toList()); } Future addDepot(DepotModel depot) async { final ref = await _db.collection('depots').add(depot.toMap()); return ref.id; } Future updateDepot(DepotModel depot) async { final map = depot.toMap(); map.remove('createdAt'); await _db.collection('depots').doc(depot.id).update(map); } Future deleteDepot(String depotId) async { await _db.collection('depots').doc(depotId).delete(); } } /// Instance singleton final travelService = TravelService();