// ignore_for_file: prefer_initializing_formals import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../auth/auth_service.dart'; import 'cloud_restore_service.dart'; enum CloudRestoreStatus { idle, restoring, success, partialFailure, authRequired, unavailable, failure, } class CloudRestoreUiState { final CloudRestoreStatus status; final CloudRestoreResult? result; final String? message; const CloudRestoreUiState({ this.status = CloudRestoreStatus.idle, this.result, this.message, }); bool get isRestoring => status == CloudRestoreStatus.restoring; } class CloudRestoreController extends StateNotifier { final CloudRestoreService _restoreService; final AuthService _authService; CloudRestoreController({ required CloudRestoreService restoreService, required AuthService authService, }) : _restoreService = restoreService, _authService = authService, super(const CloudRestoreUiState()); Future restoreFromMotorCloud() async { if (state.isRestoring) return state.result; final user = _authService.currentUser; if (user == null || user.isAnonymous) { state = const CloudRestoreUiState( status: CloudRestoreStatus.authRequired, message: 'Sign in with a MotorCloud account to restore ride history.', ); return null; } if (!_authService.isConfigured) { state = const CloudRestoreUiState( status: CloudRestoreStatus.unavailable, message: 'MotorCloud is unavailable. Try again when Firebase services are available.', ); return null; } state = const CloudRestoreUiState(status: CloudRestoreStatus.restoring); try { final result = await _restoreService.restore(); final hasFailures = result.failures > 0; final hasRestoredOrMatched = result.hasAnyRestoredData || result.existingRidesMatched > 0 || result.telemetryAlreadyPresent > 0 || result.telemetrySkipped > 0; final status = result.requiresAuthentication && !hasRestoredOrMatched ? CloudRestoreStatus.authRequired : (hasFailures && !hasRestoredOrMatched ? CloudRestoreStatus.failure : (hasFailures ? CloudRestoreStatus.partialFailure : CloudRestoreStatus.success)); state = CloudRestoreUiState( status: status, result: result, message: _formatResult(result), ); return result; } on StateError catch (e) { final message = e.message; state = CloudRestoreUiState( status: message.toLowerCase().contains('auth') ? CloudRestoreStatus.authRequired : CloudRestoreStatus.unavailable, message: message, ); return null; } catch (e) { state = CloudRestoreUiState( status: CloudRestoreStatus.failure, message: 'MotorCloud restore failed: $e', ); return null; } } String _formatResult(CloudRestoreResult result) { final parts = []; if (result.metadataRowsAdded > 0) { parts.add('${result.metadataRowsAdded} ride(s) added'); } if (result.telemetrySamplesRestored > 0) { parts.add( '${result.telemetrySamplesRestored} telemetry sample(s) restored', ); } if (result.performanceRunsRestored > 0) { parts.add( '${result.performanceRunsRestored} performance run(s) restored', ); } if (result.rideEventsRestored > 0) { parts.add('${result.rideEventsRestored} ride event(s) restored'); } if (result.existingRidesMatched > 0 || result.telemetryAlreadyPresent > 0) { final alreadyPresent = result.existingRidesMatched > result.telemetryAlreadyPresent ? result.existingRidesMatched : result.telemetryAlreadyPresent; parts.add('$alreadyPresent ride(s) already on this device'); } if (result.failures > 0) { parts.add('${result.failures} item(s) need attention'); } if (parts.isEmpty) { return 'No restorable MotorCloud rides were found for this account.'; } return 'MotorCloud restore complete: ${parts.join(', ')}.'; } }