import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/models/bookable_space_model.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/params/non_bookable_spaces_params.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/service/non_bookable_spaces_service.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/service/send_bookable_spaces_to_api_params.dart';
import 'package:syncrow_web/pages/space_management_v2/main_module/shared/models/paginated_data_model.dart';

part 'non_bookaable_spaces_event.dart';
part 'non_bookaable_spaces_state.dart';

class NonBookableSpacesBloc
    extends Bloc<NonBookableSpacesEvent, NonBookableSpacesState> {
  NonBookableSpacesService nonBookableSpacesService;
  List<BookableSpacemodel> selectedBookableSpaces = [];
  NonBookableSpacesBloc(this.nonBookableSpacesService)
      : super(NonBookableSpacesInitial()) {
    on<LoadUnBookableSpacesEvent>(_onLoadUnBookableSpacesEvent);
    on<AddToBookableSpaceEvent>(_onAddToBookableSpaceEvent);
    on<RemoveFromBookableSpaceEvent>(_onRemoveFromBookableSpaceEvent);
    on<SendBookableSpacesToApi>(_onSendBookableSpacesToApi);
    on<CheckConfigurValidityEvent>(_onCheckConfigurValidityEvent);
  }

  TimeOfDay? get endTime =>
      selectedBookableSpaces.first.spaceConfig!.bookingEndTime;

  TimeOfDay? get startTime =>
      selectedBookableSpaces.first.spaceConfig!.bookingStartTime;
  Future<void> _onLoadUnBookableSpacesEvent(LoadUnBookableSpacesEvent event,
      Emitter<NonBookableSpacesState> emit) async {
    if (state is NonBookableSpacesLoaded) {
      final currState = state as NonBookableSpacesLoaded;
      try {
        emit(NonBookableSpacesLoading(
            lastNonBookableSpaces: currState.nonBookableSpaces));

        final nonBookableSpacesList = await nonBookableSpacesService.load(
          event.nonBookableSpacesParams,
        );
        nonBookableSpacesList.data.addAll(currState.nonBookableSpaces.data);

        emit(
          NonBookableSpacesLoaded(nonBookableSpaces: nonBookableSpacesList),
        );
      } catch (e) {
        emit(
          NonBookableSpacesError(e.toString()),
        );
      }
    } else {
      try {
        emit(const NonBookableSpacesLoading());
        final nonBookableSpacesList = await nonBookableSpacesService.load(
          event.nonBookableSpacesParams,
        );
        emit(
          NonBookableSpacesLoaded(nonBookableSpaces: nonBookableSpacesList),
        );
      } catch (e) {
        emit(
          NonBookableSpacesError(e.toString()),
        );
      }
    }
  }

  void _onAddToBookableSpaceEvent(
    AddToBookableSpaceEvent event,
    Emitter<NonBookableSpacesState> emit,
  ) {
    if (state is NonBookableSpacesLoaded) {
      final currentState = state as NonBookableSpacesLoaded;
      emit(AddNonBookableSpaceIntoBookableState());
      final updatedSelectedSpaces =
          List<BookableSpacemodel>.from(currentState.selectedBookableSpaces)
            ..add(event.nonBookableSpace);

      selectedBookableSpaces.add(event.nonBookableSpace);

      emit(
        NonBookableSpacesLoaded(
          nonBookableSpaces: currentState.nonBookableSpaces,
          selectedBookableSpaces: updatedSelectedSpaces,
        ),
      );
    }
  }

  void _onRemoveFromBookableSpaceEvent(RemoveFromBookableSpaceEvent event,
      Emitter<NonBookableSpacesState> emit) {
    if (state is NonBookableSpacesLoaded) {
      final currentState = state as NonBookableSpacesLoaded;
      emit(RemoveBookableSpaceIntoNonBookableState());
      if (currentState.selectedBookableSpaces.isNotEmpty) {
        currentState.selectedBookableSpaces.remove(event.bookableSpace);
      }
      selectedBookableSpaces.remove(event.bookableSpace);
      emit(
        NonBookableSpacesLoaded(
          nonBookableSpaces: currentState.nonBookableSpaces,
          selectedBookableSpaces: currentState.selectedBookableSpaces,
        ),
      );
    }
  }

  Future<void> _onSendBookableSpacesToApi(SendBookableSpacesToApi event,
      Emitter<NonBookableSpacesState> emit) async {
    emit(const NonBookableSpacesLoading());
    try {
      await nonBookableSpacesService.sendBookableSpacesToApi(
        SendBookableSpacesToApiParams.fromBookableSpacesModel(
          selectedBookableSpaces,
        ),
      );
      emit(NonBookableSpacesInitial());
    } catch (e) {
      emit(
        NonBookableSpacesError(e.toString()),
      );
    }
  }

  void _onCheckConfigurValidityEvent(
      CheckConfigurValidityEvent event, Emitter<NonBookableSpacesState> emit) {
    if (selectedBookableSpaces.first.spaceConfig!.isValid) {
      emit(ValidSaveButtonState());
    } else {
      emit(UnValidSaveButtonState());
    }
  }
}
