import 'dart:async';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_event.dart';
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_state.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/create_subspace_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_event.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_state.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/subspace_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/tag.dart';
import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart';
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_body_model.dart';
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_update_model.dart';
import 'package:syncrow_web/services/product_api.dart';
import 'package:syncrow_web/services/space_mana_api.dart';
import 'package:syncrow_web/services/space_model_mang_api.dart';
import 'package:syncrow_web/utils/constants/action_enum.dart' as custom_action;

class SpaceManagementBloc
    extends Bloc<SpaceManagementEvent, SpaceManagementState> {
  final CommunitySpaceManagementApi _api;
  final ProductApi _productApi;
  final SpaceModelManagementApi _spaceModelApi;

  List<ProductModel>? _cachedProducts;
  List<SpaceTemplateModel>? _cachedSpaceModels;
  final SpaceTreeBloc _spaceTreeBloc;
  List<Tag>? _cachedTags;

  SpaceManagementBloc(
    this._api,
    this._productApi,
    this._spaceModelApi,
    this._spaceTreeBloc,
  ) : super(SpaceManagementInitial()) {
    on<LoadCommunityAndSpacesEvent>(_onLoadCommunityAndSpaces);
    on<CreateCommunityEvent>(_onCreateCommunity);
    on<SelectCommunityEvent>(_onSelectCommunity);
    on<DeleteCommunityEvent>(_onCommunityDelete);
    on<UpdateCommunityEvent>(_onUpdateCommunity);
    on<SaveSpacesEvent>(_onSaveSpaces);
    on<FetchProductsEvent>(_onFetchProducts);
    on<SelectSpaceEvent>(_onSelectSpace);
    on<NewCommunityEvent>(_onNewCommunity);
    on<BlankStateEvent>(_onBlankState);
    on<SpaceModelLoadEvent>(_onLoadSpaceModel);
    on<UpdateSpaceModelCache>(_updateSpaceModelCache);
    on<DeleteSpaceModelFromCache>(_deleteSpaceModelFromCache);
  }

  Future<void> _updateSpaceModelCache(
      UpdateSpaceModelCache event, Emitter<SpaceManagementState> emit) async {
    final projectUuid = await ProjectManager.getProjectUUID() ?? '';

    List<SpaceTemplateModel> allSpaceModels = [];

    bool hasNext = true;
    int page = 1;

    while (hasNext) {
      final spaceModels = await _spaceModelApi.listSpaceModels(
          page: page, projectId: projectUuid);
      if (spaceModels.isNotEmpty) {
        allSpaceModels.addAll(spaceModels);
        page++;
      } else {
        hasNext = false;
      }
    }

    _cachedSpaceModels = allSpaceModels;
    await fetchTags();

    emit(SpaceModelLoaded(
        communities: state is SpaceManagementLoaded
            ? (state as SpaceManagementLoaded).communities
            : [],
        products: _cachedProducts ?? [],
        spaceModels: List.from(_cachedSpaceModels ?? []),
        allTags: _cachedTags ?? []));
  }

  void _deleteSpaceModelFromCache(DeleteSpaceModelFromCache event,
      Emitter<SpaceManagementState> emit) async {
    if (_cachedSpaceModels != null) {
      _cachedSpaceModels = _cachedSpaceModels!
          .where((model) => model.uuid != event.deletedUuid)
          .toList();
    } else {
      _cachedSpaceModels = await fetchSpaceModels();
    }
    await fetchTags();

    emit(SpaceModelLoaded(
        communities: state is SpaceManagementLoaded
            ? (state as SpaceManagementLoaded).communities
            : [],
        products: _cachedProducts ?? [],
        spaceModels: List.from(_cachedSpaceModels ?? []),
        allTags: _cachedTags ?? []));
  }

  void updateCachedSpaceModels(List<SpaceTemplateModel> updatedModels) {
    _cachedSpaceModels = List.from(updatedModels);
  }

  void addToCachedSpaceModels(SpaceTemplateModel newModel) {
    _cachedSpaceModels?.add(newModel);
  }

  Future<List<SpaceTemplateModel>> fetchSpaceModels() async {
    try {
      if (_cachedSpaceModels != null) {
        return _cachedSpaceModels!;
      }

      final projectUuid = await ProjectManager.getProjectUUID() ?? '';

      List<SpaceTemplateModel> allSpaceModels = [];

      bool hasNext = true;
      int page = 1;

      while (hasNext) {
        final spaceModels = await _spaceModelApi.listSpaceModels(
            page: page, projectId: projectUuid);
        if (spaceModels.isNotEmpty) {
          allSpaceModels.addAll(spaceModels);
          page++;
        } else {
          hasNext = false;
        }
      }

      _cachedSpaceModels = allSpaceModels;

      return allSpaceModels;
    } catch (e) {
      return [];
    }
  }

  Future<List<Tag>> fetchTags() async {
    try {
      if (_cachedTags != null) {
        return _cachedTags!;
      }
      final projectUuid = await ProjectManager.getProjectUUID() ?? '';
      final allTags = await _spaceModelApi.listTags(projectId: projectUuid);
      _cachedTags = allTags;
      return allTags;
    } catch (e) {
      return [];
    }
  }

  void _onUpdateCommunity(
    UpdateCommunityEvent event,
    Emitter<SpaceManagementState> emit,
  ) async {
    final previousState = state;
    try {
      final projectUuid = await ProjectManager.getProjectUUID() ?? '';
      await fetchTags();

      emit(SpaceManagementLoading());
      final success = await _api.updateCommunity(
          event.communityUuid, event.name, projectUuid);
      if (success) {
        if (previousState is SpaceManagementLoaded) {
          final updatedCommunities =
              List<CommunityModel>.from(previousState.communities);
          for (var community in updatedCommunities) {
            if (community.uuid == event.communityUuid) {
              community.name = event.name;
              _spaceTreeBloc.add(OnCommunityAdded(community));

              break;
            }
          }

          var prevSpaceModels = await fetchSpaceModels();

          emit(SpaceManagementLoaded(
              communities: updatedCommunities,
              products: previousState.products,
              selectedCommunity: previousState.selectedCommunity,
              spaceModels: prevSpaceModels,
              allTags: _cachedTags ?? []));
        }
      } else {
        emit(const SpaceManagementError('Failed to update the community.'));
      }
    } catch (e) {
      emit(SpaceManagementError('Error updating community: $e'));
    }
  }

  void _onloadProducts() async {
    if (_cachedProducts == null) {
      final products = await _productApi.fetchProducts();
      _cachedProducts = products;
    }
  }

  void _onFetchProducts(
    FetchProductsEvent event,
    Emitter<SpaceManagementState> emit,
  ) async {
    try {
      _onloadProducts();
    } catch (e) {
      emit(SpaceManagementError('Error fetching products: $e'));
    }
  }

  Future<List<SpaceModel>> _fetchSpacesForCommunity(
      String communityUuid) async {
    final projectUuid = await ProjectManager.getProjectUUID() ?? '';

    return await _api.getSpaceHierarchy(communityUuid, projectUuid);
  }

  Future<void> _onNewCommunity(
    NewCommunityEvent event,
    Emitter<SpaceManagementState> emit,
  ) async {
    try {
      await fetchTags();

      if (event.communities.isEmpty) {
        emit(const SpaceManagementError('No communities provided.'));
        return;
      }

      var prevSpaceModels = await fetchSpaceModels();

      emit(BlankState(
          communities: event.communities,
          products: _cachedProducts ?? [],
          spaceModels: prevSpaceModels,
          allTags: _cachedTags ?? []));
    } catch (error) {
      emit(SpaceManagementError('Error loading communities: $error'));
    }
  }

  Future<void> _onBlankState(
      BlankStateEvent event, Emitter<SpaceManagementState> emit) async {
    try {
      final previousState = state;
      final projectUuid = await ProjectManager.getProjectUUID() ?? '';
      var spaceBloc = event.context.read<SpaceTreeBloc>();
      var spaceTreeState = event.context.read<SpaceTreeBloc>().state;

      List<CommunityModel> communities =
          await _waitForCommunityList(spaceBloc, spaceTreeState);
      await fetchSpaceModels();
      // await fetchTags();

      var prevSpaceModels = await fetchSpaceModels();

      if (previousState is SpaceManagementLoaded ||
          previousState is BlankState) {
        final prevCommunities = (previousState as dynamic).communities ?? [];
        emit(BlankState(
            communities: List<CommunityModel>.from(prevCommunities),
            products: _cachedProducts ?? [],
            spaceModels: prevSpaceModels,
            allTags: _cachedTags ?? []));
        return;
      }

      emit(BlankState(
        spaceModels: prevSpaceModels,
        communities: communities,
        products: _cachedProducts ?? [],
        allTags: _cachedTags ?? [],
      ));
    } catch (error) {
      emit(SpaceManagementError('Error loading communities: $error'));
    }
  }

  void _onLoadCommunityAndSpaces(
    LoadCommunityAndSpacesEvent event,
    Emitter<SpaceManagementState> emit,
  ) async {
    var spaceTreeState = event.context.read<SpaceTreeBloc>().state;
    var spaceBloc = event.context.read<SpaceTreeBloc>();

    _onloadProducts();
    await fetchTags();
    // Wait until `communityList` is loaded
    List<CommunityModel> communities =
        await _waitForCommunityList(spaceBloc, spaceTreeState);

    // Fetch space models after communities are available
    final prevSpaceModels = await fetchSpaceModels();
    emit(SpaceManagementLoaded(
        communities: communities,
        products: _cachedProducts ?? [],
        spaceModels: prevSpaceModels,
        allTags: _cachedTags ?? []));
  }

  Future<List<CommunityModel>> _waitForCommunityList(
      SpaceTreeBloc spaceBloc, SpaceTreeState spaceTreeState) async {
    // Check if communityList is already populated
    final filteredCommunities = spaceTreeState.searchQuery.isNotEmpty
        ? spaceTreeState.filteredCommunity
        : spaceTreeState.communityList;
    if (filteredCommunities.isNotEmpty) {
      return filteredCommunities;
    }

    final completer = Completer<List<CommunityModel>>();
    final subscription = spaceBloc.stream.listen((state) {
      if (!completer.isCompleted && state.communityList.isNotEmpty) {
        completer.complete(state.searchQuery.isNotEmpty
            ? state.filteredCommunity
            : state.communityList);
      }
    });
    try {
      final communities = await completer.future.timeout(
        const Duration(seconds: 10),
        onTimeout: () {
          if (!completer.isCompleted) {
            completer.complete([]);
          }
          return [];
        },
      );

      return communities;
    } finally {
      await subscription.cancel();
    }
  }

  void _onCommunityDelete(
    DeleteCommunityEvent event,
    Emitter<SpaceManagementState> emit,
  ) async {
    try {
      emit(SpaceManagementLoading());
      final projectUuid = await ProjectManager.getProjectUUID() ?? '';

      final success =
          await _api.deleteCommunity(event.communityUuid, projectUuid);
      if (success) {
        //  add(LoadCommunityAndSpacesEvent());
      } else {
        emit(const SpaceManagementError('Failed to delete the community.'));
      }
    } catch (e) {
      // Handle unexpected errors
      emit(SpaceManagementError('Error saving spaces: $e'));
    }
  }

  void _onCreateCommunity(
    CreateCommunityEvent event,
    Emitter<SpaceManagementState> emit,
  ) async {
    final previousState = state;
    emit(SpaceManagementLoading());

    try {
      final projectUuid = await ProjectManager.getProjectUUID() ?? '';
      await fetchTags();
      CommunityModel? newCommunity = await _api.createCommunity(
          event.name, event.description, projectUuid);
      var prevSpaceModels = await fetchSpaceModels();

      if (newCommunity != null) {
        if (previousState is SpaceManagementLoaded ||
            previousState is BlankState) {
          final prevCommunities = List<CommunityModel>.from(
            (previousState as dynamic).communities,
          );
          final updatedCommunities = prevCommunities..add(newCommunity);
          _spaceTreeBloc.add(OnCommunityAdded(newCommunity));

          emit(SpaceManagementLoaded(
            spaceModels: prevSpaceModels,
            communities: updatedCommunities,
            products: _cachedProducts ?? [],
            selectedCommunity: newCommunity,
            selectedSpace: null,
            allTags: _cachedTags ?? [],
          ));
        }
      } else {
        emit(const SpaceManagementError('Error creating community'));
      }
    } catch (e) {
      emit(SpaceManagementError('Error creating community: $e'));
    }
  }

  void _onSelectCommunity(
    SelectCommunityEvent event,
    Emitter<SpaceManagementState> emit,
  ) async {
    try {
      _handleCommunitySpaceStateUpdate(
        emit: emit,
        selectedCommunity: event.selectedCommunity,
        selectedSpace: null,
      );
    } catch (e) {
      emit(SpaceManagementError('Error updating state: $e'));
    }
  }

  void _onSelectSpace(
    SelectSpaceEvent event,
    Emitter<SpaceManagementState> emit,
  ) {
    _handleCommunitySpaceStateUpdate(
      emit: emit,
      selectedCommunity: event.selectedCommunity,
      selectedSpace: event.selectedSpace,
    );
  }

  void _handleCommunitySpaceStateUpdate({
    required Emitter<SpaceManagementState> emit,
    CommunityModel? selectedCommunity,
    SpaceModel? selectedSpace,
  }) async {
    final previousState = state;
    emit(SpaceManagementLoading());

    try {
      await fetchTags();
      if (previousState is SpaceManagementLoaded ||
          previousState is BlankState ||
          previousState is SpaceModelLoaded) {
        final communities = List<CommunityModel>.from(
          (previousState as dynamic).communities,
        );

        final spaceModels = List<SpaceTemplateModel>.from(
          (previousState as dynamic).spaceModels,
        );
        emit(SpaceManagementLoaded(
            communities: communities,
            products: _cachedProducts ?? [],
            selectedCommunity: selectedCommunity,
            selectedSpace: selectedSpace,
            spaceModels: spaceModels,
            allTags: _cachedTags ?? []));
      }
    } catch (e) {
      emit(SpaceManagementError('Error updating state: $e'));
    }
  }

  void _onSaveSpaces(
    SaveSpacesEvent event,
    Emitter<SpaceManagementState> emit,
  ) async {
    final previousState = state;
    emit(SpaceManagementLoading());

    try {
      final spaceTreeState = event.context.read<SpaceTreeBloc>().state;

      final updatedSpaces = await saveSpacesHierarchically(
          event.context, event.spaces, event.communityUuid);
      final allSpaces = await _fetchSpacesForCommunity(event.communityUuid);

      // emit(SpaceCreationSuccess(spaces: updatedSpaces));
      // updatedSpaces.forEach(
      //   (element) => element.uuid,
      // );
      // final lastUpdatedSpaced = updatedSpaces..addAll(allSpaces);
      if (previousState is SpaceManagementLoaded) {
        await _updateLoadedState(
          spaceTreeState,
          previousState,
          allSpaces,
          event.communityUuid,
          emit,
        );
        event.spaces.removeWhere(
          (space) => space.status == SpaceStatus.deleted,
        );
        event.spaces.forEach(
          (space) => space.status = SpaceStatus.unchanged,
        );
      }
    } catch (e) {
      // emit(SpaceManagementError('Error saving spaces: $e'));

      if (previousState is SpaceManagementLoaded) {
        emit(previousState);
      }
    }
  }

  Future<void> _updateLoadedState(
    SpaceTreeState spaceTreeState,
    SpaceManagementLoaded previousState,
    List<SpaceModel> allSpaces,
    String communityUuid,
    Emitter<SpaceManagementState> emit,
  ) async {
    try {
      var prevSpaceModels = await fetchSpaceModels();

      await fetchTags();

      final communities = spaceTreeState.searchQuery.isNotEmpty
          ? spaceTreeState.filteredCommunity
          : spaceTreeState.communityList;

      for (var community in communities) {
        if (community.uuid == communityUuid) {
          community.spaces = allSpaces;
          _spaceTreeBloc.add(InitialEvent());

          emit(SpaceManagementLoaded(
            communities: communities,
            products: _cachedProducts ?? [],
            selectedCommunity: community,
            selectedSpace: null,
            spaceModels: prevSpaceModels,
            allTags: _cachedTags ?? [],
          ));
          return;
        }
      }
      emit(previousState);
    } catch (e, stackTrace) {
      emit(previousState);
      // rethrow;
    }
  }

  Future<List<SpaceModel>> saveSpacesHierarchically(BuildContext context,
      List<SpaceModel> spaces, String communityUuid) async {
    final orderedSpaces = flattenHierarchy(spaces);

    final projectUuid = await ProjectManager.getProjectUUID() ?? '';
    CommunityModel? selectedCommunity;
    try {
      final spaceTreeState = context.read<SpaceTreeBloc>().state;
      final filteredCommunities = spaceTreeState.searchQuery.isNotEmpty
          ? spaceTreeState.filteredCommunity
          : spaceTreeState.communityList;

      selectedCommunity = filteredCommunities.firstWhere(
        (community) => community.uuid == communityUuid,
        orElse: () => CommunityModel(
          uuid: '',
          createdAt: DateTime.now(),
          updatedAt: DateTime.now(),
          name: '',
          description: '',
          spaces: spaces,
        ),
      );
    } catch (e) {
      return [];
    }

    final parentsToDelete = orderedSpaces.where((space) =>
        space.status == SpaceStatus.deleted &&
        (space.parent == null || space.parent?.status != SpaceStatus.deleted));

    for (var parent in parentsToDelete) {
      try {
        if (parent.uuid != null) {
          await _api.deleteSpace(communityUuid, parent.uuid!, projectUuid);
        }
      } catch (e) {}
    }
    orderedSpaces.removeWhere((space) => parentsToDelete.contains(space));

    for (var space in orderedSpaces) {
      try {
        if (space.uuid != null && space.uuid!.isNotEmpty) {
          List<TagModelUpdate> tagUpdates = [];

          List<SpaceModel> matchedSpaces =
              findMatchingSpaces(selectedCommunity.spaces, space.uuid!);

          if (matchedSpaces.isEmpty) continue;

          final prevSpace = matchedSpaces.elementAtOrNull(0);

          final List<UpdateSubspaceTemplateModel> subspaceUpdates = [];
          final List<SubspaceModel>? prevSubspaces = prevSpace?.subspaces;
          final List<SubspaceModel>? newSubspaces = space.subspaces;

          tagUpdates = processTagUpdates(prevSpace?.tags, space.tags);

          if (prevSubspaces != null || newSubspaces != null) {
            if (prevSubspaces != null && newSubspaces != null) {
              for (var prevSubspace in prevSubspaces) {
                final existsInNew = newSubspaces
                    .any((subspace) => subspace.uuid == prevSubspace.uuid);
                if (!existsInNew) {
                  subspaceUpdates.add(UpdateSubspaceTemplateModel(
                      action: custom_action.Action.delete,
                      uuid: prevSubspace.uuid));
                }
              }
            } else if (prevSubspaces != null && newSubspaces == null) {
              for (var prevSubspace in prevSubspaces) {
                subspaceUpdates.add(UpdateSubspaceTemplateModel(
                    action: custom_action.Action.delete,
                    uuid: prevSubspace.uuid));
              }
            }

            if (newSubspaces != null) {
              for (var newSubspace in newSubspaces) {
                // Tag without UUID
                if ((newSubspace.uuid == null || newSubspace.uuid!.isEmpty)) {
                  final List<TagModelUpdate> tagUpdates = [];

                  if (newSubspace.tags != null) {
                    for (var tag in newSubspace.tags!) {
                      tagUpdates.add(TagModelUpdate(
                          action: custom_action.Action.add,
                          newTagUuid: tag.uuid == '' ? null : tag.uuid,
                          tag: tag.tag,
                          productUuid: tag.product?.uuid));
                    }
                  }
                  subspaceUpdates.add(UpdateSubspaceTemplateModel(
                      action: custom_action.Action.add,
                      subspaceName: newSubspace.subspaceName,
                      tags: tagUpdates));
                }
              }
            }

            if (prevSubspaces != null && newSubspaces != null) {
              final newSubspaceMap = {
                for (var subspace in newSubspaces) subspace.uuid: subspace
              };

              for (var prevSubspace in prevSubspaces) {
                final newSubspace = newSubspaceMap[prevSubspace.uuid];

                if (newSubspace != null) {
                  final List<TagModelUpdate> tagSubspaceUpdates =
                      processTagUpdates(prevSubspace.tags, newSubspace.tags);
                  subspaceUpdates.add(UpdateSubspaceTemplateModel(
                      action: custom_action.Action.update,
                      uuid: newSubspace.uuid,
                      subspaceName: newSubspace.subspaceName,
                      tags: tagSubspaceUpdates));
                }
              }
            }
          }

          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,
              subspaces: space.subspaces,
              //  subspaceUpdates,
              tags: space.tags,
              //  tagUpdates,
              spaceModelUuid: space.spaceModel?.uuid,
              projectId: projectUuid);
        } else {
          // Call create if the space does not have a UUID
          List<CreateTagBodyModel> tagBodyModels = space.tags != null
              ? space.tags!.map((tag) => tag.toCreateTagBodyModel()).toList()
              : [];

          var createSubspaceBodyModels = space.subspaces?.map((subspace) {
                final tagBodyModels = subspace.tags
                        ?.map((tag) => tag.toCreateTagBodyModel())
                        .toList() ??
                    [];
                return CreateSubspaceModel()
                  ..subspaceName = subspace.subspaceName
                  ..tags = tagBodyModels;
              }).toList() ??
              [];

          if (space.spaceModel?.uuid != null) {
            tagBodyModels = [];
            createSubspaceBodyModels = [];
          }

          final response = await _api.createSpace(
              communityId: communityUuid,
              name: space.name,
              parentId: space.parent?.uuid,
              isPrivate: space.isPrivate,
              position: space.position,
              icon: space.icon,
              spaceModelUuid: space.spaceModel?.uuid,
              tags: tagBodyModels,
              subspaces: createSubspaceBodyModels,
              projectId: projectUuid);
          space.uuid = response?.uuid;
        }
      } catch (e) {
        return [];
        // Stop further execution on failure
      }
    }
    return spaces;
  }

  List<SpaceModel> flattenHierarchy(List<SpaceModel> spaces) {
    final result = <SpaceModel>{};
    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
  }

  void _onLoadSpaceModel(
      SpaceModelLoadEvent event, Emitter<SpaceManagementState> emit) async {
    emit(SpaceManagementLoading());

    try {
      await fetchTags();
      final spaceTreeState = event.context.read<SpaceTreeBloc>().state;
      final filteredCommunities = spaceTreeState.searchQuery.isNotEmpty
          ? spaceTreeState.filteredCommunity
          : spaceTreeState.communityList;

      List<CommunityModel> communities = filteredCommunities;

      var prevSpaceModels = await fetchSpaceModels();

      emit(SpaceModelLoaded(
          communities: communities,
          products: _cachedProducts ?? [],
          spaceModels: prevSpaceModels,
          allTags: _cachedTags ?? []));
    } catch (e) {
      emit(SpaceManagementError('Error loading communities and spaces: $e'));
    }
  }

  List<TagModelUpdate> processTagUpdates(
    List<Tag>? prevTags,
    List<Tag>? newTags,
  ) {
    final List<TagModelUpdate> tagUpdates = [];
    final processedTags = <String?>{};

    if (prevTags == null && newTags != null) {
      for (var newTag in newTags) {
        tagUpdates.add(TagModelUpdate(
          action: custom_action.Action.add,
          tag: newTag.tag,
          newTagUuid: newTag.uuid,
          productUuid: newTag.product?.uuid,
        ));
      }
      return tagUpdates;
    }

    if (newTags != null || prevTags != null) {
      // Case 1: Tags deleted
      if (prevTags != null && newTags != null) {
        for (var prevTag in prevTags) {
          final existsInNew =
              newTags.any((newTag) => newTag.uuid == prevTag.uuid);
          if (!existsInNew) {
            tagUpdates.add(TagModelUpdate(
                action: custom_action.Action.delete, uuid: prevTag.uuid));
          }
        }
      } else if (prevTags != null && newTags == null) {
        for (var prevTag in prevTags) {
          tagUpdates.add(TagModelUpdate(
              action: custom_action.Action.delete, uuid: prevTag.uuid));
        }
      }

      // Case 2: Tags added
      if (newTags != null) {
        final prevTagUuids = prevTags?.map((t) => t.uuid).toSet() ?? {};

        for (var newTag in newTags) {
          // Tag without UUID
          if ((newTag.uuid == null || !prevTagUuids.contains(newTag.uuid)) &&
              !processedTags.contains(newTag.tag)) {
            tagUpdates.add(TagModelUpdate(
                action: custom_action.Action.add,
                tag: newTag.tag,
                newTagUuid: newTag.uuid == '' ? null : newTag.uuid,
                productUuid: newTag.product?.uuid));
            processedTags.add(newTag.tag);
          }
        }
      }

      // Case 3: Tags updated
      if (prevTags != null && newTags != null) {
        final newTagMap = {for (var tag in newTags) tag.uuid: tag};

        for (var prevTag in prevTags) {
          final newTag = newTagMap[prevTag.uuid];
          if (newTag != null) {
            tagUpdates.add(TagModelUpdate(
              action: custom_action.Action.update,
              uuid: newTag.uuid,
              newTagUuid: newTag.uuid,
              tag: newTag.tag,
            ));
          } else {}
        }
      }
    }

    return tagUpdates;
  }

  List<SpaceModel> findMatchingSpaces(
      List<SpaceModel> spaces, String targetUuid) {
    List<SpaceModel> matched = [];

    for (var space in spaces) {
      if (space.uuid == targetUuid) {
        matched.add(space);
      }
      matched.addAll(findMatchingSpaces(
          space.children, targetUuid)); // Recursively search in children
    }

    return matched;
  }
}
