import 'package:dio/dio.dart'; import '../../../../core/network/api_problem.dart'; import '../../../../data/network/api_client.dart'; import '../models/profile_settings.dart'; class ProfileApi { const ProfileApi({required ApiClient apiClient}) : _apiClient = apiClient; final ApiClient _apiClient; Future getProfile() async { final json = await _apiClient.getJson('/api/v1/users/me/profile'); return _toSettings(json); } Future updateProfile(ProfileSettingsV1 next) async { final payload = { 'display_name': next.displayName, 'bio': next.bio, if (next.avatarPath != null && next.avatarPath!.isNotEmpty) 'avatar_path': next.avatarPath, }; final json = await _apiClient.rawDio.patch>( '/api/v1/users/me/profile', data: payload, ); final data = json.data; if (data is! Map) { throw ApiProblem( status: 502, title: 'Invalid profile payload', detail: 'Expected profile response object', ); } return _toSettings(data); } Future updateSettings(ProfileSettingsV1 settings) async { final payload = { 'settings': { 'version': settings.version, 'preferences': { 'interface_language': settings.preferences.interfaceLanguage, 'ai_language': settings.preferences.aiLanguage, 'timezone': settings.preferences.timezone, 'country': settings.preferences.country, }, 'privacy': settings.privacy, 'notification': { 'allow_notifications': settings.notification.allowNotifications, 'allow_vibration': settings.notification.allowVibration, }, }, }; final json = await _apiClient.rawDio.patch>( '/api/v1/users/me/settings', data: payload, ); final data = json.data; if (data is! Map) { throw ApiProblem( status: 502, title: 'Invalid settings payload', detail: 'Expected settings response object', ); } return _toSettings(data); } Future uploadAvatar(String filePath) async { final formData = FormData.fromMap({ 'file': await MultipartFile.fromFile(filePath), }); final response = await _apiClient.rawDio.post>( '/api/v1/users/me/avatar', data: formData, ); final data = response.data; if (data is! Map) { throw ApiProblem( status: 502, title: 'Invalid profile payload', detail: 'Expected profile response object', ); } return _toSettings(data); } Future deleteAccount() async { await _apiClient.deleteNoContent('/api/v1/users/me'); } ProfileSettingsV1 _toSettings(Map json) { final settingsRaw = json['settings']; final preferencesRaw = settingsRaw is Map ? settingsRaw['preferences'] : null; final preferences = preferencesRaw is Map ? PreferenceSettings( interfaceLanguage: (preferencesRaw['interface_language'] as String?) ?? 'zh-CN', aiLanguage: (preferencesRaw['ai_language'] as String?) ?? 'zh-CN', timezone: (preferencesRaw['timezone'] as String?) ?? 'Asia/Shanghai', country: (preferencesRaw['country'] as String?) ?? 'CN', ) : const PreferenceSettings(); final notificationRaw = settingsRaw is Map ? settingsRaw['notification'] : null; final notification = notificationRaw is Map ? NotificationSettings( allowNotifications: (notificationRaw['allow_notifications'] as bool? ?? true), allowVibration: (notificationRaw['allow_vibration'] as bool? ?? true), ) : const NotificationSettings(); return ProfileSettingsV1( displayName: (json['display_name'] as String?) ?? '', bio: (json['bio'] as String?) ?? '', avatarPath: json['avatar_path'] as String?, avatarUrl: json['avatar_url'] as String?, preferences: preferences, privacy: settingsRaw is Map ? (settingsRaw['privacy'] as Map? ?? const {}) : const {}, notification: notification, ); } }