import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../models/activity.dart';
import '../../../repositories/activity_repository.dart';
import '../../../services/error_service.dart';
import 'db_activity_event.dart';
import 'db_activity_state.dart';

/// BLoC pour gérer les activités de la base de données
class DbActivityBloc extends Bloc<DbActivityEvent, DbActivityState> {
  final ActivityRepository _repository;
  final ErrorService _errorService;

  DbActivityBloc({
    required ActivityRepository repository,
    required ErrorService errorService,
  })  : _repository = repository,
        _errorService = errorService,
        super(const DbActivityInitial()) {
    
    on<LoadDbActivities>(_onLoadDbActivities);
    on<SearchDbActivities>(_onSearchDbActivities);
    on<AddDbActivity>(_onAddDbActivity);
    on<AddDbActivitiesBatch>(_onAddDbActivitiesBatch);
    on<VoteForDbActivity>(_onVoteForDbActivity);
    on<DeleteDbActivity>(_onDeleteDbActivity);
    on<FilterDbActivities>(_onFilterDbActivities);
    on<RefreshDbActivities>(_onRefreshDbActivities);
    on<UpdateDbActivity>(_onUpdateDbActivity);
    on<ToggleDbActivityFavorite>(_onToggleDbActivityFavorite);
    on<ClearDbSearchResults>(_onClearDbSearchResults);
  }

  /// Charger les activités d'un voyage
  Future<void> _onLoadDbActivities(
    LoadDbActivities event,
    Emitter<DbActivityState> emit,
  ) async {
    try {
      emit(const DbActivityLoading());
      
      final activities = await _repository.getActivitiesByTrip(event.tripId);
      
      emit(DbActivityLoaded(
        activities: activities,
        tripParticipants: event.tripParticipants,
      ));
    } catch (e) {
      _errorService.logError('db_activity_bloc', 'Erreur chargement activités DB: $e');
      emit(const DbActivityError('Impossible de charger les activités du voyage'));
    }
  }

  /// Rechercher des activités
  Future<void> _onSearchDbActivities(
    SearchDbActivities event,
    Emitter<DbActivityState> emit,
  ) async {
    try {
      emit(const DbActivitySearching());
      
      // Pour l'instant, on fait une recherche simple en filtrant les activités existantes
      final allActivities = await _repository.getActivitiesByTrip(event.tripId);
      final results = allActivities
          .where((activity) => 
              activity.name.toLowerCase().contains(event.query.toLowerCase()) ||
              activity.description.toLowerCase().contains(event.query.toLowerCase()))
          .toList();
      
      emit(DbActivitySearchResults(
        results: results,
        query: event.query,
        tripParticipants: event.tripParticipants,
      ));
    } catch (e) {
      _errorService.logError('db_activity_bloc', 'Erreur recherche activités: $e');
      emit(const DbActivityError('Erreur lors de la recherche'));
    }
  }

  /// Ajouter une activité
  Future<void> _onAddDbActivity(
    AddDbActivity event,
    Emitter<DbActivityState> emit,
  ) async {
    try {
      await _repository.addActivity(event.activity);
      
      // Recharger les activités si on est dans l'état chargé
      if (state is DbActivityLoaded) {
        final currentState = state as DbActivityLoaded;
        add(LoadDbActivities(
          tripId: event.activity.tripId,
          tripParticipants: currentState.tripParticipants,
        ));
      }
      
      emit(const DbActivityOperationSuccess('Activité ajoutée avec succès'));
    } catch (e) {
      _errorService.logError('db_activity_bloc', 'Erreur ajout activité: $e');
      emit(const DbActivityError('Impossible d\'ajouter l\'activité'));
    }
  }

  /// Ajouter plusieurs activités
  Future<void> _onAddDbActivitiesBatch(
    AddDbActivitiesBatch event,
    Emitter<DbActivityState> emit,
  ) async {
    try {
      await _repository.addActivitiesBatch(event.activities);
      
      // Recharger les activités si on est dans l'état chargé
      if (state is DbActivityLoaded && event.activities.isNotEmpty) {
        final currentState = state as DbActivityLoaded;
        add(LoadDbActivities(
          tripId: event.activities.first.tripId,
          tripParticipants: currentState.tripParticipants,
        ));
      }
      
      emit(DbActivityOperationSuccess('${event.activities.length} activités ajoutées'));
    } catch (e) {
      _errorService.logError('db_activity_bloc', 'Erreur ajout batch: $e');
      emit(const DbActivityError('Impossible d\'ajouter les activités'));
    }
  }

