import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/spaces_management/model/community_model.dart'; import 'package:syncrow_web/pages/spaces_management/model/product_model.dart'; import 'package:syncrow_web/pages/spaces_management/model/space_model.dart'; import 'package:syncrow_web/pages/spaces_management/bloc/space_management_event.dart'; import 'package:syncrow_web/pages/spaces_management/bloc/space_management_state.dart'; import 'package:syncrow_web/services/product_api.dart'; import 'package:syncrow_web/services/space_mana_api.dart'; class SpaceManagementBloc extends Bloc { final CommunitySpaceManagementApi _api; final ProductApi _productApi; List? _cachedProducts; SpaceManagementBloc(this._api, this._productApi) : super(SpaceManagementInitial()) { on(_onLoadCommunityAndSpaces); on(_onUpdateSpacePosition); on(_onCreateCommunity); on(_onSaveSpaces); on(_onFetchProducts); } void _onFetchProducts( FetchProductsEvent event, Emitter emit, ) async { if (_cachedProducts != null) { // Products are already cached, no need to fetch again return; } try { final products = await _productApi.fetchProducts(); _cachedProducts = products; // Cache the products locally } catch (e) { emit(SpaceManagementError('Error fetching products: $e')); } } void _onLoadCommunityAndSpaces( LoadCommunityAndSpacesEvent event, Emitter emit, ) async { emit(SpaceManagementLoading()); try { if (_cachedProducts == null) { final products = await _productApi.fetchProducts(); _cachedProducts = products; } // Fetch all communities List communities = await _api.fetchCommunities(); // Use Future.wait to handle async calls within map List updatedCommunities = await Future.wait( communities.map((community) async { List spaces = await _api.getSpaceHierarchy(community.uuid); return CommunityModel( uuid: community.uuid, createdAt: community.createdAt, updatedAt: community.updatedAt, name: community.name, description: community.description, spaces: spaces, // New spaces list region: community.region, ); }).toList(), ); emit(SpaceManagementLoaded(communities: updatedCommunities, products: _cachedProducts ?? [])); } catch (e) { emit(SpaceManagementError('Error loading communities and spaces: $e')); } } void _onUpdateSpacePosition( UpdateSpacePositionEvent event, Emitter emit, ) { // Handle space position update logic } void _onCreateCommunity( CreateCommunityEvent event, Emitter emit, ) async { final previousState = state; emit(SpaceManagementLoading()); try { CommunityModel? newCommunity = await _api.createCommunity( event.name, event.description, event.regionId, ); if (newCommunity != null) { if (previousState is SpaceManagementLoaded) { final updatedCommunities = List.from(previousState.communities) ..add(newCommunity); emit(SpaceManagementLoaded( communities: updatedCommunities, products: _cachedProducts ?? [])); } } else { emit(const SpaceManagementError('Error creating community')); } } catch (e) { emit(SpaceManagementError('Error creating community: $e')); } } void _onSaveSpaces( SaveSpacesEvent event, Emitter emit, ) async { final previousState = state; emit(SpaceManagementLoading()); try { final updatedSpaces = await saveSpacesHierarchically(event.spaces, event.communityUuid); emit(SpaceCreationSuccess(spaces: updatedSpaces)); add(LoadCommunityAndSpacesEvent()); } catch (e) { emit(SpaceManagementError('Error saving spaces: $e')); if (previousState is SpaceManagementLoaded) { emit(previousState); } } } Future> saveSpacesHierarchically( List spaces, String communityUuid) async { final orderedSpaces = flattenHierarchy(spaces); for (var space in orderedSpaces) { try { if (space.uuid != null && space.uuid!.isNotEmpty) { // Call update if the space already has a UUID final response = await _api.updateSpace( communityId: communityUuid, spaceId: space.uuid!, name: space.name, parentId: space.parent?.uuid, isPrivate: space.isPrivate, position: space.position, icon: space.icon, direction: space.incomingConnection?.direction, ); } else { // Call create if the space does not have a UUID final response = await _api.createSpace( communityId: communityUuid, name: space.name, parentId: space.parent?.uuid, isPrivate: space.isPrivate, position: space.position, icon: space.icon, direction: space.incomingConnection?.direction, products: space.selectedProducts ); space.uuid = response?.uuid; } } catch (e) { print('Error creating space ${space.name}: $e'); rethrow; // Stop further execution on failure } } return spaces; } List flattenHierarchy(List spaces) { final result = {}; final topLevelSpaces = spaces.where((space) => space.parent == null); void visit(SpaceModel space) { if (!result.contains(space)) { result.add(space); for (var child in spaces.where((s) => s.parent == space)) { visit(child); } } } for (var space in topLevelSpaces) { visit(space); } for (var space in spaces) { if (!result.contains(space)) { result.add(space); } } return result.toList(); // Convert back to a list } }