import 'package:flutter_bloc/flutter_bloc.dart'; import '../../domain/usecase/add_payment_card_usecase.dart'; import '../event/add_card_event.dart'; import '../state/add_card_state.dart'; // 🔹 Импорты для Result и Failure import '../../core/result.dart'; import '../../core/failures.dart'; class AddCardBloc extends Bloc { final AddPaymentCardUsecase addPaymentCardUsecase; AddCardBloc(this.addPaymentCardUsecase) : super(const AddCardState()) { on(_onCardNumberChanged); on(_onExpiryDateChanged); on(_onCvvChanged); on(_onCardHolderChanged); on(_onAddCardSubmitted); } void _onCardNumberChanged(CardNumberChanged event, Emitter emit) { final formatted = _formatCardNumber(event.cardNumber); emit(state.copyWith(cardNumber: formatted)); } void _onExpiryDateChanged(ExpiryDateChanged event, Emitter emit) { final formatted = _formatExpiryDate(event.expiryDate); emit(state.copyWith(expiryDate: formatted)); } void _onCvvChanged(CvvChanged event, Emitter emit) { final formatted = event.cvv.replaceAll(RegExp(r'\D'), '').substring(0, 3); emit(state.copyWith(cvv: formatted)); } void _onCardHolderChanged(CardHolderChanged event, Emitter emit) { emit(state.copyWith(cardHolder: event.cardHolder)); } Future _onAddCardSubmitted(AddCardSubmitted event, Emitter emit) async { if (state.cardNumber.isEmpty || state.expiryDate.isEmpty) return; emit(state.copyWith(status: AddCardStatus.loading)); final expiryParts = state.expiryDate.split('/'); // Используем state if (expiryParts.length != 2) { emit(state.copyWith( status: AddCardStatus.failure, errorMessage: 'Неверный формат даты', )); return; } final result = await addPaymentCardUsecase( cardNumber: state.cardNumber.replaceAll(' ', ''), expiryMonth: expiryParts[0], expiryYear: expiryParts[1], cardHolder: state.cardHolder.trim(), cvv: state.cvv, ); if (result is Success) { emit(state.copyWith(status: AddCardStatus.success)); } else if (result is Failure) { final failure = result.failure; String errorMessage = 'Ошибка добавления карты'; if (failure is AuthFailure) { errorMessage = 'Неверные данные карты'; } else if (failure is AuthBlockFailure) { errorMessage = 'Доступ заблокирован'; } else if (failure is UnknownFailure) { errorMessage = failure.message ?? 'Неизвестная ошибка'; } emit(state.copyWith( status: AddCardStatus.failure, errorMessage: errorMessage, )); } } String _formatCardNumber(String value) { final cleaned = value.replaceAll(RegExp(r'\D'), ''); final limited = cleaned.substring(0, cleaned.length > 16 ? 16 : cleaned.length); String formatted = ''; for (int i = 0; i < limited.length; i++) { if (i > 0 && i % 4 == 0) { formatted += ' '; } formatted += limited[i]; } return formatted; } String _formatExpiryDate(String value) { final cleaned = value.replaceAll(RegExp(r'\D'), ''); if (cleaned.isEmpty) return ''; if (cleaned.length <= 2) { return cleaned; } final month = cleaned.substring(0, 2); final year = cleaned.substring(2, cleaned.length > 4 ? 4 : cleaned.length); return '$month/$year'; } }