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));
  }
}