import 'package:flutter/foundation.dart'; import '../models/user_credentials.dart'; import '../providers/auth_provider.dart'; /// Session manager for handling app startup and session restoration /// /// Provides utilities for: /// - Checking if saved credentials exist /// - Attempting to restore previous session /// - Handling session expiration /// /// Usage example: /// ```dart /// final sessionManager = SessionManager(authProvider: authProvider); /// /// // Check if session can be restored /// final canRestore = await sessionManager.canRestoreSession(); /// /// // Attempt to restore session /// final restored = await sessionManager.restoreSession(); /// /// // Handle session expiration /// await sessionManager.handleSessionExpired(); /// ``` class SessionManager { final AuthProvider _authProvider; SessionManager({required AuthProvider authProvider}) : _authProvider = authProvider; /// Check if saved credentials exist /// /// Returns true if credentials are stored, false otherwise /// Does not validate if the session is still active Future hasSavedCredentials() async { try { final credentials = await UserCredentials.loadSecurely(); return credentials != null; } catch (e) { debugPrint('Error checking saved credentials: $e'); return false; } } /// Check if session can be restored /// /// Checks if saved credentials exist and are valid /// Returns true if session restoration should be attempted Future canRestoreSession() async { return await hasSavedCredentials(); } /// Attempt to restore session from saved credentials /// /// Loads credentials from secure storage and attempts login /// Returns SessionRestoreResult with status and details Future restoreSession() async { try { // Check if credentials exist final hasCredentials = await hasSavedCredentials(); if (!hasCredentials) { return SessionRestoreResult( success: false, reason: SessionRestoreFailureReason.noCredentials, message: '未找到保存的登录凭证', ); } // Attempt to restore session using AuthProvider final restored = await _authProvider.restoreSession(); if (restored) { return SessionRestoreResult(success: true, message: '会话恢复成功'); } else { // Check the error message from auth provider final errorMessage = _authProvider.errorMessage; final reason = _determineFailureReason(errorMessage); return SessionRestoreResult( success: false, reason: reason, message: errorMessage ?? '会话恢复失败', ); } } catch (e) { debugPrint('Error restoring session: $e'); return SessionRestoreResult( success: false, reason: SessionRestoreFailureReason.unknown, message: '会话恢复出错: $e', ); } } /// Handle session expiration /// /// Clears current session and credentials /// Should be called when session is detected as expired Future handleSessionExpired() async { try { await _authProvider.logout(); debugPrint('Session expired and cleared'); } catch (e) { debugPrint('Error handling session expiration: $e'); } } /// Clear saved session data /// /// Removes all saved credentials and session information /// Useful for logout or when user wants to clear data Future clearSession() async { try { await _authProvider.logout(); debugPrint('Session cleared successfully'); } catch (e) { debugPrint('Error clearing session: $e'); } } /// Validate current session /// /// Checks if the current session is still valid /// Returns true if session is active and healthy Future validateSession() async { try { if (!_authProvider.isAuthenticated) { return false; } return await _authProvider.checkSession(); } catch (e) { debugPrint('Error validating session: $e'); return false; } } /// Get session status /// /// Returns current session status information SessionStatus getSessionStatus() { return SessionStatus( isAuthenticated: _authProvider.isAuthenticated, authState: _authProvider.state, hasConnection: _authProvider.connection != null, errorMessage: _authProvider.errorMessage, ); } /// Determine failure reason from error message SessionRestoreFailureReason _determineFailureReason(String? errorMessage) { if (errorMessage == null) { return SessionRestoreFailureReason.unknown; } if (errorMessage.contains('密码错误') || errorMessage.contains('凭证')) { return SessionRestoreFailureReason.invalidCredentials; } else if (errorMessage.contains('网络') || errorMessage.contains('连接')) { return SessionRestoreFailureReason.networkError; } else if (errorMessage.contains('过期')) { return SessionRestoreFailureReason.sessionExpired; } else { return SessionRestoreFailureReason.unknown; } } } /// Result of session restoration attempt class SessionRestoreResult { final bool success; final SessionRestoreFailureReason? reason; final String message; SessionRestoreResult({ required this.success, this.reason, required this.message, }); @override String toString() { return 'SessionRestoreResult(success: $success, reason: $reason, message: $message)'; } } /// Reasons why session restoration might fail enum SessionRestoreFailureReason { /// No saved credentials found noCredentials, /// Saved credentials are invalid invalidCredentials, /// Session has expired sessionExpired, /// Network connection error networkError, /// Unknown error unknown, } /// Current session status information class SessionStatus { final bool isAuthenticated; final AuthState authState; final bool hasConnection; final String? errorMessage; SessionStatus({ required this.isAuthenticated, required this.authState, required this.hasConnection, this.errorMessage, }); /// Check if session is healthy bool get isHealthy => isAuthenticated && hasConnection && errorMessage == null; @override String toString() { return 'SessionStatus(' 'isAuthenticated: $isAuthenticated, ' 'authState: $authState, ' 'hasConnection: $hasConnection, ' 'errorMessage: $errorMessage' ')'; } } /// Extension methods for SessionRestoreFailureReason extension SessionRestoreFailureReasonExtension on SessionRestoreFailureReason { /// Get user-friendly message for the failure reason String get userMessage { switch (this) { case SessionRestoreFailureReason.noCredentials: return '未找到保存的登录信息,请重新登录'; case SessionRestoreFailureReason.invalidCredentials: return '登录凭证无效,请重新登录'; case SessionRestoreFailureReason.sessionExpired: return '会话已过期,请重新登录'; case SessionRestoreFailureReason.networkError: return '网络连接失败,请检查网络后重试'; case SessionRestoreFailureReason.unknown: return '会话恢复失败,请重新登录'; } } /// Check if user should be prompted to login again bool get shouldPromptLogin { switch (this) { case SessionRestoreFailureReason.noCredentials: case SessionRestoreFailureReason.invalidCredentials: case SessionRestoreFailureReason.sessionExpired: return true; case SessionRestoreFailureReason.networkError: case SessionRestoreFailureReason.unknown: return false; // User might want to retry } } }