import 'package:dio/dio.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:injectable/injectable.dart';
import '../domain/entities/type_reference_entity.dart';
import '../domain/usecases/get_org_types.dart';
import '../domain/usecases/create_org_type.dart';
import '../domain/usecases/update_org_type.dart';
import '../domain/usecases/delete_org_type.dart';

part 'org_types_event.dart';
part 'org_types_state.dart';

@injectable
class OrgTypesBloc extends Bloc<OrgTypesEvent, OrgTypesState> {
  final GetOrgTypes _getOrgTypes;
  final CreateOrgType _createOrgType;
  final UpdateOrgType _updateOrgType;
  final DeleteOrgType _deleteOrgType;

  OrgTypesBloc(
    this._getOrgTypes,
    this._createOrgType,
    this._updateOrgType,
    this._deleteOrgType,
  ) : super(const OrgTypesInitial()) {
    on<LoadOrgTypes>(_onLoad);
    on<CreateOrgTypeEvent>(_onCreate);
    on<UpdateOrgTypeEvent>(_onUpdate);
    on<DeleteOrgTypeEvent>(_onDelete);
  }

  Future<void> _onLoad(LoadOrgTypes event, Emitter<OrgTypesState> emit) async {
    emit(const OrgTypesLoading());
    try {
      final types = await _getOrgTypes();
      emit(OrgTypesLoaded(types));
    } catch (e) {
      if (e is DioException && e.type == DioExceptionType.cancel) return;
      emit(OrgTypesError(e.toString()));
    }
  }

  Future<void> _onCreate(CreateOrgTypeEvent event, Emitter<OrgTypesState> emit) async {
    final current = state is OrgTypesLoaded ? (state as OrgTypesLoaded).types : <TypeReferenceEntity>[];
    emit(OrgTypeOperating(List.from(current)));
    try {
      await _createOrgType(
        code: event.code,
        libelle: event.libelle,
        description: event.description,
        couleur: event.couleur,
        ordreAffichage: event.ordreAffichage,
      );
      final types = await _getOrgTypes();
      emit(OrgTypeSuccess(types: types, message: 'Type créé avec succès'));
    } catch (e) {
      if (e is DioException && e.type == DioExceptionType.cancel) return;
      emit(OrgTypeOperationError(types: List.from(current), message: e.toString()));
    }
  }

  Future<void> _onUpdate(UpdateOrgTypeEvent event, Emitter<OrgTypesState> emit) async {
    final current = state is OrgTypesLoaded ? (state as OrgTypesLoaded).types : <TypeReferenceEntity>[];
    emit(OrgTypeOperating(List.from(current)));
    try {
      await _updateOrgType(
        id: event.id,
        code: event.code,
        libelle: event.libelle,
        description: event.description,
        couleur: event.couleur,
        ordreAffichage: event.ordreAffichage,
      );
      final types = await _getOrgTypes();
      emit(OrgTypeSuccess(types: types, message: 'Type modifié avec succès'));
    } catch (e) {
      if (e is DioException && e.type == DioExceptionType.cancel) return;
      emit(OrgTypeOperationError(types: List.from(current), message: e.toString()));
    }
  }

  Future<void> _onDelete(DeleteOrgTypeEvent event, Emitter<OrgTypesState> emit) async {
    final current = state is OrgTypesLoaded ? (state as OrgTypesLoaded).types : <TypeReferenceEntity>[];
    emit(OrgTypeOperating(List.from(current)));
    try {
      await _deleteOrgType(event.id);
      final types = await _getOrgTypes();
      emit(OrgTypeSuccess(types: types, message: 'Type supprimé'));
    } catch (e) {
      if (e is DioException && e.type == DioExceptionType.cancel) return;
      emit(OrgTypeOperationError(types: List.from(current), message: e.toString()));
    }
  }
}
