import 'package:get/get.dart'; import 'package:http/http.dart' as http; import 'package:on_field_work/helpers/services/app_logger.dart'; import 'package:on_field_work/model/user_permission.dart'; import 'package:on_field_work/model/employees/employee_info.dart'; import 'package:on_field_work/model/projects_model.dart'; import 'package:on_field_work/helpers/services/storage/local_storage.dart'; import 'package:on_field_work/helpers/services/auth_service.dart'; import 'package:on_field_work/helpers/services/api_endpoints.dart'; import 'package:on_field_work/helpers/utils/encryption_helper.dart'; class PermissionService { static final Map> _userDataCache = {}; static const String _baseUrl = ApiEndpoints.baseUrl; static Future> fetchAllUserData( String token, { bool hasRetried = false, }) async { logSafe("Fetching user data..."); final cached = _userDataCache[token]; if (cached != null) { logSafe("User data cache hit."); return cached; } final uri = Uri.parse("$_baseUrl/user/profile"); final headers = {'Authorization': 'Bearer $token'}; try { final response = await http.get(uri, headers: headers); final statusCode = response.statusCode; if (response.body.isEmpty || response.body.trim().isEmpty) { logSafe("❌ Empty user data response — auto logout"); await _handleUnauthorized(); throw Exception("Empty user data response"); } final decrypted = decryptResponse(response.body); if (decrypted == null) { logSafe("❌ Failed to decrypt user data — auto logout", level: LogLevel.error); await _handleUnauthorized(); throw Exception("Decryption failed for user data"); } final data = decrypted is Map ? decrypted['data'] ?? decrypted : null; if (data == null || data is! Map) { logSafe("❌ Decrypted user data is invalid — auto logout", level: LogLevel.error); await _handleUnauthorized(); throw Exception("Invalid decrypted user data"); } if (statusCode == 200) { final result = { 'permissions': _parsePermissions(data['featurePermissions']), 'employeeInfo': _parseEmployeeInfo(data['employeeInfo']), 'projects': _parseProjectsInfo(data['projects']), }; _userDataCache[token] = result; logSafe("User data fetched and decrypted successfully."); return result; } if (statusCode == 401 && !hasRetried) { logSafe("Unauthorized. Attempting token refresh...", level: LogLevel.warning); final refreshed = await AuthService.refreshToken(); if (refreshed) { final newToken = await LocalStorage.getJwtToken(); if (newToken != null && newToken.isNotEmpty) { return fetchAllUserData(newToken, hasRetried: true); } } await _handleUnauthorized(); logSafe("Token refresh failed. Redirecting to login.", level: LogLevel.warning); throw Exception('Unauthorized. Token refresh failed.'); } final errorMsg = data['message'] ?? 'Unknown error'; logSafe("Failed to fetch user data: $errorMsg", level: LogLevel.warning); throw Exception('Failed to fetch user data: $errorMsg'); } catch (e, stacktrace) { logSafe("Exception while fetching user data", level: LogLevel.error, error: e, stackTrace: stacktrace); rethrow; } } static Future _handleUnauthorized() async { logSafe("Clearing tokens and redirecting to login due to unauthorized access.", level: LogLevel.warning); await LocalStorage.removeToken('jwt_token'); await LocalStorage.removeToken('refresh_token'); await LocalStorage.setLoggedInUser(false); Get.offAllNamed('/auth/login-option'); } static List _parsePermissions(List? permissions) { logSafe("Parsing user permissions..."); if (permissions == null) return []; return permissions.map((perm) => UserPermission.fromJson({'id': perm})).toList(); } static EmployeeInfo _parseEmployeeInfo(Map? data) { logSafe("Parsing employee info..."); if (data == null) throw Exception("Employee data missing"); return EmployeeInfo.fromJson(data); } static List _parseProjectsInfo(List? projects) { logSafe("Parsing projects info..."); if (projects == null) return []; return projects.map((proj) => ProjectInfo.fromJson(proj)).toList(); } }