wesal/frontend/lib/services/user_service.dart
2025-08-03 10:06:34 +03:00

258 lines
8.1 KiB
Dart

import 'dart:convert';
import '../constants/api_constants.dart';
import 'http_service.dart';
import 'auth_service.dart';
import 'cache_service.dart';
class UserService {
static bool _pollingStarted = false;
/// Get current user with caching - returns cached data if available and fresh
static Future<Map<String, dynamic>> getCurrentUser({bool forceRefresh = false}) async {
// Return cached data if available and not forcing refresh
if (!forceRefresh) {
final cached = CacheService.getCached<Map<String, dynamic>>(CacheService.userProfileKey);
if (cached != null && !CacheService.isCacheExpired(CacheService.userProfileKey, CacheService.userCacheDuration)) {
return {
'success': true,
'message': 'Loaded from cache',
'data': cached,
};
}
// Return stale data while fetching fresh data in background
final stale = CacheService.getCachedStale<Map<String, dynamic>>(CacheService.userProfileKey);
if (stale != null && !forceRefresh) {
// Trigger background refresh
_fetchAndCacheUser();
return {
'success': true,
'message': 'Loaded from cache (refreshing in background)',
'data': stale,
};
}
// Also check AuthService cache for backward compatibility
final authCachedData = await AuthService.getCachedUserData();
if (authCachedData != null) {
// Update our cache with auth service data
CacheService.setCached(CacheService.userProfileKey, authCachedData);
return {'success': true, 'data': authCachedData};
}
}
// Fetch fresh data
return await _fetchAndCacheUser();
}
static Future<Map<String, dynamic>> _fetchAndCacheUser([bool fromPolling = false]) async {
try {
final response = await HttpService.get(ApiConstants.getUserEndpoint);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
// Only cache when not called from polling to prevent conflicts
if (!fromPolling) {
CacheService.setCached(CacheService.userProfileKey, data);
}
// Also save to AuthService for backward compatibility
await AuthService.saveUserData(data);
return {
'success': true,
'data': data,
'message': '',
};
} else if (response.statusCode == 401 || response.statusCode == 403) {
await AuthService.handleAuthenticationError();
return {
'success': false,
'message': 'Session expired. Please login again.',
'data': null,
};
} else {
return {
'success': false,
'message': 'Server error (${response.statusCode})',
'data': null,
};
}
} catch (e) {
print('Error fetching user: $e');
return {
'success': false,
'message': 'Network error. Please check your connection.',
'data': null,
};
}
}
/// Start background polling for user profile
static void startPolling() {
_pollingStarted = true;
CacheService.startPolling(
CacheService.userProfileKey,
() => _fetchAndCacheUser(true), // Mark as from polling
CacheService.userPollingInterval,
CacheService.userCacheDuration,
);
}
/// Stop background polling for user profile
static void stopPolling() {
CacheService.stopPolling(CacheService.userProfileKey);
_pollingStarted = false;
}
/// Get user profile stream for real-time updates
static Stream<Map<String, dynamic>> getUserStream() {
return CacheService.getStream<Map<String, dynamic>>(CacheService.userProfileKey);
}
/// Force notify stream with current cached data (useful for initial stream setup)
static void notifyStreamWithCurrentData() {
final cached = CacheService.getCachedStale<Map<String, dynamic>>(
CacheService.userProfileKey,
);
if (cached != null) {
// Re-notify the stream with current data
CacheService.notifyStreamListeners<Map<String, dynamic>>(
CacheService.userProfileKey,
cached,
);
}
}
/// Check if polling is active
static bool get isPollingActive => _pollingStarted;
/// Invalidate user cache (useful after updating profile)
static void invalidateCache() {
CacheService.clearCache(CacheService.userProfileKey);
}
static Future<Map<String, dynamic>> updateFCMToken(String fcmToken) async {
try {
final response = await HttpService.post(ApiConstants.updateUserEndpoint, {
'fcmToken': fcmToken,
});
if (response.statusCode == 200) {
return {'success': true};
} else if (response.statusCode == 401) {
return {
'success': false,
'message': 'Session expired. Please login again.',
};
} else if (response.statusCode == 403) {
return {
'success': false,
'message': 'Access denied. Invalid credentials.',
};
} else {
return {
'success': false,
'message': 'Server error (${response.statusCode})',
};
}
} catch (e) {
print('Error updating FCM token: $e');
return {
'success': false,
'message': 'Network error. Please check your connection.',
};
}
}
static Future<Map<String, dynamic>> updateUser({
String? displayName,
String? username,
String? avatar,
}) async {
try {
final Map<String, dynamic> updateData = {};
if (displayName != null) updateData['displayName'] = displayName;
if (username != null) updateData['username'] = username;
if (avatar != null) updateData['avatar'] = avatar;
final response = await HttpService.post(ApiConstants.updateUserEndpoint, updateData);
if (response.statusCode == 200) {
final responseData = jsonDecode(response.body);
if (responseData['status'] == true) {
// Update cache with new user data
CacheService.setCached(CacheService.userProfileKey, responseData['data']);
// Also save to AuthService for backward compatibility
await AuthService.saveUserData(responseData['data']);
return {
'success': true,
'message': responseData['message'] ?? 'Profile updated successfully',
'data': responseData['data'],
};
} else {
return {
'success': false,
'message': responseData['message'] ?? 'Failed to update profile',
};
}
} else if (response.statusCode == 401 || response.statusCode == 403) {
await AuthService.handleAuthenticationError();
return {
'success': false,
'message': 'Session expired. Please login again.',
};
} else {
final responseData = jsonDecode(response.body);
return {
'success': false,
'message': responseData['message'] ?? 'Server error (${response.statusCode})',
};
}
} catch (e) {
print('Error updating user: $e');
return {
'success': false,
'message': 'Network error. Please check your connection.',
};
}
}
static Future<Map<String, dynamic>> createUser({
required String email,
required String password,
required String displayName,
}) async {
try {
final response = await HttpService.post('/admin/createUser', {
'email': email,
'password': password,
'displayName': displayName,
});
final responseData = jsonDecode(response.body);
if (response.statusCode == 200 || response.statusCode == 201) {
return {
'success': responseData['status'] ?? false,
'message': responseData['message'] ?? 'User created successfully',
'data': responseData['data'],
};
} else {
return {
'success': false,
'message': responseData['message'] ?? 'Failed to create user',
};
}
} catch (e) {
print('Error creating user: $e');
return {
'success': false,
'message': 'Network error. Please check your connection.',
};
}
}
}