import 'package:dio/dio.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:injectable/injectable.dart'; import '../../../../core/utils/logger.dart'; import '../../data/repositories/network_repository.dart'; import 'network_event.dart'; import 'network_state.dart'; @injectable class NetworkBloc extends Bloc { final NetworkRepository _repository; NetworkBloc(this._repository) : super(NetworkInitial()) { on(_onLoadNetworkRequested); on(_onSearchNetworkRequested); on(_onToggleFollowRequested); } Future _onToggleFollowRequested(ToggleFollowRequested event, Emitter emit) async { if (state is! NetworkLoaded) return; final current = state as NetworkLoaded; NetworkItem? item; for (final i in current.items) { if (i.id == event.itemId) { item = i; break; } } if (item == null) return; // Seuls les membres (type Member) sont persistés côté backend ; Organisation reste local. if (item.type != 'Member') { final items = current.items.map((i) { if (i.id == event.itemId) return i.copyWith(isConnected: !i.isConnected); return i; }).toList(); emit(NetworkLoaded(items: items, currentQuery: current.currentQuery)); return; } try { final bool newFollowing = item.isConnected ? await _repository.unfollow(event.itemId) : await _repository.follow(event.itemId); final items = current.items.map((i) { if (i.id == event.itemId) return i.copyWith(isConnected: newFollowing); return i; }).toList(); emit(NetworkLoaded(items: items, currentQuery: current.currentQuery)); } catch (e, st) { if (e is DioException && e.type == DioExceptionType.cancel) return; AppLogger.error('NetworkBloc: toggle follow échoué', error: e, stackTrace: st); emit(const NetworkError('Impossible de mettre à jour le suivi. Réessayez.')); } } Future _onLoadNetworkRequested(LoadNetworkRequested event, Emitter emit) async { emit(NetworkLoading()); try { final followedIds = await _repository.getFollowedIds(); final items = await _repository.search('', followedIds: followedIds.toSet()); emit(NetworkLoaded(items: items, currentQuery: '')); } catch (e, st) { if (e is DioException && e.type == DioExceptionType.cancel) return; AppLogger.error('NetworkBloc: chargement réseau échoué', error: e, stackTrace: st); emit(NetworkError('Erreur chargement réseau : $e')); } } Future _onSearchNetworkRequested(SearchNetworkRequested event, Emitter emit) async { emit(NetworkLoading()); try { if (event.query.trim().isEmpty) { final followedIds = await _repository.getFollowedIds(); final items = await _repository.search('', followedIds: followedIds.toSet()); emit(NetworkLoaded(items: items, currentQuery: '')); return; } final followedIds = await _repository.getFollowedIds(); final items = await _repository.search(event.query, followedIds: followedIds.toSet()); emit(NetworkLoaded(items: items, currentQuery: event.query)); } catch (e, st) { if (e is DioException && e.type == DioExceptionType.cancel) return; AppLogger.error('NetworkBloc: recherche réseau échouée', error: e, stackTrace: st); emit(NetworkError('Erreur de recherche : $e')); } } }