// lib/services/notification_service.dart import 'dart:convert'; import 'dart:developer'; import 'package:wanisdriver/config/constants/app_constant.dart'; import 'package:wanisdriver/models/notification_model.dart'; import 'package:wanisdriver/models/dynamic_response.dart'; import 'package:http/http.dart' as http; import 'package:shared_preferences/shared_preferences.dart'; import '../config/api_response.dart'; import '../config/enum/action_enum.dart'; import '../config/enum/notification_status_enum.dart'; class NotificationService { String token = ''; int statusCode = -1; bool errorToken = false; /// Retrieves the authentication token from SharedPreferences. Future getToken() async { final prefs = await SharedPreferences.getInstance(); if (prefs.getString('token') == null || prefs.getString('token') == '') { prefs.setString('token', 'InvalidToken'); } if (prefs.getString('token') != null) { token = prefs.getString('token')!; } return token.toString(); } /// 1. Save a new Notification Future> saveNotification(NotificationModel notification) async { errorToken = false; statusCode = -1; await getToken(); final uri = Uri.https( url, // Ensure this is correctly set '/api/notifications', ); final response = await http.post( uri, headers: { 'Authorization': 'Bearer $token', 'Content-type': 'application/json', 'Accept': 'application/json', }, body: json.encode(notification.toJson()), ); APIResponse apiResponse = APIResponse(); apiResponse.statusCode = response.statusCode; apiResponse.dataJson = response.body; if (response.statusCode == 201) { final data = json.decode(response.body); final savedNotification = NotificationModel.fromJson(data); apiResponse.data = savedNotification; } else if (response.statusCode == 401) { errorToken = true; apiResponse.errorMessage = 'Unauthorized: Invalid or expired token'; } else { apiResponse.errorMessage = 'Failed to save notification: ${response.reasonPhrase}'; } return apiResponse; } /// 2. Update an existing Notification Future> updateNotification(int id, NotificationModel notification) async { errorToken = false; statusCode = -1; await getToken(); final uri = Uri.https( url, '/api/notifications/$id', ); final response = await http.put( uri, headers: { 'Authorization': 'Bearer $token', 'Content-type': 'application/json', 'Accept': 'application/json', }, body: json.encode(notification.toJson()), ); APIResponse apiResponse = APIResponse(); apiResponse.statusCode = response.statusCode; apiResponse.dataJson = response.body; if (response.statusCode == 200) { final data = json.decode(response.body); final updatedNotification = NotificationModel.fromJson(data); apiResponse.data = updatedNotification; } else if (response.statusCode == 401) { errorToken = true; apiResponse.errorMessage = 'Unauthorized: Invalid or expired token'; } else if (response.statusCode == 404) { apiResponse.errorMessage = 'Notification not found'; } else { apiResponse.errorMessage = 'Failed to update notification: ${response.reasonPhrase}'; } return apiResponse; } /// 3. Get all Notifications Future>> getAllNotifications() async { errorToken = false; statusCode = -1; await getToken(); final uri = Uri.https( url, '/api/notifications', ); final response = await http.get( uri, headers: { 'Authorization': 'Bearer $token', 'Accept': 'application/json', }, ); APIResponse> apiResponse = APIResponse>(); apiResponse.statusCode = response.statusCode; apiResponse.dataJson = response.body; if (response.statusCode == 200) { final data = json.decode(response.body) as List; final notifications = data.map((item) => NotificationModel.fromJson(item)).toList(); apiResponse.data = notifications; } else if (response.statusCode == 401) { errorToken = true; apiResponse.errorMessage = 'Unauthorized: Invalid or expired token'; } else { apiResponse.errorMessage = 'Failed to retrieve notifications: ${response.reasonPhrase}'; } return apiResponse; } /// 4. Update the status of a Notification Future> updateNotificationStatus(int id, NotificationStatus status) async { errorToken = false; statusCode = -1; await getToken(); final uri = Uri.https( url, '/api/notifications/$id/status', {'status': status.value}, ); final response = await http.patch( uri, headers: { 'Authorization': 'Bearer $token', 'Accept': 'application/json', }, ); APIResponse apiResponse = APIResponse(); apiResponse.statusCode = response.statusCode; apiResponse.dataJson = response.body; if (response.statusCode == 200) { final data = json.decode(response.body); final updatedNotification = NotificationModel.fromJson(data); apiResponse.data = updatedNotification; } else if (response.statusCode == 401) { errorToken = true; apiResponse.errorMessage = 'Unauthorized: Invalid or expired token'; } else if (response.statusCode == 404) { apiResponse.errorMessage = 'Notification not found'; } else { apiResponse.errorMessage = 'Failed to update notification status: ${response.reasonPhrase}'; } return apiResponse; } /// 5. Mark all Notifications as read for the authenticated user Future> readAllNotifications() async { errorToken = false; statusCode = -1; await getToken(); final uri = Uri.https( url, '/api/v1/notifications/read-all', ); final response = await http.patch( uri, headers: { 'Authorization': 'Bearer $token', 'Accept': 'application/json', }, ); // Initialize the APIResponse object APIResponse apiResponse = APIResponse(); apiResponse.statusCode = response.statusCode; if (response.statusCode == 200) { apiResponse.data = true; // Operation succeeded apiResponse.errorMessage = null; // No error } else if (response.statusCode == 401) { errorToken = true; apiResponse.data = false; // Operation failed apiResponse.errorMessage = 'Unauthorized: Invalid or expired token'; } else { apiResponse.data = false; // Operation failed apiResponse.errorMessage = 'Failed to mark all notifications as read: ${response.reasonPhrase}'; } return apiResponse; } /// 6. Get all Notifications with pagination Future> getAllPaginated(int page, int size) async { errorToken = false; statusCode = -1; // Reset statusCode await getToken(); // Ensure token is available final uri = Uri.https( url, '/api/v1/notifications/paginated', { 'page': page.toString(), 'size': size.toString(), }, ); final response = await http.get( uri, headers: { 'Authorization': 'Bearer $token', 'Accept': 'application/json', }, ); log("getAllPaginated -----> response.statusCode ${response.statusCode}"); log("getAllPaginated -----> response.body ${response.body}"); if (response.statusCode == 200) { final parsedBody = json.decode(response.body); // Directly pass the parsed JSON map to DynamicResponse.fromJson return APIResponse( statusCode: response.statusCode, data: DynamicResponse.fromJson(parsedBody), errorMessage: null, // No error if successful ); } else if (response.statusCode == 401) { errorToken = true; return APIResponse( statusCode: response.statusCode, data: null, errorMessage: 'Unauthorized: Invalid or expired token', ); } else { String errorMessage = 'Failed to retrieve paginated notifications: ${response.reasonPhrase}'; // Attempt to parse a specific error message from the body if available try { final errorParsed = json.decode(response.body); if (errorParsed != null && errorParsed['message'] != null) { errorMessage = errorParsed['message']; } } catch (e) { log("Error parsing error response body: $e"); } return APIResponse( statusCode: response.statusCode, data: null, errorMessage: errorMessage, ); } } /// 7. Get all Notifications filtered by Action with pagination Future> getAllByActionPaginated(ActionEnum action, int page, int size) async { errorToken = false; statusCode = -1; await getToken(); final uri = Uri.https( url, '/api/notifications/paginated-by-action', { 'action': action.value, 'page': page.toString(), 'size': size.toString(), }, ); final response = await http.get( uri, headers: { 'Authorization': 'Bearer $token', 'Accept': 'application/json', }, ); log("getAllByActionPaginated -----> response.statusCode ${response.statusCode}"); log("getAllByActionPaginated -----> response.body ${response.body}"); if (response.statusCode == 200) { final parsedBody = json.decode(response.body); return APIResponse( statusCode: response.statusCode, data: DynamicResponse.fromJson(parsedBody), errorMessage: null, ); } else if (response.statusCode == 401) { errorToken = true; return APIResponse( statusCode: response.statusCode, data: null, errorMessage: 'Unauthorized: Invalid or expired token', ); } else { String errorMessage = 'Failed to retrieve notifications by action: ${response.reasonPhrase}'; try { final errorParsed = json.decode(response.body); if (errorParsed != null && errorParsed['message'] != null) { errorMessage = errorParsed['message']; } } catch (e) { log("Error parsing error response body: $e"); } return APIResponse( statusCode: response.statusCode, data: null, errorMessage: errorMessage, ); } } /// 8. Get all Notifications filtered by Status with pagination Future> getAllByStatusPaginated(NotificationStatus status, int page, int size) async { errorToken = false; statusCode = -1; await getToken(); final uri = Uri.https( url, '/api/notifications/paginated-by-status', { 'status': status.value, 'page': page.toString(), 'size': size.toString(), }, ); final response = await http.get( uri, headers: { 'Authorization': 'Bearer $token', 'Accept': 'application/json', }, ); log("getAllByStatusPaginated -----> response.statusCode ${response.statusCode}"); log("getAllByStatusPaginated -----> response.body ${response.body}"); if (response.statusCode == 200) { final parsedBody = json.decode(response.body); return APIResponse( statusCode: response.statusCode, data: DynamicResponse.fromJson(parsedBody), errorMessage: null, ); } else if (response.statusCode == 401) { errorToken = true; return APIResponse( statusCode: response.statusCode, data: null, errorMessage: 'Unauthorized: Invalid or expired token', ); } else { String errorMessage = 'Failed to retrieve notifications by status: ${response.reasonPhrase}'; try { final errorParsed = json.decode(response.body); if (errorParsed != null && errorParsed['message'] != null) { errorMessage = errorParsed['message']; } } catch (e) { log("Error parsing error response body: $e"); } return APIResponse( statusCode: response.statusCode, data: null, errorMessage: errorMessage, ); } } /// 9. Get the latest Notification Future> getLastNotification() async { errorToken = false; statusCode = -1; await getToken(); final uri = Uri.https( url, '/api/notifications/latest', ); final response = await http.get( uri, headers: { 'Authorization': 'Bearer $token', 'Accept': 'application/json', }, ); APIResponse apiResponse = APIResponse(); apiResponse.statusCode = response.statusCode; apiResponse.dataJson = response.body; if (response.statusCode == 200) { final data = json.decode(response.body); final latestNotification = NotificationModel.fromJson(data); apiResponse.data = latestNotification; } else if (response.statusCode == 401) { errorToken = true; apiResponse.errorMessage = 'Unauthorized: Invalid or expired token'; } else if (response.statusCode == 404) { apiResponse.errorMessage = 'No notifications found'; } else { apiResponse.errorMessage = 'Failed to retrieve the latest notification: ${response.reasonPhrase}'; } return apiResponse; } /// 10. Delete a Notification by ID Future> deleteNotification(int id) async { errorToken = false; statusCode = -1; await getToken(); final uri = Uri.https( url, '/api/notifications/$id', ); final response = await http.delete( uri, headers: { 'Authorization': 'Bearer $token', 'Accept': 'application/json', }, ); APIResponse apiResponse = APIResponse(); apiResponse.statusCode = response.statusCode; apiResponse.dataJson = response.body; if (response.statusCode == 200) { apiResponse.data = 'Notification deleted successfully.'; } else if (response.statusCode == 401) { errorToken = true; apiResponse.errorMessage = 'Unauthorized: Invalid or expired token'; } else if (response.statusCode == 404) { apiResponse.errorMessage = 'Notification not found'; } else { apiResponse.errorMessage = 'Failed to delete notification: ${response.reasonPhrase}'; } return apiResponse; } }