// ABOUTME: Settings BLoC for managing all user preferences and configuration state
// ABOUTME: Handles settings events and manages state transitions with proper error handling
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter/foundation.dart';
import '../../services/preferences_service.dart';
import '../../models/settings/app_settings.dart';
import '../../models/settings/theme_settings.dart';
import '../../models/settings/unit_settings.dart';
import '../../models/settings/privacy_settings.dart';
import 'settings_event.dart';
import 'settings_state.dart';

/// BLoC for managing application settings and user preferences
class SettingsBloc extends Bloc<SettingsEvent, SettingsState> {
  final PreferencesService _preferencesService;

  SettingsBloc({
    PreferencesService? preferencesService,
  })  : _preferencesService = preferencesService ?? PreferencesService.instance,
        super(const SettingsInitial()) {
    // Register event handlers
    on<LoadSettingsEvent>(_onLoadSettings);
    on<ResetSettingsEvent>(_onResetSettings);
    on<UpdateSettingsEvent>(_onUpdateSettings);
    on<UpdateThemeSettingsEvent>(_onUpdateThemeSettings);
    on<ToggleThemeModeEvent>(_onToggleThemeMode);
    on<UpdateThemeModeEvent>(_onUpdateThemeMode);
    on<UpdateHighContrastEvent>(_onUpdateHighContrast);
    on<UpdateTextScaleEvent>(_onUpdateTextScale);
    on<UpdateAnimationsEnabledEvent>(_onUpdateAnimationsEnabled);
    on<UpdateUnitSettingsEvent>(_onUpdateUnitSettings);
    on<UpdateWeightUnitEvent>(_onUpdateWeightUnit);
    on<UpdateDateFormatEvent>(_onUpdateDateFormat);
    on<UpdateTimeFormatEvent>(_onUpdateTimeFormat);
    on<UpdateShowDecimalsEvent>(_onUpdateShowDecimals);
    on<UpdatePrivacySettingsEvent>(_onUpdatePrivacySettings);
    on<UpdateLocalEncryptionEvent>(_onUpdateLocalEncryption);
    on<UpdateRequireAuthEvent>(_onUpdateRequireAuth);
    on<UpdateBiometricAuthEvent>(_onUpdateBiometricAuth);
    on<UpdateDataRetentionEvent>(_onUpdateDataRetention);
    on<UpdateBackupFrequencyEvent>(_onUpdateBackupFrequency);
    on<UpdateAnalyticsEvent>(_onUpdateAnalytics);
    on<UpdateCrashReportsEvent>(_onUpdateCrashReports);
    on<UpdateLanguageEvent>(_onUpdateLanguage);
    on<UpdateNotificationsEvent>(_onUpdateNotifications);
    on<ExportSettingsEvent>(_onExportSettings);
    on<ImportSettingsEvent>(_onImportSettings);

    // Load settings on initialization
    add(const LoadSettingsEvent());
  }

  /// Load settings from preferences service
  Future<void> _onLoadSettings(
    LoadSettingsEvent event,
    Emitter<SettingsState> emit,
  ) async {
    emit(const SettingsLoading());
    try {
      await _preferencesService.initialize();
      final settings = _preferencesService.settings;
      emit(SettingsLoaded(settings));
    } catch (e) {
      debugPrint('Error loading settings: $e');
      emit(SettingsError(
        'Failed to load settings',
        details: e.toString(),
        currentSettings: AppSettings.defaults(),
      ));
    }
  }

  /// Reset settings to defaults
  Future<void> _onResetSettings(
    ResetSettingsEvent event,
    Emitter<SettingsState> emit,
  ) async {
    try {
      final currentSettings = state.currentSettings ?? AppSettings.defaults();
      emit(SettingsSaving(currentSettings));
      
      await _preferencesService.resetToDefaults();
      final newSettings = _preferencesService.settings;
      
      emit(SettingsReset(newSettings));
    } catch (e) {
      debugPrint('Error resetting settings: $e');
      emit(SettingsError(
        'Failed to reset settings',
        details: e.toString(),
        currentSettings: state.currentSettings,
      ));
    }
  }

