/// BLoC pour la gestion des adhésions (demandes d'adhésion)
library adhesions_bloc;

import 'package:dio/dio.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:injectable/injectable.dart';
import '../../../core/utils/logger.dart';
import '../data/models/adhesion_model.dart';
import '../data/repositories/adhesion_repository.dart';

part 'adhesions_event.dart';
part 'adhesions_state.dart';

@injectable
class AdhesionsBloc extends Bloc<AdhesionsEvent, AdhesionsState> {
  final AdhesionRepository _repository;

  AdhesionsBloc(this._repository) : super(const AdhesionsState()) {
    on<LoadAdhesions>(_onLoadAdhesions);
    on<LoadAdhesionsByMembre>(_onLoadAdhesionsByMembre);
    on<LoadAdhesionsEnAttente>(_onLoadAdhesionsEnAttente);
    on<LoadAdhesionsByStatut>(_onLoadAdhesionsByStatut);
    on<LoadAdhesionById>(_onLoadAdhesionById);
    on<CreateAdhesion>(_onCreateAdhesion);
    on<ApprouverAdhesion>(_onApprouverAdhesion);
    on<RejeterAdhesion>(_onRejeterAdhesion);
    on<EnregistrerPaiementAdhesion>(_onEnregistrerPaiementAdhesion);
    on<LoadAdhesionsStats>(_onLoadAdhesionsStats);
  }

  Future<void> _onLoadAdhesions(LoadAdhesions event, Emitter<AdhesionsState> emit) async {
    emit(state.copyWith(status: AdhesionsStatus.loading, message: 'Chargement...'));
    try {
      final list = await _repository.getAll(page: event.page, size: event.size);
      emit(state.copyWith(status: AdhesionsStatus.loaded, adhesions: list));
    } catch (e) {
      if (e is DioException && e.type == DioExceptionType.cancel) return;
      emit(state.copyWith(status: AdhesionsStatus.error, message: e.toString(), error: e));
    }
  }

  Future<void> _onLoadAdhesionsByMembre(LoadAdhesionsByMembre event, Emitter<AdhesionsState> emit) async {
    emit(state.copyWith(status: AdhesionsStatus.loading, message: 'Chargement...'));
    try {
      final list = await _repository.getByMembre(event.membreId, page: event.page, size: event.size);
      emit(state.copyWith(status: AdhesionsStatus.loaded, adhesions: list));
    } catch (e) {
      if (e is DioException && e.type == DioExceptionType.cancel) return;
      emit(state.copyWith(status: AdhesionsStatus.error, message: e.toString(), error: e));
    }
  }


  Future<void> _onLoadAdhesionsEnAttente(LoadAdhesionsEnAttente event, Emitter<AdhesionsState> emit) async {
    emit(state.copyWith(status: AdhesionsStatus.loading, message: 'Chargement...'));
    try {
      final list = await _repository.getEnAttente(page: event.page, size: event.size);
      emit(state.copyWith(status: AdhesionsStatus.loaded, adhesions: list));
    } catch (e) {
      if (e is DioException && e.type == DioExceptionType.cancel) return;
      emit(state.copyWith(status: AdhesionsStatus.error, message: e.toString(), error: e));
    }
  }

  Future<void> _onLoadAdhesionsByStatut(LoadAdhesionsByStatut event, Emitter<AdhesionsState> emit) async {
    emit(state.copyWith(status: AdhesionsStatus.loading, message: 'Chargement...'));
    try {
      final list = await _repository.getByStatut(event.statut, page: event.page, size: event.size);
      emit(state.copyWith(status: AdhesionsStatus.loaded, adhesions: list));
    } catch (e) {
      if (e is DioException && e.type == DioExceptionType.cancel) return;
      emit(state.copyWith(status: AdhesionsStatus.error, message: e.toString(), error: e));
    }
  }

  Future<void> _onLoadAdhesionById(LoadAdhesionById event, Emitter<AdhesionsState> emit) async {
    emit(state.copyWith(status: AdhesionsStatus.loading));
    try {
      final adhesion = await _repository.getById(event.id);
      emit(state.copyWith(status: AdhesionsStatus.loaded, adhesionDetail: adhesion));
    } catch (e) {
      if (e is DioException && e.type == DioExceptionType.cancel) return;
      emit(state.copyWith(status: AdhesionsStatus.error, message: e.toString(), error: e));
    }
  }

  Future<void> _onCreateAdhesion(CreateAdhesion event, Emitter<AdhesionsState> emit) async {
    emit(state.copyWith(status: AdhesionsStatus.loading, message: 'Création...'));
    try {
      await _repository.create(event.adhesion);
      add(const LoadAdhesions());
    } catch (e) {
      if (e is DioException && e.type == DioExceptionType.cancel) return;
      emit(state.copyWith(status: AdhesionsStatus.error, message: e.toString(), error: e));
    }
  }

  Future<void> _onApprouverAdhesion(ApprouverAdhesion event, Emitter<AdhesionsState> emit) async {
    emit(state.copyWith(status: AdhesionsStatus.loading));
    try {
      final updated = await _repository.approuver(event.id, approuvePar: event.approuvePar);
      emit(state.copyWith(status: AdhesionsStatus.loaded, adhesionDetail: updated));
      add(const LoadAdhesions());
    } catch (e) {
      if (e is DioException && e.type == DioExceptionType.cancel) return;
      emit(state.copyWith(status: AdhesionsStatus.error, message: e.toString(), error: e));
    }
  }

  Future<void> _onRejeterAdhesion(RejeterAdhesion event, Emitter<AdhesionsState> emit) async {
    emit(state.copyWith(status: AdhesionsStatus.loading));
    try {
      final updated = await _repository.rejeter(event.id, event.motifRejet);
      emit(state.copyWith(status: AdhesionsStatus.loaded, adhesionDetail: updated));
      add(const LoadAdhesions());
    } catch (e) {
      if (e is DioException && e.type == DioExceptionType.cancel) return;
      emit(state.copyWith(status: AdhesionsStatus.error, message: e.toString(), error: e));
    }
  }

  Future<void> _onEnregistrerPaiementAdhesion(EnregistrerPaiementAdhesion event, Emitter<AdhesionsState> emit) async {
    emit(state.copyWith(status: AdhesionsStatus.loading));
    try {
      final updated = await _repository.enregistrerPaiement(
        event.id,
        montantPaye: event.montantPaye,
        methodePaiement: event.methodePaiement,
        referencePaiement: event.referencePaiement,
      );
      emit(state.copyWith(status: AdhesionsStatus.loaded, adhesionDetail: updated));
      add(const LoadAdhesions());
    } catch (e) {
      if (e is DioException && e.type == DioExceptionType.cancel) return;
      emit(state.copyWith(status: AdhesionsStatus.error, message: e.toString(), error: e));
    }
  }

  Future<void> _onLoadAdhesionsStats(LoadAdhesionsStats event, Emitter<AdhesionsState> emit) async {
    try {
      final stats = await _repository.getStats();
      emit(state.copyWith(stats: stats));
    } catch (e, st) {
      if (e is DioException && e.type == DioExceptionType.cancel) return;
      AppLogger.error('AdhesionsBloc: chargement stats échoué', error: e, stackTrace: st);
      emit(state.copyWith(
        status: AdhesionsStatus.error,
        message: e.toString(),
        error: e,
      ));
    }
  }
}
