import 'package:flutter/foundation.dart';
import '../providers/auth_provider.dart';
import '../services/notification_service.dart';
import '../services/storage_service.dart';
import '../utils/session_manager.dart';

/// Service for handling app initialization tasks
///
/// Coordinates initialization of various services and providers:
/// - Theme preferences loading
/// - Notification service setup
/// - Session restoration
/// - Cache management
///
/// Usage example:
/// ```dart
/// final initService = AppInitializationService(
///   authProvider: authProvider,
///   themeProvider: themeProvider,
///   notificationService: notificationService,
/// );
///
/// final result = await initService.initialize();
/// if (result.success) {
///   // App initialized successfully
/// }
/// ```
class AppInitializationService {
  final AuthProvider _authProvider;
  final NotificationService _notificationService;
  final StorageService _storageService;
  late final SessionManager _sessionManager;

  AppInitializationService({
    required AuthProvider authProvider,
    required NotificationService notificationService,
    StorageService? storageService,
  }) : _authProvider = authProvider,
       _notificationService = notificationService,
       _storageService = storageService ?? StorageService() {
    _sessionManager = SessionManager(authProvider: _authProvider);
  }

  /// Initialize the application
  ///
  /// Performs all necessary initialization tasks in the correct order
  /// Returns InitializationResult with status and details
  Future<InitializationResult> initialize() async {
    final startTime = DateTime.now();
    final steps = <InitializationStep>[];

    try {
      // Step 1: Initialize notification service
      steps.add(await _initializeNotifications());

      // Step 2: Load theme preferences
      steps.add(await _loadThemePreferences());

      // Step 3: Check and manage cache
      steps.add(await _manageCacheVersion());

      // Step 4: Attempt session restoration
      steps.add(await _restoreSession());

      final duration = DateTime.now().difference(startTime);
      final allSuccessful = steps.every((step) => step.success);

      return InitializationResult(
        success: allSuccessful,
        steps: steps,
        duration: duration,
        sessionRestored: steps
            .firstWhere(
              (s) => s.name == 'Session Restoration',
              orElse: () => InitializationStep(
                name: 'Session Restoration',
                success: false,
              ),
            )
            .success,
      );
    } catch (e) {
      debugPrint('Error during app initialization: $e');
      final duration = DateTime.now().difference(startTime);

      return InitializationResult(
        success: false,
        steps: steps,
        duration: duration,
        error: e.toString(),
      );
    }
  }

  /// Initialize notification service
  Future<InitializationStep> _initializeNotifications() async {
    try {
      await _notificationService.initialize();
      return InitializationStep(
        name: 'Notification Service',
        success: true,
        message: 'Notification service initialized',
      );
    } catch (e) {
      debugPrint('Failed to initialize notifications: $e');
      return InitializationStep(
        name: 'Notification Service',
        success: false,
        message: 'Failed to initialize notifications: $e',
      );
    }
  }

  /// Load theme preferences
  Future<InitializationStep> _loadThemePreferences() async {
    try {
      // Theme preferences are loaded in ThemeProvider constructor
      // This step just confirms it's ready
      return InitializationStep(
        name: 'Theme Preferences',
        success: true,
        message: 'Theme preferences loaded',
      );
    } catch (e) {
      debugPrint('Failed to load theme preferences: $e');
      return InitializationStep(
        name: 'Theme Preferences',
        success: false,
        message: 'Failed to load theme preferences: $e',
      );
    }
  }

  /// Manage cache version
  Future<InitializationStep> _manageCacheVersion() async {
    try {
      const expectedCacheVersion = 1; // Update this when data structure changes
      final cleared = await _storageService.clearCacheIfVersionMismatch(
        expectedCacheVersion,
      );

      if (cleared) {
        return InitializationStep(
          name: 'Cache Management',
          success: true,
          message: 'Cache cleared due to version mismatch',
        );
      } else {
        return InitializationStep(
          name: 'Cache Management',
          success: true,
          message: 'Cache version is current',
        );
      }
    } catch (e) {
      debugPrint('Failed to manage cache: $e');
      return InitializationStep(
        name: 'Cache Management',
        success: false,
        message: 'Failed to manage cache: $e',
      );
    }
  }

  /// Attempt to restore previous session
  Future<InitializationStep> _restoreSession() async {
    try {
      // Check if session can be restored
      final canRestore = await _sessionManager.canRestoreSession();

      if (!canRestore) {
        return InitializationStep(
          name: 'Session Restoration',
          success: false,
          message: 'No saved session to restore',
        );
      }

      // Attempt restoration
      final result = await _sessionManager.restoreSession();

      if (result.success) {
        return InitializationStep(
          name: 'Session Restoration',
          success: true,
          message: 'Session restored successfully',
        );
      } else {
        // Session restoration failed, but this is not a critical error
        // User will just need to login again
        return InitializationStep(
          name: 'Session Restoration',
          success: false,
          message: result.message,
          reason: result.reason,
        );
      }
    } catch (e) {
      debugPrint('Error during session restoration: $e');
      return InitializationStep(
        name: 'Session Restoration',
        success: false,
        message: 'Session restoration error: $e',
      );
    }
  }

  /// Get session manager instance
  SessionManager get sessionManager => _sessionManager;

  /// Get storage service instance
  StorageService get storageService => _storageService;
}

/// Result of app initialization
class InitializationResult {
  final bool success;
  final List<InitializationStep> steps;
  final Duration duration;
  final bool sessionRestored;
  final String? error;

  InitializationResult({
    required this.success,
    required this.steps,
    required this.duration,
    this.sessionRestored = false,
    this.error,
  });

  /// Get failed steps
  List<InitializationStep> get failedSteps =>
      steps.where((step) => !step.success).toList();

  /// Get successful steps
  List<InitializationStep> get successfulSteps =>
      steps.where((step) => step.success).toList();

  /// Check if initialization is complete (even with some non-critical failures)
  bool get isComplete => steps.isNotEmpty;

  @override
  String toString() {
    return 'InitializationResult('
        'success: $success, '
        'sessionRestored: $sessionRestored, '
        'steps: ${steps.length}, '
        'duration: ${duration.inMilliseconds}ms'
        ')';
  }
}

/// Individual initialization step
class InitializationStep {
  final String name;
  final bool success;
  final String? message;
  final SessionRestoreFailureReason? reason;

  InitializationStep({
    required this.name,
    required this.success,
    this.message,
    this.reason,
  });

  @override
  String toString() {
    return 'InitializationStep('
        'name: $name, '
        'success: $success, '
        'message: $message'
        ')';
  }
}