  /// Update complete settings
  Future<void> _onUpdateSettings(
    UpdateSettingsEvent event,
    Emitter<SettingsState> emit,
  ) async {
    try {
      emit(SettingsSaving(event.settings));
      await _preferencesService.updateSettings(event.settings);
      emit(SettingsSaved(event.settings, successMessage: 'Settings updated'));
    } catch (e) {
      debugPrint('Error updating settings: $e');
      emit(SettingsError(
        'Failed to update settings',
        details: e.toString(),
        currentSettings: state.currentSettings,
      ));
    }
  }

  /// Update theme settings
  Future<void> _onUpdateThemeSettings(
    UpdateThemeSettingsEvent event,
    Emitter<SettingsState> emit,
  ) async {
    try {
      final currentSettings = state.currentSettings ?? AppSettings.defaults();
      final newSettings = currentSettings.copyWith(themeSettings: event.themeSettings);
      
      emit(SettingsSaving(newSettings));
      await _preferencesService.updateThemeSettings(event.themeSettings);
      emit(SettingsSaved(newSettings));
    } catch (e) {
      debugPrint('Error updating theme settings: $e');
      emit(SettingsError(
        'Failed to update theme settings',
        details: e.toString(),
        currentSettings: state.currentSettings,
      ));
    }
  }

  /// Toggle theme mode
  Future<void> _onToggleThemeMode(
    ToggleThemeModeEvent event,
    Emitter<SettingsState> emit,
  ) async {
    try {
      final currentSettings = state.currentSettings ?? AppSettings.defaults();
      emit(SettingsSaving(currentSettings));
      
      await _preferencesService.toggleThemeMode();
      final newSettings = _preferencesService.settings;
      
      emit(SettingsSaved(newSettings));
    } catch (e) {
      debugPrint('Error toggling theme mode: $e');
      emit(SettingsError(
        'Failed to toggle theme',
        details: e.toString(),
        currentSettings: state.currentSettings,
      ));
    }
  }

  /// Update specific theme mode
  Future<void> _onUpdateThemeMode(
    UpdateThemeModeEvent event,
    Emitter<SettingsState> emit,
  ) async {
    try {
      final currentSettings = state.currentSettings ?? AppSettings.defaults();
      final newThemeSettings = currentSettings.themeSettings.copyWith(themeMode: event.themeMode);
      
      add(UpdateThemeSettingsEvent(newThemeSettings));
    } catch (e) {
      debugPrint('Error updating theme mode: $e');
      emit(SettingsError(
        'Failed to update theme mode',
        details: e.toString(),
        currentSettings: state.currentSettings,
      ));
    }
  }

  /// Update high contrast
  Future<void> _onUpdateHighContrast(
    UpdateHighContrastEvent event,
    Emitter<SettingsState> emit,
  ) async {
    final currentSettings = state.currentSettings ?? AppSettings.defaults();
    final newThemeSettings = currentSettings.themeSettings.copyWith(highContrast: event.enabled);
    add(UpdateThemeSettingsEvent(newThemeSettings));
  }

  /// Update text scale
  Future<void> _onUpdateTextScale(
    UpdateTextScaleEvent event,
    Emitter<SettingsState> emit,
  ) async {
    final currentSettings = state.currentSettings ?? AppSettings.defaults();
    final newThemeSettings = currentSettings.themeSettings.copyWith(textScale: event.textScale);
    add(UpdateThemeSettingsEvent(newThemeSettings));
  }

  /// Update animations enabled
  Future<void> _onUpdateAnimationsEnabled(
    UpdateAnimationsEnabledEvent event,
    Emitter<SettingsState> emit,
  ) async {
    final currentSettings = state.currentSettings ?? AppSettings.defaults();
    final newThemeSettings = currentSettings.themeSettings.copyWith(animationsEnabled: event.enabled);
    add(UpdateThemeSettingsEvent(newThemeSettings));
  }

  /// Update unit settings
  Future<void> _onUpdateUnitSettings(
    UpdateUnitSettingsEvent event,
    Emitter<SettingsState> emit,
  ) async {
    try {
      final currentSettings = state.currentSettings ?? AppSettings.defaults();
      final newSettings = currentSettings.copyWith(unitSettings: event.unitSettings);
      
      emit(SettingsSaving(newSettings));
      await _preferencesService.updateUnitSettings(event.unitSettings);
      emit(SettingsSaved(newSettings));
    } catch (e) {
      debugPrint('Error updating unit settings: $e');
      emit(SettingsError(
        'Failed to update unit settings',
        details: e.toString(),
        currentSettings: state.currentSettings,
      ));
    }
  }

