library admin_users_bloc;

import 'package:dio/dio.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:injectable/injectable.dart';
import '../data/models/admin_user_model.dart';
import '../data/repositories/admin_user_repository.dart';
part 'admin_users_event.dart';
part 'admin_users_state.dart';

@injectable
class AdminUsersBloc extends Bloc<AdminUsersEvent, AdminUsersState> {
  final AdminUserRepository _repository;

  AdminUsersBloc(this._repository) : super(AdminUsersInitial()) {
    on<AdminUsersLoadRequested>(_onLoadRequested);
    on<AdminUserDetailRequested>(_onDetailRequested);
    on<AdminUserDetailWithRolesRequested>(_onDetailWithRolesRequested);
    on<AdminUserRolesUpdateRequested>(_onRolesUpdateRequested);
    on<AdminRolesLoadRequested>(_onRolesLoadRequested);
  }

  Future<void> _onLoadRequested(AdminUsersLoadRequested e, Emitter<AdminUsersState> emit) async {
    emit(AdminUsersLoading());
    try {
      final result = await _repository.search(
        page: e.page,
        size: e.size,
        search: e.search,
      );
      emit(AdminUsersLoaded(
        users: result.users,
        totalCount: result.totalCount,
        currentPage: result.currentPage,
        pageSize: result.pageSize,
        totalPages: result.totalPages,
      ));
    } catch (err) {
      if (err is DioException && err.type == DioExceptionType.cancel) return;
      emit(AdminUsersError(err.toString()));
    }
  }

  Future<void> _onDetailRequested(AdminUserDetailRequested e, Emitter<AdminUsersState> emit) async {
    emit(AdminUsersLoading());
    try {
      final user = await _repository.getById(e.userId);
      if (user == null) {
        emit(AdminUsersError('Utilisateur non trouvé'));
        return;
      }
      final roles = await _repository.getUserRoles(e.userId);
      emit(AdminUserDetailLoaded(user: user, userRoles: roles));
    } catch (err) {
      if (err is DioException && err.type == DioExceptionType.cancel) return;
      emit(AdminUsersError(err.toString()));
    }
  }

  Future<void> _onDetailWithRolesRequested(AdminUserDetailWithRolesRequested e, Emitter<AdminUsersState> emit) async {
    emit(AdminUsersLoading());
    try {
      final user = await _repository.getById(e.userId);
      if (user == null) {
        emit(AdminUsersError('Utilisateur non trouvé'));
        return;
      }
      final userRoles = await _repository.getUserRoles(e.userId);
      final allRoles = await _repository.getRealmRoles();
      emit(AdminUserDetailLoaded(user: user, userRoles: userRoles, allRoles: allRoles));
    } catch (err) {
      if (err is DioException && err.type == DioExceptionType.cancel) return;
      emit(AdminUsersError(err.toString()));
    }
  }

  Future<void> _onRolesUpdateRequested(AdminUserRolesUpdateRequested e, Emitter<AdminUsersState> emit) async {
    try {
      await _repository.setUserRoles(e.userId, e.roleNames);
      emit(AdminUserRolesUpdated());
      add(AdminUserDetailWithRolesRequested(e.userId));
    } catch (err) {
      if (err is DioException && err.type == DioExceptionType.cancel) return;
      emit(AdminUsersError(err.toString()));
    }
  }

  Future<void> _onRolesLoadRequested(AdminRolesLoadRequested e, Emitter<AdminUsersState> emit) async {
    try {
      final roles = await _repository.getRealmRoles();
      emit(AdminRolesLoaded(roles));
    } catch (err) {
      if (err is DioException && err.type == DioExceptionType.cancel) return;
      emit(AdminUsersError(err.toString()));
    }
  }
}