  /// Voter pour une activité
  Future<void> _onVoteForDbActivity(
    VoteForDbActivity event,
    Emitter<DbActivityState> emit,
  ) async {
    try {
      await _repository.voteForActivity(
        event.activityId,
        event.userId,
        event.isUpvote ? 1 : -1,
      );
      
      // Recharger les activités pour refléter le nouveau vote
      if (state is DbActivityLoaded) {
        final currentState = state as DbActivityLoaded;
        final activity = currentState.activities.firstWhere(
          (a) => a.id == event.activityId,
        );
        add(LoadDbActivities(
          tripId: activity.tripId,
          tripParticipants: currentState.tripParticipants,
        ));
      }
      
      emit(const DbActivityOperationSuccess('Vote enregistré'));
    } catch (e) {
      _errorService.logError('db_activity_bloc', 'Erreur vote: $e');
      emit(const DbActivityError('Impossible d\'enregistrer le vote'));
    }
  }

  /// Supprimer une activité
  Future<void> _onDeleteDbActivity(
    DeleteDbActivity event,
    Emitter<DbActivityState> emit,
  ) async {
    try {
      await _repository.deleteActivity(event.activityId);
      
      // Mettre à jour la liste locale si on est dans l'état chargé
      if (state is DbActivityLoaded) {
        final currentState = state as DbActivityLoaded;
        final updatedActivities = currentState.activities
            .where((activity) => activity.id != event.activityId)
            .toList();
        
        emit(currentState.copyWith(activities: updatedActivities));
      }
      
      emit(const DbActivityOperationSuccess('Activité supprimée'));
    } catch (e) {
      _errorService.logError('db_activity_bloc', 'Erreur suppression: $e');
      emit(const DbActivityError('Impossible de supprimer l\'activité'));
    }
  }

  /// Filtrer les activités
  Future<void> _onFilterDbActivities(
    FilterDbActivities event,
    Emitter<DbActivityState> emit,
  ) async {
    if (state is! DbActivityLoaded) return;
    
    final currentState = state as DbActivityLoaded;
    List<Activity> filteredActivities = List.from(currentState.activities);
    
    // Filtrer par catégorie
    if (event.category != null && event.category!.isNotEmpty) {
      filteredActivities = filteredActivities
          .where((activity) => activity.category == event.category)
          .toList();
    }
    
    // Note: isFavorite n'existe pas dans le modèle Activity actuel
    // if (event.showFavorites == true) {
    //   filteredActivities = filteredActivities
    //       .where((activity) => activity.isFavorite == true)
    //       .toList();
    // }
    
    emit(currentState.copyWith(activities: filteredActivities));
  }

  /// Rafraîchir les activités
  Future<void> _onRefreshDbActivities(
    RefreshDbActivities event,
    Emitter<DbActivityState> emit,
  ) async {
    add(LoadDbActivities(
      tripId: event.tripId,
      tripParticipants: event.tripParticipants,
    ));
  }

  /// Mettre à jour une activité
  Future<void> _onUpdateDbActivity(
    UpdateDbActivity event,
    Emitter<DbActivityState> emit,
  ) async {
    try {
      await _repository.updateActivity(event.activity);
      
      // Mettre à jour la liste locale
      if (state is DbActivityLoaded) {
        final currentState = state as DbActivityLoaded;
        final updatedActivities = currentState.activities.map((activity) {
          return activity.id == event.activity.id ? event.activity : activity;
        }).toList();
        
        emit(currentState.copyWith(activities: updatedActivities));
      }
      
      emit(const DbActivityOperationSuccess('Activité mise à jour'));
    } catch (e) {
      _errorService.logError('db_activity_bloc', 'Erreur mise à jour: $e');
      emit(const DbActivityError('Impossible de mettre à jour l\'activité'));
    }
  }

  /// Basculer le favori d'une activité
  Future<void> _onToggleDbActivityFavorite(
    ToggleDbActivityFavorite event,
    Emitter<DbActivityState> emit,
  ) async {
    // Note: La fonctionnalité favori n'existe pas encore dans le repository
    // Cette méthode peut être implémentée plus tard
    emit(const DbActivityError('Fonctionnalité favori non disponible'));
  }

  /// Effacer les résultats de recherche
  Future<void> _onClearDbSearchResults(
    ClearDbSearchResults event,
    Emitter<DbActivityState> emit,
  ) async {
    if (state is DbActivitySearchResults) {
      // Retourner à l'état précédent ou initial
      emit(const DbActivityInitial());
    }
  }
}