  /// Update weight unit
  Future<void> _onUpdateWeightUnit(
    UpdateWeightUnitEvent event,
    Emitter<SettingsState> emit,
  ) async {
    final currentSettings = state.currentSettings ?? AppSettings.defaults();
    final newUnitSettings = currentSettings.unitSettings.copyWith(weightUnit: event.weightUnit);
    add(UpdateUnitSettingsEvent(newUnitSettings));
  }

  /// Update date format
  Future<void> _onUpdateDateFormat(
    UpdateDateFormatEvent event,
    Emitter<SettingsState> emit,
  ) async {
    final currentSettings = state.currentSettings ?? AppSettings.defaults();
    final newUnitSettings = currentSettings.unitSettings.copyWith(dateFormat: event.dateFormat);
    add(UpdateUnitSettingsEvent(newUnitSettings));
  }

  /// Update time format
  Future<void> _onUpdateTimeFormat(
    UpdateTimeFormatEvent event,
    Emitter<SettingsState> emit,
  ) async {
    final currentSettings = state.currentSettings ?? AppSettings.defaults();
    final newUnitSettings = currentSettings.unitSettings.copyWith(timeFormat: event.timeFormat);
    add(UpdateUnitSettingsEvent(newUnitSettings));
  }

  /// Update show decimals
  Future<void> _onUpdateShowDecimals(
    UpdateShowDecimalsEvent event,
    Emitter<SettingsState> emit,
  ) async {
    final currentSettings = state.currentSettings ?? AppSettings.defaults();
    final newUnitSettings = currentSettings.unitSettings.copyWith(showDecimals: event.showDecimals);
    add(UpdateUnitSettingsEvent(newUnitSettings));
  }

  /// Update privacy settings
  Future<void> _onUpdatePrivacySettings(
    UpdatePrivacySettingsEvent event,
    Emitter<SettingsState> emit,
  ) async {
    try {
      final currentSettings = state.currentSettings ?? AppSettings.defaults();
      final newSettings = currentSettings.copyWith(privacySettings: event.privacySettings);
      
      emit(SettingsSaving(newSettings));
      await _preferencesService.updatePrivacySettings(event.privacySettings);
      emit(SettingsSaved(newSettings));
    } catch (e) {
      debugPrint('Error updating privacy settings: $e');
      emit(SettingsError(
        'Failed to update privacy settings',
        details: e.toString(),
        currentSettings: state.currentSettings,
      ));
    }
  }

  /// Update local encryption
  Future<void> _onUpdateLocalEncryption(
    UpdateLocalEncryptionEvent event,
    Emitter<SettingsState> emit,
  ) async {
    final currentSettings = state.currentSettings ?? AppSettings.defaults();
    final newPrivacySettings = currentSettings.privacySettings.copyWith(enableLocalEncryption: event.enabled);
    add(UpdatePrivacySettingsEvent(newPrivacySettings));
  }

  /// Update require auth
  Future<void> _onUpdateRequireAuth(
    UpdateRequireAuthEvent event,
    Emitter<SettingsState> emit,
  ) async {
    final currentSettings = state.currentSettings ?? AppSettings.defaults();
    final newPrivacySettings = currentSettings.privacySettings.copyWith(requireAuthForAccess: event.required);
    add(UpdatePrivacySettingsEvent(newPrivacySettings));
  }

  /// Update biometric auth
  Future<void> _onUpdateBiometricAuth(
    UpdateBiometricAuthEvent event,
    Emitter<SettingsState> emit,
  ) async {
    final currentSettings = state.currentSettings ?? AppSettings.defaults();
    final newPrivacySettings = currentSettings.privacySettings.copyWith(enableBiometric: event.enabled);
    add(UpdatePrivacySettingsEvent(newPrivacySettings));
  }

  /// Update data retention
  Future<void> _onUpdateDataRetention(
    UpdateDataRetentionEvent event,
    Emitter<SettingsState> emit,
  ) async {
    final currentSettings = state.currentSettings ?? AppSettings.defaults();
    final newPrivacySettings = currentSettings.privacySettings.copyWith(dataRetention: event.retentionPeriod);
    add(UpdatePrivacySettingsEvent(newPrivacySettings));
  }

