/// BLoC pour la gestion des sauvegardes
library backup_bloc;

import 'package:dio/dio.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:injectable/injectable.dart';
import 'package:equatable/equatable.dart';
import '../../data/repositories/backup_repository.dart';
import '../../data/models/backup_model.dart';
import '../../data/models/backup_config_model.dart';

// Events
abstract class BackupEvent extends Equatable {
  @override
  List<Object?> get props => [];
}

class LoadBackups extends BackupEvent {}

class CreateBackup extends BackupEvent {
  final String name;
  final String? description;
  CreateBackup(this.name, {this.description});
  @override
  List<Object?> get props => [name, description];
}

class RestoreBackup extends BackupEvent {
  final String backupId;
  RestoreBackup(this.backupId);
  @override
  List<Object?> get props => [backupId];
}

class DeleteBackup extends BackupEvent {
  final String backupId;
  DeleteBackup(this.backupId);
  @override
  List<Object?> get props => [backupId];
}

class LoadBackupConfig extends BackupEvent {}

class UpdateBackupConfig extends BackupEvent {
  final Map<String, dynamic> config;
  UpdateBackupConfig(this.config);
  @override
  List<Object?> get props => [config];
}

// States
abstract class BackupState extends Equatable {
  @override
  List<Object?> get props => [];
}

class BackupInitial extends BackupState {}

class BackupLoading extends BackupState {}

class BackupsLoaded extends BackupState {
  final List<BackupModel> backups;
  BackupsLoaded(this.backups);
  @override
  List<Object?> get props => [backups];
}

class BackupConfigLoaded extends BackupState {
  final BackupConfigModel config;
  BackupConfigLoaded(this.config);
  @override
  List<Object?> get props => [config];
}

class BackupSuccess extends BackupState {
  final String message;
  BackupSuccess(this.message);
  @override
  List<Object?> get props => [message];
}

class BackupError extends BackupState {
  final String error;
  BackupError(this.error);
  @override
  List<Object?> get props => [error];
}

// Bloc
@injectable
class BackupBloc extends Bloc<BackupEvent, BackupState> {
  final BackupRepository _repository;

  BackupBloc(this._repository) : super(BackupInitial()) {
    on<LoadBackups>(_onLoadBackups);
    on<CreateBackup>(_onCreateBackup);
    on<RestoreBackup>(_onRestoreBackup);
    on<DeleteBackup>(_onDeleteBackup);
    on<LoadBackupConfig>(_onLoadBackupConfig);
    on<UpdateBackupConfig>(_onUpdateBackupConfig);
  }

  Future<void> _onLoadBackups(LoadBackups event, Emitter<BackupState> emit) async {
    emit(BackupLoading());
    try {
      final backups = await _repository.getAll();
      emit(BackupsLoaded(backups));
    } catch (e) {
      if (e is DioException && e.type == DioExceptionType.cancel) return;
      emit(BackupError('Erreur: ${e.toString()}'));
    }
  }

  Future<void> _onCreateBackup(CreateBackup event, Emitter<BackupState> emit) async {
    emit(BackupLoading());
    try {
      await _repository.create(event.name, description: event.description);
      final backups = await _repository.getAll();
      emit(BackupsLoaded(backups));
      emit(BackupSuccess('Sauvegarde créée'));
    } catch (e) {
      if (e is DioException && e.type == DioExceptionType.cancel) return;
      emit(BackupError('Erreur: ${e.toString()}'));
    }
  }

  Future<void> _onRestoreBackup(RestoreBackup event, Emitter<BackupState> emit) async {
    emit(BackupLoading());
    try {
      await _repository.restore(event.backupId);
      emit(BackupSuccess('Restauration en cours'));
    } catch (e) {
      if (e is DioException && e.type == DioExceptionType.cancel) return;
      emit(BackupError('Erreur: ${e.toString()}'));
    }
  }

  Future<void> _onDeleteBackup(DeleteBackup event, Emitter<BackupState> emit) async {
    emit(BackupLoading());
    try {
      await _repository.delete(event.backupId);
      final backups = await _repository.getAll();
      emit(BackupsLoaded(backups));
      emit(BackupSuccess('Sauvegarde supprimée'));
    } catch (e) {
      if (e is DioException && e.type == DioExceptionType.cancel) return;
      emit(BackupError('Erreur: ${e.toString()}'));
    }
  }

  Future<void> _onLoadBackupConfig(LoadBackupConfig event, Emitter<BackupState> emit) async {
    emit(BackupLoading());
    try {
      final config = await _repository.getConfig();
      emit(BackupConfigLoaded(config));
    } catch (e) {
      if (e is DioException && e.type == DioExceptionType.cancel) return;
      emit(BackupError('Erreur: ${e.toString()}'));
    }
  }

  Future<void> _onUpdateBackupConfig(UpdateBackupConfig event, Emitter<BackupState> emit) async {
    emit(BackupLoading());
    try {
      final config = await _repository.updateConfig(event.config);
      emit(BackupConfigLoaded(config));
      emit(BackupSuccess('Configuration mise à jour'));
    } catch (e) {
      if (e is DioException && e.type == DioExceptionType.cancel) return;
      emit(BackupError('Erreur: ${e.toString()}'));
    }
  }
}
