import 'package:flutter/material.dart';
import 'package:flutter_paytabs_bridge/BaseBillingShippingInfo.dart';
import 'package:flutter_paytabs_bridge/IOSThemeConfiguration.dart';
import 'package:flutter_paytabs_bridge/PaymentSDKNetworks.dart';
import 'package:flutter_paytabs_bridge/PaymentSdkApms.dart';
import 'package:flutter_paytabs_bridge/PaymentSdkConfigurationDetails.dart';
import 'package:flutter_paytabs_bridge/PaymentSdkLocale.dart';
import 'package:flutter_paytabs_bridge/PaymentSdkTokenFormat.dart';
import 'package:flutter_paytabs_bridge/PaymentSdkTokeniseType.dart';
import 'package:flutter_paytabs_bridge/PaymentSdkTransactionType.dart';
import 'package:flutter_paytabs_bridge/flutter_paytabs_bridge.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/cache_consts.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/paytabs_config.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/features/paytabs/models/paytabs_transaction_response_model.dart';
import 'package:hmg_patient_app_new/features/payfort/models/payfort_request_insert_model.dart';
import 'package:hmg_patient_app_new/features/payfort/models/payfort_response_insert_model.dart';
import 'package:hmg_patient_app_new/features/payfort/payfort_repo.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';

class PayTabsViewModel extends ChangeNotifier {
  late PaymentSdkConfigurationDetails paymentConfiguration;
  final AppState appState;
  final PayfortRepo payfortRepo;
  final ErrorHandlerService errorHandlerService;
  late PaytabsTransactionResponseModel paytabsTransactionResponseModel;

  PayTabsViewModel({
    required this.appState,
    required this.payfortRepo,
    required this.errorHandlerService,
  });

  setPaymentConfiguration(String paymentDescription, num amount, {bool isAddCard = false}) {
    String cartID = DateTime.now().millisecondsSinceEpoch.toString();
    paymentConfiguration = PaymentSdkConfigurationDetails(
        profileId: PaymentSdkDefaultConfig.profileID,
        serverKey: PaymentSdkDefaultConfig.serverKey,
        clientKey: PaymentSdkDefaultConfig.clientKey,
        transactionType: PaymentSdkTransactionType.SALE,
        cartId: cartID.substring((cartID.length - 5), cartID.length),
        cartDescription: paymentDescription,
        merchantName: PaymentSdkDefaultConfig.defaultMerchantName,
        locale: appState.isArabic() ? PaymentSdkLocale.AR : PaymentSdkLocale.EN,
        merchantApplePayIndentifier: ApiConsts.appEnvironmentType == AppEnvironmentTypeEnum.uat
            ? PaymentSdkDefaultConfig.defaultMerchantAppleBundleIDUAT
            : PaymentSdkDefaultConfig.defaultMerchantAppleBundleID,
        // merchantApplePayIndentifier: PaymentSdkDefaultConfig.defaultMerchantAppleBundleIDUAT,
        screentTitle: paymentDescription,
        amount: amount.toDouble(),
        showBillingInfo: false,
        forceShippingInfo: false,
        currencyCode: PaymentSdkDefaultConfig.defaultCurrency,
        merchantCountryCode: PaymentSdkDefaultConfig.defaultMerchantCountryCode,
        billingDetails: BillingDetails(
            "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}" ?? "HMG Patient",
            "CustID_${appState.getAuthenticatedUser()!.patientId.toString()}@HMG.com",
            appState.getAuthenticatedUser()!.mobileNumber ?? "0000000000",
            "Riyadh",
            "SA",
            "Riyadh",
            "Riyadh",
            "12626"),
        shippingDetails: ShippingDetails(
            "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}" ?? "HMG Patient",
            "CustID_${appState.getAuthenticatedUser()!.patientId.toString()}@HMG.com",
            appState.getAuthenticatedUser()!.mobileNumber ?? "0000000000",
            "Riyadh",
            "SA",
            "Riyadh",
            "Riyadh",
            "12626"),
        alternativePaymentMethods: [],
        linkBillingNameWithCardHolderName: true,
      simplifyApplePayValidation: true,
    );

    paymentConfiguration.iOSThemeConfigurations = IOSThemeConfigurations(
      // logoImage: "assets/images/png/hmg_logo.png",
      backgroundColor: "ffffff",
      backgroundColorDark: "ffffff",
      secondaryColor: "191919",
      secondaryColorDark: "191919",
      primaryColor: "ffffff",
      primaryColorDark: "ffffff",
      // primaryFont: "Poppins",
      titleFontColor: "2E3039",
      titleFontColorDark: "2E3039",
      // titleFont: "Poppins",
      primaryFontColor: "2E3039",
      primaryFontColorDark: "2E3039",
      inputFieldBackgroundColor: "ffffff",
      inputFieldBackgroundColorDark: "ffffff",
      placeholderColor: "2E3039",
      placeholderColorDark: "2E3039",
      buttonColor: "ED1C2B",
      buttonColorDark: "ED1C2B",
        inputsCornerRadius: 12
        // buttonFont: "Poppins",
        );
    paymentConfiguration.tokeniseType = PaymentSdkTokeniseType.USER_OPTIONAL_DEFAULT_ON;
    paymentConfiguration.tokenFormat = PaymentSdkTokenFormat.Hex32Format;

    notifyListeners();
  }

