import 'package:bloc/bloc.dart';
import 'package:krow_core/core.dart';
import '../../../domain/usecases/apply_for_shift_usecase.dart';
import '../../../domain/usecases/decline_shift_usecase.dart';
import '../../../domain/usecases/get_shift_details_usecase.dart';
import '../../../domain/arguments/get_shift_details_arguments.dart';
import 'shift_details_event.dart';
import 'shift_details_state.dart';

class ShiftDetailsBloc extends Bloc<ShiftDetailsEvent, ShiftDetailsState>
    with BlocErrorHandler<ShiftDetailsState> {
  final GetShiftDetailsUseCase getShiftDetails;
  final ApplyForShiftUseCase applyForShift;
  final DeclineShiftUseCase declineShift;

  ShiftDetailsBloc({
    required this.getShiftDetails,
    required this.applyForShift,
    required this.declineShift,
  }) : super(ShiftDetailsInitial()) {
    on<LoadShiftDetailsEvent>(_onLoadDetails);
    on<BookShiftDetailsEvent>(_onBookShift);
    on<DeclineShiftDetailsEvent>(_onDeclineShift);
  }

  Future<void> _onLoadDetails(
    LoadShiftDetailsEvent event,
    Emitter<ShiftDetailsState> emit,
  ) async {
    emit(ShiftDetailsLoading());
    await handleError(
      emit: emit,
      action: () async {
        final shift = await getShiftDetails(
          GetShiftDetailsArguments(shiftId: event.shiftId, roleId: event.roleId),
        );
        if (shift != null) {
          emit(ShiftDetailsLoaded(shift));
        } else {
          emit(const ShiftDetailsError("Shift not found"));
        }
      },
      onError: (String errorKey) => ShiftDetailsError(errorKey),
    );
  }

  Future<void> _onBookShift(
    BookShiftDetailsEvent event,
    Emitter<ShiftDetailsState> emit,
  ) async {
    await handleError(
      emit: emit,
      action: () async {
        await applyForShift(
          event.shiftId,
          isInstantBook: true,
          roleId: event.roleId,
        );
        emit(
          ShiftActionSuccess("Shift successfully booked!", shiftDate: event.date),
        );
      },
      onError: (String errorKey) => ShiftDetailsError(errorKey),
    );
  }

  Future<void> _onDeclineShift(
    DeclineShiftDetailsEvent event,
    Emitter<ShiftDetailsState> emit,
  ) async {
    await handleError(
      emit: emit,
      action: () async {
        await declineShift(event.shiftId);
        emit(const ShiftActionSuccess("Shift declined"));
      },
      onError: (String errorKey) => ShiftDetailsError(errorKey),
    );
  }
}

