import 'dart:convert'; import 'package:http/http.dart' as http; import '../../config/api_config.dart'; import '../../models/user_profile.dart'; import '../../services/auth_service.dart'; import 'profile_api_exception.dart'; /// HTTP client for Postgres-backed profile API. class UserProfileRemoteStore { UserProfileRemoteStore({http.Client? client}) : _client = client ?? http.Client(); final http.Client _client; Future fetchProfile() async { final String? token = await AuthService.instance.getIdToken(); if (token == null) { return null; } final http.Response response = await _client.get( Uri.parse('$apiBaseUrl/v1/me/profile'), headers: _authHeaders(token), ); if (response.statusCode == 404) { return null; } if (response.statusCode != 200) { throw ProfileApiException(response.statusCode, response.body); } return _profileFromApi( jsonDecode(response.body) as Map, ); } Future pushProfile(UserProfile profile) async { final String? token = await AuthService.instance.getIdToken(); if (token == null) { throw StateError('Not signed in'); } final http.Response response = await _client.put( Uri.parse('$apiBaseUrl/v1/me/profile'), headers: _authHeaders(token), body: jsonEncode(profile.toApiJson()), ); if (response.statusCode == 409) { final Map body = jsonDecode(response.body) as Map; throw ProfileConflictException( _profileFromApi(body['profile'] as Map), ); } if (response.statusCode != 200) { throw ProfileApiException(response.statusCode, response.body); } return _profileFromApi( jsonDecode(response.body) as Map, ); } Map _authHeaders(String token) { return { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', 'Accept': 'application/json', }; } UserProfile _profileFromApi(Map json) { return UserProfile( firebaseUid: json['firebaseUid'] as String, email: json['email'] as String?, displayName: json['displayName'] as String?, photoUrl: json['photoUrl'] as String?, locale: json['locale'] as String? ?? 'en', timezone: json['timezone'] as String?, onboardingCompleted: json['onboardingCompleted'] as bool? ?? false, revision: (json['revision'] as num).toInt(), updatedAt: DateTime.parse(json['updatedAt'] as String).toUtc(), lastSyncedAt: DateTime.now().toUtc(), dirty: false, ); } }