  setAlternatePaymentConfiguration(String paymentDescription, num amount, {bool isAddCard = false}) {
    String cartID = DateTime.now().millisecondsSinceEpoch.toString();
    paymentConfiguration = PaymentSdkConfigurationDetails(
      profileId: PaymentSdkDefaultConfig.profileID,
      serverKey: PaymentSdkDefaultConfig.serverKey,
      clientKey: PaymentSdkDefaultConfig.clientKey,
      transactionType: PaymentSdkTransactionType.SALE,
      cartId: cartID.substring((cartID.length - 5), cartID.length),
      cartDescription: paymentDescription,
      merchantName: PaymentSdkDefaultConfig.defaultMerchantName,
      locale: appState.isArabic() ? PaymentSdkLocale.AR : PaymentSdkLocale.EN,
      screentTitle: paymentDescription,
      amount: amount.toDouble(),
      showBillingInfo: false,
      forceShippingInfo: false,
      currencyCode: PaymentSdkDefaultConfig.defaultCurrency,
      merchantCountryCode: PaymentSdkDefaultConfig.defaultMerchantCountryCode,
      billingDetails: BillingDetails("${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}" ?? "HMG Patient",
          "CustID_${appState.getAuthenticatedUser()!.patientId.toString()}@HMG.com", appState.getAuthenticatedUser()!.mobileNumber ?? "0000000000", "Riyadh", "SA", "Riyadh", "Riyadh", "12626"),
      shippingDetails: ShippingDetails("${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}" ?? "HMG Patient",
          "CustID_${appState.getAuthenticatedUser()!.patientId.toString()}@HMG.com", appState.getAuthenticatedUser()!.mobileNumber ?? "0000000000", "Riyadh", "SA", "Riyadh", "Riyadh", "12626"),
      alternativePaymentMethods: [PaymentSdkAPms.TAMARA],
      linkBillingNameWithCardHolderName: false,
      simplifyApplePayValidation: true,
    );

    paymentConfiguration.iOSThemeConfigurations = IOSThemeConfigurations(
        // logoImage: "assets/images/png/hmg_logo.png",
        backgroundColor: "ffffff",
        backgroundColorDark: "ffffff",
        secondaryColor: "191919",
        secondaryColorDark: "191919",
        primaryColor: "ffffff",
        primaryColorDark: "ffffff",
        // primaryFont: "Poppins",
        titleFontColor: "2E3039",
        titleFontColorDark: "2E3039",
        // titleFont: "Poppins",
        primaryFontColor: "2E3039",
        primaryFontColorDark: "2E3039",
        inputFieldBackgroundColor: "ffffff",
        inputFieldBackgroundColorDark: "ffffff",
        placeholderColor: "2E3039",
        placeholderColorDark: "2E3039",
        buttonColor: "ED1C2B",
        buttonColorDark: "ED1C2B",
        inputsCornerRadius: 12
        // buttonFont: "Poppins",
        );
    paymentConfiguration.tokeniseType = PaymentSdkTokeniseType.USER_OPTIONAL_DEFAULT_ON;
    paymentConfiguration.tokenFormat = PaymentSdkTokenFormat.Hex32Format;

    notifyListeners();
  }

