// lib/providers/notification_provider.dart import 'dart:developer'; import 'package:wanisdriver/services/auth_services.dart'; import 'package:flutter/material.dart'; import 'package:wanisdriver/models/notification_model.dart'; import 'package:wanisdriver/models/dynamic_response.dart'; import '../config/api_response.dart'; import '../config/enum/action_enum.dart'; import '../config/enum/notification_status_enum.dart'; import '../services/notificaitons_services.dart'; class NotificationProvider with ChangeNotifier { final NotificationService _notificationService = NotificationService(); final AuthServices _authService = AuthServices(); List _notifications = []; bool _isLoading = false; bool _isRefreshing = false; bool _hasMore = true; int _currentPage = 0; int _totalPages = 1; List get notifications => _notifications; bool get isLoading => _isLoading; bool get isRefreshing => _isRefreshing; bool get hasMore => _hasMore; /// Fetches notifications with optional filtering by action or status. Future fetchNotifications({ int page = 0, int size = 10, ActionEnum? action, NotificationStatus? status, String? date, }) async { _isLoading = true; if (page == 0) { _isRefreshing = true; log("[FetchNotifications] Starting refresh fetch"); } notifyListeners(); APIResponse response; try { log("[FetchNotifications] Fetching with params: page=$page, size=$size, status=$status"); if (action != null) { response = await _notificationService.getAllByActionPaginated(action, page, size); } else if (status != null) { response = await _notificationService.getAllByStatusPaginated(status, page, size); } else { response = await _notificationService.getAllPaginated(page, size); } log("[FetchNotifications] Response status: ${response.statusCode}"); if (response.isValidResponse) { final contentList = (response.data as DynamicResponse).content; final newNotifications = contentList.map((item) => NotificationModel.fromJson(item)).toList(); log("[FetchNotifications] Fetched ${newNotifications.length} notifications"); if (page == 0) { _notifications = newNotifications; log("[FetchNotifications] Replacing notifications list"); } else { _notifications.addAll(newNotifications); log("[FetchNotifications] Appending notifications, total now: ${_notifications.length}"); } _currentPage = (response.data as DynamicResponse).currentPage; _totalPages = (response.data as DynamicResponse).totalPages; _hasMore = _currentPage < _totalPages - 1; log("[FetchNotifications] Page $_currentPage of $_totalPages. hasMore: $_hasMore"); } else { log("[FetchNotifications] Invalid response. StatusCode: ${response.statusCode}, Error: ${response.errorMessage}"); if (response.statusCode == 401) { log("[FetchNotifications] Attempting token refresh..."); APIResponse refreshResponse = await _authService.refreshToken(); if (refreshResponse.isValidResponse && refreshResponse.data != null) { log("[FetchNotifications] Token refresh successful. Retrying fetch..."); if (action != null) { response = await _notificationService.getAllByActionPaginated(action, page, size); } else if (status != null) { response = await _notificationService.getAllByStatusPaginated(status, page, size); } else { response = await _notificationService.getAllPaginated(page, size); } if (response.isValidResponse) { final contentList = (response.data as DynamicResponse).content; final newNotifications = contentList.map((item) => NotificationModel.fromJson(item)).toList(); log("[FetchNotifications] Fetched ${newNotifications.length} notifications after token refresh"); if (page == 0) { _notifications = newNotifications; } else { _notifications.addAll(newNotifications); } _currentPage = (response.data as DynamicResponse).currentPage; _totalPages = (response.data as DynamicResponse).totalPages; _hasMore = _currentPage < _totalPages - 1; } else { log("[FetchNotifications] Failed after retry. Error: ${response.errorMessage}"); _hasMore = false; } } else { log("[FetchNotifications] Token refresh failed: ${refreshResponse.errorMessage}"); _hasMore = false; } } else { _hasMore = false; } } } catch (e, stackTrace) { log("[FetchNotifications] Exception occurred: $e", stackTrace: stackTrace); _hasMore = false; } finally { _isLoading = false; _isRefreshing = false; notifyListeners(); log("[FetchNotifications] Done. isLoading: $_isLoading, isRefreshing: $_isRefreshing"); } } /// Loads more notifications for pagination. Future loadMoreNotifications({ ActionEnum? action, NotificationStatus? status, String? date, }) async { if (_hasMore && !_isLoading) { await fetchNotifications( page: _currentPage + 1, size: 10, action: action, status: status, date: date, ); } } /// Refreshes the notifications list. Future refreshNotifications({ ActionEnum? action, NotificationStatus? status, String? date, }) async { await fetchNotifications( page: 0, size: 10, action: action, status: status, date: date, ); } /// Saves a new notification. Future> saveNotification(NotificationModel notification) async { APIResponse response = await _notificationService.saveNotification(notification); if (response.isValidResponse && response.data != null) { _notifications.insert(0, response.data!); // Add to the beginning of the list notifyListeners(); } return response; } /// Updates an existing notification. Future> updateNotification(int id, NotificationModel notification) async { APIResponse response = await _notificationService.updateNotification(id, notification); if (response.isValidResponse && response.data != null) { int index = _notifications.indexWhere((n) => n.id == id); if (index != -1) { _notifications[index] = response.data!; notifyListeners(); } } return response; } /// Updates the status of a notification. Future> updateNotificationStatus(int id, NotificationStatus status) async { APIResponse response = await _notificationService.updateNotificationStatus(id, status); if (response.isValidResponse && response.data != null) { int index = _notifications.indexWhere((n) => n.id == id); if (index != -1) { _notifications[index] = _notifications[index].copyWith(status: status); notifyListeners(); } } return response; } /// Marks all notifications as read. Future> markAllAsRead() async { APIResponse response = await _notificationService.readAllNotifications(); if (response.isValidResponse) { _notifications = _notifications.map((notification) { return notification.copyWith(status: NotificationStatus.READ); }).toList(); notifyListeners(); } return response; } /// Retrieves the latest notification. Future> getLatestNotification() async { APIResponse response = await _notificationService.getLastNotification(); if (response.isValidResponse && response.data != null) { _notifications.insert(0, response.data!); // Add to the beginning of the list notifyListeners(); } return response; } /// Deletes a notification by ID. Future> deleteNotification(int id) async { APIResponse response = await _notificationService.deleteNotification(id); if (response.isValidResponse) { _notifications.removeWhere((n) => n.id == id); notifyListeners(); } return response; } }