import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:shared_preferences/shared_preferences.dart'; import '../models/user.dart'; import 'api/api_config.dart'; import 'api/tokenService.dart'; class AuthService { static const String _currentUserKey = 'current_user'; /// Connexion de l'utilisateur /// Retourne l'utilisateur connecté avec le flag changement_mdp_obligatoire static Future login(String email, String password) async { try { final response = await http.post( Uri.parse('${ApiConfig.baseUrl}${ApiConfig.login}'), headers: ApiConfig.headers, body: jsonEncode({ 'email': email, 'password': password, }), ); if (response.statusCode == 200 || response.statusCode == 201) { final data = jsonDecode(response.body); // API renvoie access_token / refresh_token (snake_case) final accessToken = data['access_token'] as String? ?? data['accessToken'] as String?; final refreshToken = data['refresh_token'] as String? ?? data['refreshToken'] as String?; if (accessToken == null) throw Exception('Token absent dans la réponse serveur'); await TokenService.saveToken(accessToken); await TokenService.saveRefreshToken(refreshToken ?? ''); final user = await _fetchUserProfile(accessToken); // Stocker l'utilisateur en cache await _saveCurrentUser(user); return user; } else { final error = jsonDecode(response.body); throw Exception(error['message'] ?? 'Erreur de connexion'); } } catch (e) { if (e is Exception) rethrow; throw Exception('Erreur réseau: impossible de se connecter au serveur'); } } /// Récupère le profil utilisateur via /auth/me static Future _fetchUserProfile(String token) async { try { final response = await http.get( Uri.parse('${ApiConfig.baseUrl}${ApiConfig.authMe}'), headers: ApiConfig.authHeaders(token), ); if (response.statusCode == 200) { final data = jsonDecode(response.body); return AppUser.fromJson(data); } else { throw Exception('Erreur lors de la récupération du profil'); } } catch (e) { if (e is Exception) rethrow; throw Exception('Erreur réseau: impossible de récupérer le profil'); } } /// Changement de mot de passe obligatoire static Future changePasswordRequired({ required String currentPassword, required String newPassword, }) async { final token = await TokenService.getToken(); if (token == null) { throw Exception('Non authentifié'); } try { final response = await http.post( Uri.parse('${ApiConfig.baseUrl}${ApiConfig.changePasswordRequired}'), headers: ApiConfig.authHeaders(token), body: jsonEncode({ 'mot_de_passe_actuel': currentPassword, 'nouveau_mot_de_passe': newPassword, 'confirmation_mot_de_passe': newPassword, }), ); if (response.statusCode != 200 && response.statusCode != 201) { final error = jsonDecode(response.body); throw Exception(error['message'] ?? 'Erreur lors du changement de mot de passe'); } // Après le changement de MDP, rafraîchir le profil utilisateur final user = await _fetchUserProfile(token); await _saveCurrentUser(user); } catch (e) { if (e is Exception) rethrow; throw Exception('Erreur réseau: impossible de changer le mot de passe'); } } /// Déconnexion de l'utilisateur static Future logout() async { await TokenService.clearAll(); final prefs = await SharedPreferences.getInstance(); await prefs.remove(_currentUserKey); } /// Vérifie si l'utilisateur est connecté static Future isLoggedIn() async { final token = await TokenService.getToken(); return token != null; } /// Récupère l'utilisateur connecté depuis le cache static Future getCurrentUser() async { final prefs = await SharedPreferences.getInstance(); final userJson = prefs.getString(_currentUserKey); if (userJson != null) { return AppUser.fromJson(jsonDecode(userJson)); } return null; } /// Sauvegarde l'utilisateur actuel en cache static Future _saveCurrentUser(AppUser user) async { final prefs = await SharedPreferences.getInstance(); await prefs.setString(_currentUserKey, jsonEncode(user.toJson())); } /// Rafraîchit le profil utilisateur depuis l'API static Future refreshCurrentUser() async { final token = await TokenService.getToken(); if (token == null) return null; try { final user = await _fetchUserProfile(token); await _saveCurrentUser(user); return user; } catch (e) { return null; } } }