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<bool> 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<bool> 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<SessionRestoreResult> 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<void> 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<void> 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<bool> 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
    }
  }
}
