import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:image_picker/image_picker.dart';
import 'package:krow/core/application/clients/api/api_exception.dart';
import 'package:krow/core/application/di/injectable.dart';
import 'package:krow/features/profile/role_kit/data/models/mutate_kit_dto.dart';
import 'package:krow/features/profile/role_kit/data/staff_role_kit_repository.dart';
import 'package:krow/features/profile/role_kit/domain/bloc/role_kit_event.dart';
import 'package:krow/features/profile/role_kit/domain/bloc/role_kit_state.dart';
import 'package:krow/features/profile/role_kit/domain/role_kit_entity.dart';
import 'package:krow/features/profile/role_kit/domain/staff_role_kit_repository_impl.dart';

class RoleKitBloc extends Bloc<RoleKitEvent, RoleKitState> {
  RoleKitBloc() : super(RoleKitState()) {
    on<RoleKitEventFetch>(_onFetch);
    on<RoleKitEventSelectRole>(_onSelectRole);
    on<RoleKitEventSubmit>(_onSubmit);
    on<RoleKiEventChangeState>(_onChangeState);
    on<RoleKitEventUploadPhoto>(_onUploadPhoto);
    on<RoleKitEventDeletePhoto>(_onDeletePhoto);
  }

  Future<void> _onFetch(
      RoleKitEventFetch event, Emitter<RoleKitState> emit) async {
    emit(state.copyWith(roleKitType: event.type, loading: true));
    var roles = await getIt<StaffRoleKitRepository>().getStaffRole();
    emit(state.copyWith(roles: roles, loading: false));
  }

  Future<void> _onSelectRole(
      RoleKitEventSelectRole event, Emitter<RoleKitState> emit) async {
    List<RoleKitEntity> roleKitViewModels = [];

    var confirmedKits = state.roleKitType == RoleKitType.equipment
        ? event.role.confirmedEquipments
        : event.role.confirmedUniforms;




    (state.roleKitType == RoleKitType.equipment
            ? event.role.skill?.equipments
            : event.role.skill?.uniforms)
        ?.forEach((item) {
      var confirmed = confirmedKits
          ?.where((element) => element.skillKitId == item.id)
          .firstOrNull;
      roleKitViewModels.add(RoleKitEntity(
          id: item.id,
          title: item.name ?? '',
          confirmed: confirmed != null,
          imageUrl: confirmed?.photo,
          isMandatory: (item.isRequired ?? false) || (item.photoRequired ?? false),
          needPhoto: item.photoRequired ?? false));
    });

    emit(state.copyWith(
        selectedRole: event.role, roleKitItems: roleKitViewModels));
  }

  void _onChangeState(
      RoleKiEventChangeState event, Emitter<RoleKitState> emit) {
    event.item.confirmed = !event.item.confirmed;
    emit(state.copyWith(showError: false));
  }

  void _onUploadPhoto(
      RoleKitEventUploadPhoto event, Emitter<RoleKitState> emit) async {
    event.item.uploading = true;
    emit(state.copyWith(showError: false));
    try {
      var image = await ImagePicker().pickImage(source: ImageSource.gallery);
      if (image != null) {
        var imagePath = image.path;
        var result =
            await getIt<StaffRoleKitRepository>().uploadImage(imagePath);
        event.item.uploading = false;
        event.item.imageToken = result['token'];
        event.item.imageUrl = result['url'];
        event.item.localImage = imagePath;
      }
    } catch(e){
      if (e is DisplayableException) {
        emit(state.copyWith(apiError: e.message,loading: false));
      }
    }finally {
      event.item.uploading = false;
      emit(state.copyWith());
    }
  }

  void _onSubmit(RoleKitEventSubmit event, Emitter<RoleKitState> emit) async {
    final allMandatoryItemsChecked = state.roleKitItems
        .where((element) => element.isMandatory)
        .every((element) => element.confirmed);
    final allPhotoUploaded = state.roleKitItems
        .where((element) => element.needPhoto)
        .every((element) =>
            element.imageUrl != null || element.localImage != null);

    if (allMandatoryItemsChecked && allPhotoUploaded) {
      emit(state.copyWith(loading: true));

      var confirmed = state.roleKitItems
          .where((e) => e.confirmed)
          .map((e) => MutateKitDto(id: e.id, photo: e.imageToken ?? e.imageUrl))
          .toList();
      try {
        await getIt<StaffRoleKitRepository>()
            .putKit(
            state.selectedRole!.skill!.id, confirmed, state.roleKitType);

      }catch (e) {
        if (e is DisplayableException) {
          emit(state.copyWith(apiError: e.message));
        }
        return;
      } finally {
        emit(state.copyWith(loading: false));
      }
      emit(state.copyWith(success: true));
    } else {
      emit(state.copyWith(showError: true));
    }
  }

  void _onDeletePhoto(
      RoleKitEventDeletePhoto event, Emitter<RoleKitState> emit) {
    event.item.imageUrl = null;
    event.item.localImage = null;
    event.item.imageToken = null;
    emit(state.copyWith());
  }
}
