import 'package:bloc/bloc.dart';
import 'package:krow/core/data/models/event/business_member_model.dart';
import 'package:krow/core/data/models/event/full_address_model.dart';
import 'package:krow/core/entity/position_entity.dart';
import 'package:krow/core/entity/shift_entity.dart';
import 'package:krow/features/create_event/domain/google_places_service.dart';
import 'package:krow/features/create_event/presentation/create_role_section/bloc/create_role_bloc.dart';
import 'package:meta/meta.dart';

part 'create_shift_details_event.dart';
part 'create_shift_details_state.dart';

class CreateShiftDetailsBloc
    extends Bloc<CreateShiftDetailsEvent, CreateShiftDetailsState> {
  CreateShiftDetailsBloc({required bool expanded})
      : super(CreateShiftDetailsState(
            suggestions: [],
            isExpanded: expanded,
            shift: ShiftEntity.empty(),
            roles: [
              RoleViewModel(
                  id: DateTime.now().millisecondsSinceEpoch.toString(),
                  bloc: CreateRoleBloc()),
            ])) {
    on<CreateShiftInitializeEvent>(_onInitialize);
    on<CreateShiftAddressQueryChangedEvent>(_onQueryChanged);
    on<CreateShiftAddressSelectEvent>(_onAddressSelect);
    on<CreateShiftSelectContactEvent>(_onSelectContact);
    on<CreateShiftRemoveContactEvent>(_onRemoveContact);
    on<CreateEventAddRoleEvent>(_onAddRole);
    on<DeleteRoleDeleteEvent>(_onDeleteRole);
    on<ExpandShiftEvent>(_onExpandShift);
    on<ValidationFailedEvent>((event, emit) {
      emit(state.copyWith(validationState: event.validationState));
    });
  }

  void _onInitialize(CreateShiftInitializeEvent event, emit) async {
    emit(CreateShiftDetailsState(
        suggestions: [],
        isExpanded: state.isExpanded,
        shift: event.shift,
        roles: [
          ...event.shift.positions.map((roleEntity) => RoleViewModel(
              id: roleEntity.id,
              bloc: CreateRoleBloc()
                ..add(
                  CreateRoleInitEvent(roleEntity),
                ))),
        ]));
  }

  void _onQueryChanged(CreateShiftAddressQueryChangedEvent event, emit) async {
    try {
      final googlePlacesService = GooglePlacesService();
      final suggestions =
          await googlePlacesService.fetchSuggestions(event.query);
      emit(state.copyWith(suggestions: suggestions));
    } catch (e) {
      print(e);
    }
  }

  void _onAddressSelect(CreateShiftAddressSelectEvent event, emit) async {
    if (event.address != null) {
      emit(state.copyWith(
          suggestions: [],
          shift: state.shift.copyWith(fullAddress: event.address!)));
      return;
    }

    if (event.place != null) {
      final googlePlacesService = GooglePlacesService();
      final fullAddress =
          await googlePlacesService.getPlaceDetails(event.place!.placeId);
      FullAddress address = FullAddress.fromGoogle(fullAddress);
      emit(state.copyWith(
          suggestions: [], shift: state.shift.copyWith(fullAddress: address)));
      return;
    }
  }

  void _onSelectContact(CreateShiftSelectContactEvent event, emit) {
    emit(state.copyWith(
        shift: state.shift
            .copyWith(managers: [...state.shift.managers, event.contact])));
  }

  void _onRemoveContact(CreateShiftRemoveContactEvent event, emit) {
    emit(state.copyWith(
        shift: state.shift.copyWith(
            managers: state.shift.managers
                .where((element) => element != event.contact)
                .toList())));
  }

  void _onAddRole(CreateEventAddRoleEvent event, emit) {
    final id = DateTime.now().millisecondsSinceEpoch.toString();
    final bloc = CreateRoleBloc();

    PositionEntity newPosition = PositionEntity.empty();

    bloc.add(CreateRoleInitEvent(newPosition));

    newPosition.parentShift = state.shift;
    state.shift.positions.add(newPosition);

    emit(state.copyWith(
      roles: [
        ...state.roles,
        RoleViewModel(id: id, bloc: bloc),
      ],
    ));
  }

  void _onDeleteRole(DeleteRoleDeleteEvent event, emit) {
    emit(state.copyWith(
      roles: state.roles.where((element) => element.id != event.id).toList(),
    ));
  }

  void _onExpandShift(ExpandShiftEvent event, emit) {
    emit(state.copyWith(isExpanded: !state.isExpanded));
  }
}
