/// BLoC pour la gestion des approbations de transactions
library approval_bloc;

import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:injectable/injectable.dart';
import '../../domain/usecases/get_pending_approvals.dart';
import '../../domain/usecases/approve_transaction.dart';
import '../../domain/usecases/reject_transaction.dart';
import '../../domain/usecases/get_approval_by_id.dart';
import 'approval_event.dart';
import 'approval_state.dart';

@injectable
class ApprovalBloc extends Bloc<ApprovalEvent, ApprovalState> {
  final GetPendingApprovals getPendingApprovals;
  final GetApprovalById getApprovalById;
  final ApproveTransaction approveTransaction;
  final RejectTransaction rejectTransaction;

  ApprovalBloc({
    required this.getPendingApprovals,
    required this.getApprovalById,
    required this.approveTransaction,
    required this.rejectTransaction,
  }) : super(const ApprovalInitial()) {
    on<LoadPendingApprovals>(_onLoadPendingApprovals);
    on<LoadApprovalById>(_onLoadApprovalById);
    on<ApproveTransactionEvent>(_onApproveTransaction);
    on<RejectTransactionEvent>(_onRejectTransaction);
    on<RefreshApprovals>(_onRefreshApprovals);
  }

  Future<void> _onLoadPendingApprovals(
    LoadPendingApprovals event,
    Emitter<ApprovalState> emit,
  ) async {
    emit(const ApprovalsLoading());

    final result = await getPendingApprovals(
      organizationId: event.organizationId,
    );

    result.fold(
      (failure) => emit(ApprovalError(failure.message)),
      (approvals) {
        if (approvals.isEmpty) {
          emit(const ApprovalsEmpty());
        } else {
          emit(ApprovalsLoaded(
            approvals: approvals,
            pendingCount: approvals.length,
          ));
        }
      },
    );
  }

  Future<void> _onLoadApprovalById(
    LoadApprovalById event,
    Emitter<ApprovalState> emit,
  ) async {
    emit(const ApprovalsLoading());

    final result = await getApprovalById(event.approvalId);

    result.fold(
      (failure) => emit(ApprovalError(failure.message)),
      (approval) => emit(ApprovalDetailLoaded(approval)),
    );
  }

  Future<void> _onApproveTransaction(
    ApproveTransactionEvent event,
    Emitter<ApprovalState> emit,
  ) async {
    emit(const ApprovalActionInProgress('approve'));

    final result = await approveTransaction(
      approvalId: event.approvalId,
      comment: event.comment,
    );

    result.fold(
      (failure) => emit(ApprovalError(failure.message)),
      (approval) => emit(TransactionApproved(approval: approval)),
    );
  }

  Future<void> _onRejectTransaction(
    RejectTransactionEvent event,
    Emitter<ApprovalState> emit,
  ) async {
    emit(const ApprovalActionInProgress('reject'));

    final result = await rejectTransaction(
      approvalId: event.approvalId,
      reason: event.reason,
    );

    result.fold(
      (failure) => emit(ApprovalError(failure.message)),
      (approval) => emit(TransactionRejected(approval: approval)),
    );
  }

  Future<void> _onRefreshApprovals(
    RefreshApprovals event,
    Emitter<ApprovalState> emit,
  ) async {
    // Keep current state while refreshing
    final result = await getPendingApprovals(
      organizationId: event.organizationId,
    );

    result.fold(
      (failure) => emit(ApprovalError(failure.message)),
      (approvals) {
        if (approvals.isEmpty) {
          emit(const ApprovalsEmpty());
        } else {
          emit(ApprovalsLoaded(
            approvals: approvals,
            pendingCount: approvals.length,
          ));
        }
      },
    );
  }
}