  Future<void> paytabsRequestInsert({required PayfortRequestInsertModel payfortRequestInsertModel, Function(dynamic)? onSuccess, Function(String)? onError}) async {
    final result = await payfortRepo.payfortRequestInsert(payfortRequestInsertModel: payfortRequestInsertModel);

    result.fold(
      (failure) async => await errorHandlerService.handleError(failure: failure),
      (apiResponse) {
        if (apiResponse.messageStatus == 2) {
          // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
        } else if (apiResponse.messageStatus == 1) {
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse);
          }
        }
      },
    );
  }

  Future<void> paytabsResponseInsert({required PayfortResponseInsertModel payfortResponseInsertModel, Function(dynamic)? onSuccess, Function(String)? onError}) async {
    final result = await payfortRepo.payfortResponseInsert(payfortResponseInsertModel: payfortResponseInsertModel);

    result.fold(
      (failure) async => await errorHandlerService.handleError(failure: failure),
      (apiResponse) {
        if (apiResponse.messageStatus == 2) {
          // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
        } else if (apiResponse.messageStatus == 1) {
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse);
          }
        }
      },
    );
  }

  startApplePayPayment({Function(PaytabsTransactionResponseModel)? onSuccess, Function(String)? onError}) async {
    bool _callbackFired = false; // prevent duplicate callback invocations

    await FlutterPaytabsBridge.startApplePayPayment(paymentConfiguration, (event) {
      if (_callbackFired) return; // ignore any subsequent callback calls

      final transactionDetails = event["data"] as Map<Object?, Object?>?;
      if (event["status"] == "success") {
        _callbackFired = true;
        // Cast Map<Object?, Object?> to Map<String, dynamic>
        final data = Map<String, dynamic>.from(event["data"] as Map);
        paytabsTransactionResponseModel = PaytabsTransactionResponseModel.fromJson(data);
        if (paytabsTransactionResponseModel.isSuccess!) {
          onSuccess!(paytabsTransactionResponseModel);
        } else {
          // Transaction was processed but failed
          final reason =
              transactionDetails?["payResponseReturn"] ?? transactionDetails?["responseMessage"] ?? transactionDetails?["message"] ?? "Unknown error";
          final responseCode = transactionDetails?["responseCode"] ?? "";
          final errorMessage =
              responseCode.toString().isNotEmpty ? "Transaction failed (Code: $responseCode): $reason" : "Transaction failed: $reason";
          onError!(errorMessage);
        }
      } else if (event["status"] == "error") {
        _callbackFired = true;
        final errorMessage = event["message"] ?? "An error occurred";
        debugPrint("Error occurred in transaction: $errorMessage");
        debugPrint("Full error event: $event");
        onError!(errorMessage);
      } else if (event["status"] == "event") {
        // Intermediate SDK events – do NOT mark _callbackFired, just log
        final eventMessage = event["message"] ?? "Event occurred";
        debugPrint("Event occurred: $eventMessage");
      }
    });
  }

  startCardPayment({
    required String paymentOption,
    required String liveServiceID,
    required String isScheduleLiveCare,
    required String appointmentDate,
    required String appointmentNo,
    required String doctorID,
    required String transactionID,
    required String amount,
    required String fileNumber,
    required String orderDescription,
    required String serviceID,
    required String projectID,
    Function(PaytabsTransactionResponseModel)? onSuccess,
    Function(String)? onError,
  }) async {
    bool _callbackFired = false; // prevent duplicate callback invocations

    try {
      LoaderBottomSheet.showLoader();

      // Create PayfortRequestInsertModel (same as Payfort implementation)
      PayfortRequestInsertModel payfortRequestInsertModel = PayfortRequestInsertModel();

      payfortRequestInsertModel.commandType = "SALE";
      payfortRequestInsertModel.amount = num.parse(amount);
      payfortRequestInsertModel.customerEmail = getIt.get<AppState>().getAuthenticatedUser()!.emailAddress;
      payfortRequestInsertModel.orderDescription = orderDescription;
      payfortRequestInsertModel.serviceID = serviceID;
      payfortRequestInsertModel.paymentOption = paymentOption;
      payfortRequestInsertModel.clientRequestID = transactionID;
      payfortRequestInsertModel.projectID = projectID;
      payfortRequestInsertModel.fileNumber = getIt.get<AppState>().getAuthenticatedUser()!.patientId.toString();
      payfortRequestInsertModel.customerName = "${getIt.get<AppState>().getAuthenticatedUser()!.firstName} ${getIt.get<AppState>().getAuthenticatedUser()!.lastName}";
      payfortRequestInsertModel.currency = getIt.get<AppState>().getAuthenticatedUser()!.outSa! == 0 ? "SAR" : "AED";
      payfortRequestInsertModel.liveServiceID = liveServiceID;
      payfortRequestInsertModel.latitude = getIt.get<AppState>().userLat.toString();
      payfortRequestInsertModel.longitude = getIt.get<AppState>().userLong.toString();
      payfortRequestInsertModel.merchantReference = transactionID;
      payfortRequestInsertModel.deviceToken = await Utils.getStringFromPrefs(CacheConst.pushToken);
      payfortRequestInsertModel.language = getIt.get<AppState>().isArabic() ? "ar" : "en";
      payfortRequestInsertModel.integrationId = "2"; // PayTabs integration ID
      payfortRequestInsertModel.isSchedule = isScheduleLiveCare;
      payfortRequestInsertModel.appointmentDate = appointmentDate;
      payfortRequestInsertModel.appointmentNo = appointmentNo;
      payfortRequestInsertModel.doctorID = doctorID;

      // Call request insert API before payment
      await paytabsRequestInsert(payfortRequestInsertModel: payfortRequestInsertModel);

      LoaderBottomSheet.hideLoader();

      // Start PayTabs payment
      FlutterPaytabsBridge.startCardPayment(paymentConfiguration, (event) async {
        if (_callbackFired) return; // ignore any subsequent callback calls

        final transactionDetails = event["data"] as Map<Object?, Object?>?;
        if (event["status"] == "success") {
          _callbackFired = true;

          LoaderBottomSheet.showLoader();

          // Cast Map<Object?, Object?> to Map<String, dynamic>
          final data = Map<String, dynamic>.from(event["data"] as Map);
          paytabsTransactionResponseModel = PaytabsTransactionResponseModel.fromJson(data);

          // Create PayfortResponseInsertModel (same as Payfort implementation)
          PayfortResponseInsertModel payfortResponseInsertModel = PayfortResponseInsertModel();

          payfortResponseInsertModel.fortId = paytabsTransactionResponseModel.transactionReference ?? "";
          payfortResponseInsertModel.commandType = paytabsTransactionResponseModel.transactionType ?? "SALE";
          // payfortResponseInsertModel.amount = paytabsTransactionResponseModel.tranTotal ?? 0;
          payfortResponseInsertModel.amount = num.parse(amount);
          payfortResponseInsertModel.sadadOLP = "";
          payfortResponseInsertModel.paymentOption = paytabsTransactionResponseModel.paymentInfo?.paymentMethod ?? "";
          payfortResponseInsertModel.customerIP = "";
          payfortResponseInsertModel.eCI = "";
          payfortResponseInsertModel.responseMessage = paytabsTransactionResponseModel.payResponseReturn ?? "";
          payfortResponseInsertModel.cardNumber = paytabsTransactionResponseModel.paymentInfo!.paymentDescription;
          payfortResponseInsertModel.cardBin = "";
          payfortResponseInsertModel.installmentsNumber = 0;
          payfortResponseInsertModel.status = paytabsTransactionResponseModel.isSuccess! ? "success" : "failed";
          payfortResponseInsertModel.merchantRef = transactionID;
          payfortResponseInsertModel.isRefund = false;
          payfortResponseInsertModel.remmeberMe = true;
          payfortResponseInsertModel.reconciliationReference = "";

          // Call response insert API after payment
          await paytabsResponseInsert(payfortResponseInsertModel: payfortResponseInsertModel);

          LoaderBottomSheet.hideLoader();

          if (paytabsTransactionResponseModel.isSuccess!) {
            if (onSuccess != null) {
              onSuccess(paytabsTransactionResponseModel);
            }
          } else {
            // Transaction was processed but failed
            final reason = transactionDetails?["payResponseReturn"] ?? transactionDetails?["responseMessage"] ?? transactionDetails?["message"] ?? "Unknown error";
            final responseCode = transactionDetails?["responseCode"] ?? "";
            final errorMessage = responseCode.toString().isNotEmpty ? "Transaction failed (Code: $responseCode): $reason" : "Transaction failed: $reason";
            if (onError != null) {
              onError(errorMessage);
            }
          }
        } else if (event["status"] == "error") {
          _callbackFired = true;
          final errorMessage = event["message"] ?? "An error occurred";
          debugPrint("Error occurred in transaction: $errorMessage");
          debugPrint("Full error event: $event");
          if (onError != null) {
            onError(errorMessage);
          }
        } else if (event["status"] == "event") {
          // Intermediate SDK events – do NOT mark _callbackFired, just log
          final eventMessage = event["message"] ?? "Event occurred";
          debugPrint("Event occurred: $eventMessage");
        }
      });
    } catch (error) {
      debugPrint("PayTabs Payment Error: $error");
      LoaderBottomSheet.hideLoader();
      if (onError != null) {
        onError("Payment initialization failed: $error");
      }
    }
  }

  startAlternatePayment({Function(PaytabsTransactionResponseModel)? onSuccess, Function(String)? onError}) {
    bool _callbackFired = false; // prevent duplicate callback invocations

    FlutterPaytabsBridge.startAlternativePaymentMethod(paymentConfiguration, (event) {
      if (_callbackFired) return; // ignore any subsequent callback calls

      final transactionDetails = event["data"] as Map<Object?, Object?>?;
      if (event["status"] == "success") {
        _callbackFired = true;
        // Cast Map<Object?, Object?> to Map<String, dynamic>
        final data = Map<String, dynamic>.from(event["data"] as Map);
        paytabsTransactionResponseModel = PaytabsTransactionResponseModel.fromJson(data);
        if (paytabsTransactionResponseModel.isSuccess!) {
          onSuccess!(paytabsTransactionResponseModel);
        } else {
          // Transaction was processed but failed
          final reason = transactionDetails?["payResponseReturn"] ?? transactionDetails?["responseMessage"] ?? transactionDetails?["message"] ?? "Unknown error";
          final responseCode = transactionDetails?["responseCode"] ?? "";
          final errorMessage = responseCode.toString().isNotEmpty ? "Transaction failed (Code: $responseCode): $reason" : "Transaction failed: $reason";
          onError!(errorMessage);
        }
      } else if (event["status"] == "error") {
        _callbackFired = true;
        final errorMessage = event["message"] ?? "An error occurred";
        debugPrint("Error occurred in transaction: $errorMessage");
        debugPrint("Full error event: $event");
        onError!(errorMessage);
      } else if (event["status"] == "event") {
        // Intermediate SDK events – do NOT mark _callbackFired, just log
        final eventMessage = event["message"] ?? "Event occurred";
        debugPrint("Event occurred: $eventMessage");
      }
    });
  }
}
