import 'dart:io';
import 'package:adyen_checkout/adyen_checkout.dart';
import 'package:bloc/bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:go_router/go_router.dart';
import 'package:payment_plugin/_generated/data/remote/models/payment_event_handler.dart';
import 'package:payment_plugin/domain/models/payment_configurations.dart';
import 'package:payment_plugin/domain/models/payment_method.dart';
import 'package:payment_plugin/domain/models/stored_payment_method.dart';
import 'package:payment_plugin/domain/repositories/adyen_repository.dart';
import 'package:payment_plugin/presentation/app/bloc/payment_cards_state.dart';
class PaymentCardsCubit extends Cubit<PaymentCardsState> {
final AdyenRepository adyenRepository;
late PaymentConfigurations? paymentConfigurations;
void Function(StoredPaymentMethod)? onPaymentMethodSelected;
void Function()? onPaymentMethodValidationError;
PaymentCardsCubit({
required this.adyenRepository,
this.onPaymentMethodSelected,
this.onPaymentMethodValidationError,
StoredPaymentMethod? initialSelectedPaymentMethod,
}) : super(PaymentCardsState.initial()) {
if (initialSelectedPaymentMethod != null) {
emit(state.paymentMethodSelected(initialSelectedPaymentMethod));
}
init();
}
bool get isSelectedPaymentMethod => state.selectedPaymentMethod != null;
Future<PaymentConfigurations?> fetchPaymentConfiguration() async {
try {
final session =
await adyenRepository.fetchSessionForAddingCard();
if (session == null) {
return null;
}
return session;
} catch (e) {
debugPrint("error: $e");
return null;
}
}
void init() async {
try {
final cards = await adyenRepository.getCards();
paymentConfigurations = await fetchPaymentConfiguration();
if (cards.isEmpty) {
emit(state.cardsFetchedEmpty());
} else {
emit(state.cardsFetched(cards));
}
} catch (e) {
debugPrint("error: $e");
emit(state.cardsFetchedError());
}
}
Future<void> onPaymentResult(
PaymentResult result, BuildContext context) async {
switch (result) {
case PaymentAdvancedFinished():
debugPrint("Result advanced: ${result.resultCode}");
if (context.mounted) {
context.pop();
init();
}
break;
case PaymentSessionFinished():
debugPrint("Result session: ${result.sessionData}");
if (context.mounted) {
context.pop();
init();
}
break;
case PaymentCancelledByUser():
case PaymentError():
emit(state.cardsFetchedError());
}
}
Future<void> storePaymentMethod(PaymentMethod paymentMethod) async {
debugPrint("Payment method: $paymentMethod");
try {
final response = await adyenRepository.addCard(paymentMethod);
if (response != null) {
//emit(state.cardsFetched(response));
} else {
emit(state.cardsFetchedError());
}
} catch (e) {
debugPrint("error: $e");
}
}
SessionCheckout sessionCheckout() {
return paymentConfigurations?.sessionCheckout ??
SessionCheckout(
id: "123",
sessionData: "123",
paymentMethods: {
"scheme": {
"type": "scheme",
"brands": ["visa", "mc"],
},
},
);
}
Checkout advancedCheckout(String shopperReference, String apiKey) {
return AdvancedCheckout(
onSubmit: (data, [extra]) async {
debugPrint("Data: $data");
debugPrint("Extra: $extra");
try {
final merchantAccount =
paymentConfigurations?.sessionCheckout.id as String;
final response =
await adyenRepository.submitPayment(data, shopperReference, merchantAccount, apiKey);
return PaymentEventHandler().handleResponse(jsonResponse: response);
} catch (e) {
return Error(errorMessage: "$e");
}
},
onAdditionalDetails: (data) async {
final response = await adyenRepository.postPaymentsDetails(data, apiKey);
return PaymentEventHandler().handleResponse(jsonResponse: response!);
},
);
}
void disposeWebViewResources() {
// Force WebView cleanup
if (Platform.isAndroid) {
// Android-specific WebView cleanup
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
overlays: SystemUiOverlay.values);
}
}
Future<void> onRemoveCard(String cardId) async {
try {
emit(state.loading(true));
await adyenRepository.removeCard(cardId);
// If the removed card was selected, clear the selection
if (state.selectedPaymentMethod?.id == cardId) {
emit(state.clearSelectedPaymentMethod());
}
init();
} catch (e) {
debugPrint("error: $e");
}
}
void selectPaymentMethod(StoredPaymentMethod paymentMethod) {
emit(state.paymentMethodSelected(paymentMethod).setMissingPaymentMethod(false));
onPaymentMethodSelected?.call(paymentMethod);
}
void setMissingPaymentMethodError() {
emit(state.setMissingPaymentMethod(true));
onPaymentMethodValidationError?.call();
}
void clearMissingPaymentMethodError() {
emit(state.setMissingPaymentMethod(false));
}
}