  /// Update backup frequency
  Future<void> _onUpdateBackupFrequency(
    UpdateBackupFrequencyEvent event,
    Emitter<SettingsState> emit,
  ) async {
    final currentSettings = state.currentSettings ?? AppSettings.defaults();
    final newPrivacySettings = currentSettings.privacySettings.copyWith(backupFrequency: event.backupFrequency);
    add(UpdatePrivacySettingsEvent(newPrivacySettings));
  }

  /// Update analytics
  Future<void> _onUpdateAnalytics(
    UpdateAnalyticsEvent event,
    Emitter<SettingsState> emit,
  ) async {
    try {
      final currentSettings = state.currentSettings ?? AppSettings.defaults();
      final newSettings = currentSettings.copyWith(enableAnalytics: event.enabled);
      
      emit(SettingsSaving(newSettings));
      await _preferencesService.updateAnalyticsEnabled(event.enabled);
      emit(SettingsSaved(newSettings));
    } catch (e) {
      debugPrint('Error updating analytics setting: $e');
      emit(SettingsError(
        'Failed to update analytics setting',
        details: e.toString(),
        currentSettings: state.currentSettings,
      ));
    }
  }

  /// Update crash reports
  Future<void> _onUpdateCrashReports(
    UpdateCrashReportsEvent event,
    Emitter<SettingsState> emit,
  ) async {
    final currentSettings = state.currentSettings ?? AppSettings.defaults();
    final newPrivacySettings = currentSettings.privacySettings.copyWith(shareCrashReports: event.enabled);
    add(UpdatePrivacySettingsEvent(newPrivacySettings));
  }

  /// Update language
  Future<void> _onUpdateLanguage(
    UpdateLanguageEvent event,
    Emitter<SettingsState> emit,
  ) async {
    try {
      final currentSettings = state.currentSettings ?? AppSettings.defaults();
      final newSettings = currentSettings.copyWith(language: event.language);
      
      emit(SettingsSaving(newSettings));
      await _preferencesService.updateLanguage(event.language);
      emit(SettingsSaved(newSettings));
    } catch (e) {
      debugPrint('Error updating language: $e');
      emit(SettingsError(
        'Failed to update language',
        details: e.toString(),
        currentSettings: state.currentSettings,
      ));
    }
  }

  /// Update notifications
  Future<void> _onUpdateNotifications(
    UpdateNotificationsEvent event,
    Emitter<SettingsState> emit,
  ) async {
    try {
      final currentSettings = state.currentSettings ?? AppSettings.defaults();
      final newSettings = currentSettings.copyWith(enableNotifications: event.enabled);
      
      emit(SettingsSaving(newSettings));
      await _preferencesService.updateNotificationsEnabled(event.enabled);
      emit(SettingsSaved(newSettings));
    } catch (e) {
      debugPrint('Error updating notifications: $e');
      emit(SettingsError(
        'Failed to update notifications',
        details: e.toString(),
        currentSettings: state.currentSettings,
      ));
    }
  }

  /// Export settings
  Future<void> _onExportSettings(
    ExportSettingsEvent event,
    Emitter<SettingsState> emit,
  ) async {
    try {
      final exportData = _preferencesService.exportSettings();
      // For now, just return the export data - in Step 12 we'll add file operations
      emit(SettingsExported(exportData, 'settings_export.json'));
    } catch (e) {
      debugPrint('Error exporting settings: $e');
      emit(SettingsExportError(
        'Failed to export settings',
        details: e.toString(),
        currentSettings: state.currentSettings,
      ));
    }
  }

  /// Import settings
  Future<void> _onImportSettings(
    ImportSettingsEvent event,
    Emitter<SettingsState> emit,
  ) async {
    try {
      emit(const SettingsLoading());
      
      final success = await _preferencesService.importSettings(event.settingsJson);
      if (success) {
        final newSettings = _preferencesService.settings;
        emit(SettingsImported(newSettings, 'Settings imported successfully'));
      } else {
        emit(SettingsImportError(
          'Invalid settings format',
          'JSON',
          currentSettings: state.currentSettings,
        ));
      }
    } catch (e) {
      debugPrint('Error importing settings: $e');
      emit(SettingsImportError(
        'Failed to import settings',
        'JSON',
        details: e.toString(),
        currentSettings: state.currentSettings,
      ));
    }
  }
}
