import 'package:riverpod_annotation/riverpod_annotation.dart'; import '../../features/products/presentation/providers/products_provider.dart'; import '../../features/categories/presentation/providers/categories_provider.dart'; import '../../features/settings/presentation/providers/settings_provider.dart'; import 'network_info_provider.dart'; part 'sync_status_provider.g.dart'; /// Sync status provider - manages data synchronization state @riverpod class SyncStatus extends _$SyncStatus { @override Future build() async { // Initialize with idle state return const SyncResult( status: SyncState.idle, lastSyncTime: null, message: 'Ready to sync', ); } /// Perform full sync of all data Future syncAll() async { // Check network connectivity first final isConnected = await ref.read(isConnectedProvider.future); if (!isConnected) { state = const AsyncValue.data( SyncResult( status: SyncState.offline, lastSyncTime: null, message: 'No internet connection', ), ); return; } // Start sync state = const AsyncValue.data( SyncResult( status: SyncState.syncing, lastSyncTime: null, message: 'Syncing data...', ), ); try { // Sync categories first (products depend on categories) await ref.read(categoriesProvider.notifier).refresh(); // Then sync products await ref.read(productsProvider.notifier).refresh(); // Update last sync time in settings await ref.read(settingsProvider.notifier).updateLastSyncTime(); // Sync completed successfully state = AsyncValue.data( SyncResult( status: SyncState.success, lastSyncTime: DateTime.now(), message: 'Sync completed successfully', ), ); } catch (error, stackTrace) { // Sync failed state = AsyncValue.data( SyncResult( status: SyncState.failed, lastSyncTime: null, message: 'Sync failed: ${error.toString()}', error: error, ), ); // Also set error state for proper error handling state = AsyncValue.error(error, stackTrace); } } /// Sync only products Future syncProducts() async { final isConnected = await ref.read(isConnectedProvider.future); if (!isConnected) { state = const AsyncValue.data( SyncResult( status: SyncState.offline, lastSyncTime: null, message: 'No internet connection', ), ); return; } state = const AsyncValue.data( SyncResult( status: SyncState.syncing, lastSyncTime: null, message: 'Syncing products...', ), ); try { await ref.read(productsProvider.notifier).refresh(); await ref.read(settingsProvider.notifier).updateLastSyncTime(); state = AsyncValue.data( SyncResult( status: SyncState.success, lastSyncTime: DateTime.now(), message: 'Products synced successfully', ), ); } catch (error, stackTrace) { state = AsyncValue.data( SyncResult( status: SyncState.failed, lastSyncTime: null, message: 'Product sync failed: ${error.toString()}', error: error, ), ); state = AsyncValue.error(error, stackTrace); } } /// Sync only categories Future syncCategories() async { final isConnected = await ref.read(isConnectedProvider.future); if (!isConnected) { state = const AsyncValue.data( SyncResult( status: SyncState.offline, lastSyncTime: null, message: 'No internet connection', ), ); return; } state = const AsyncValue.data( SyncResult( status: SyncState.syncing, lastSyncTime: null, message: 'Syncing categories...', ), ); try { await ref.read(categoriesProvider.notifier).refresh(); await ref.read(settingsProvider.notifier).updateLastSyncTime(); state = AsyncValue.data( SyncResult( status: SyncState.success, lastSyncTime: DateTime.now(), message: 'Categories synced successfully', ), ); } catch (error, stackTrace) { state = AsyncValue.data( SyncResult( status: SyncState.failed, lastSyncTime: null, message: 'Category sync failed: ${error.toString()}', error: error, ), ); state = AsyncValue.error(error, stackTrace); } } /// Reset sync status to idle void resetStatus() { state = const AsyncValue.data( SyncResult( status: SyncState.idle, lastSyncTime: null, message: 'Ready to sync', ), ); } } /// Sync state enum enum SyncState { idle, syncing, success, failed, offline, } /// Sync result model class SyncResult { final SyncState status; final DateTime? lastSyncTime; final String message; final Object? error; const SyncResult({ required this.status, required this.lastSyncTime, required this.message, this.error, }); bool get isSyncing => status == SyncState.syncing; bool get isSuccess => status == SyncState.success; bool get isFailed => status == SyncState.failed; bool get isOffline => status == SyncState.offline; bool get isIdle => status == SyncState.idle; } /// Provider for last sync time from settings @riverpod DateTime? lastSyncTime(Ref ref) { final settingsAsync = ref.watch(settingsProvider); return settingsAsync.when( data: (settings) => settings.lastSyncAt, loading: () => null, error: (_, __) => null, ); }