import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../database/database.dart'; import '../../features/records/records_service.dart'; import '../auth/auth_providers.dart'; import '../auth/auth_state.dart'; import '../cloud/firebase_account_sync_service.dart'; import '../github/github_auth_service.dart'; import '../github/github_sync_service.dart'; import 'firebase_sync_provider.dart'; import 'github_sync_provider.dart'; import 'r2_upload_service.dart'; import 'sync_bundle_worker.dart'; import 'sync_manager.dart'; import 'sync_models.dart'; import 'sync_outbox.dart'; final r2UploadServiceProvider = Provider((ref) => R2UploadService()); final syncBundleWorkerProvider = Provider((ref) => SyncBundleWorker(ref.watch(databaseProvider))); /// Cloud sync state is account-scoped. The Firebase UID is intentionally part /// of the persisted namespace so signing out and into another account cannot /// inherit the previous account's synced/pending/failed ride state. final syncOutboxProvider = Provider((ref) { final prefs = ref.watch(sharedPreferencesProvider); final user = ref.watch(currentUserProvider); final namespace = user?.uid ?? 'local'; return SyncOutbox(prefs, storageNamespace: namespace); }); final firebaseSyncProvider = Provider((ref) => FirebaseSyncProvider( db: ref.watch(databaseProvider), authService: ref.watch(authServiceProvider), bundleWorker: ref.watch(syncBundleWorkerProvider), r2UploadService: ref.watch(r2UploadServiceProvider), )); final firebaseAccountSyncServiceProvider = Provider((ref) => FirebaseAccountSyncService( db: ref.watch(databaseProvider), auth: ref.watch(authServiceProvider), )); final githubSyncProvider = Provider((ref) => GitHubSyncProvider( service: ref.watch(githubSyncServiceProvider), auth: ref.watch(githubAuthServiceProvider), )); final syncManagerProvider = ChangeNotifierProvider((ref) { final manager = SyncManager( ref.watch(syncOutboxProvider), initialProviders: [ref.watch(firebaseSyncProvider), ref.watch(githubSyncProvider)], defaultProviderId: 'firebase', ); final accountSync = ref.watch(firebaseAccountSyncServiceProvider); ref.listen(authNotifierProvider, (previous, next) { if (next.isAuthenticated && previous?.isAuthenticated != true) { manager.retryAuthRequired(); accountSync.syncAccount().then((_) {}, onError: (_) { // Profile/garage synchronization is downstream of riding and must // never interrupt telemetry or ride persistence. }); } }); ref.onDispose(manager.dispose); return manager; }); final syncStateProvider = Provider((ref) => ref.watch(syncManagerProvider).currentState); final pendingSyncCountProvider = Provider((ref) => ref.watch(syncStateProvider).pendingCount); final isSyncProcessingProvider = Provider((ref) => ref.watch(syncStateProvider).isProcessing);