// lib/remote/auth_client.dart import 'dart:convert'; import 'package:http/http.dart' as http; class RemoteAuth { final Uri base; final String email; final String password; String? _token; RemoteAuth({ required String baseUrl, required this.email, required this.password, }) : base = Uri.parse(baseUrl.endsWith('/') ? baseUrl : '$baseUrl/'); Uri get _loginUri => base.resolve('auth/login'); /// Esegue il login e memorizza il token Future login() async { print('POST URL: $_loginUri'); print('Body: ${json.encode({'email': email, 'password': password})}'); final res = await http.post( _loginUri, headers: {'Content-Type': 'application/json'}, body: json.encode({'email': email, 'password': password}), ).timeout(const Duration(seconds: 20)); print('Status: ${res.statusCode}'); print('Response: ${utf8.decode(res.bodyBytes)}'); if (res.statusCode != 200) { throw Exception('Login fallito: HTTP ${res.statusCode} ${res.reasonPhrase}'); } final map = json.decode(utf8.decode(res.bodyBytes)) as Map; final token = map['token'] as String?; if (token == null || token.isEmpty) { throw Exception('Login fallito: token assente nella risposta'); } _token = token; return token; } /// Ritorna gli headers con Bearer, lanciando il login se necessario Future> authHeaders() async { _token ??= await login(); return {'Authorization': 'Bearer $_token'}; } /// Invalida il token (es. dopo 401) e riesegue il login Future> refreshAndHeaders() async { _token = null; return await authHeaders(); } }