<?php
defined( 'ABSPATH' ) || exit;

// AJAX function for WordPress
add_action( 'wp_ajax_robust_nmi_log_ajax_errors', 'robust_nmi_log_ajax_errors' );
add_action( 'wp_ajax_nopriv_robust_nmi_log_ajax_errors', 'robust_nmi_log_ajax_errors' );
function robust_nmi_log_ajax_errors() {
	// Check nonce
	if ( ! isset( $_POST['robust_nmi_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['robust_nmi_nonce'] ) ), 'robust_nmi_log_errors_action' ) ) {
		wp_send_json_error( array( 'message' => __( 'Invalid nonce.', 'robust-nmi-payment-gateway' ) ) );
	}

	// Get current user's username
	$current_user = wp_get_current_user();
	$username = $current_user->user_login;
	$gateway = new Robust_NMI_Gateway();

	$error = isset( $_POST['error'] ) ? sanitize_text_field( wp_unslash( $_POST['error'] ) ) : '';

	if ( $gateway->debug == 'yes' ) {
		$gateway->log->add( 'robust_nmi', '' );
		$gateway->log->add( 'robust_nmi', $username . ' 3DS :' . $error );
		$gateway->log->add( 'robust_nmi', '' );
	}

	wp_die();
}


add_action( 'woocommerce_payment_token_deleted', 'robust_nmi_payment_token_deleted', 10, 2 );

/**
 * Delete token from NMI.
 */
function robust_nmi_payment_token_deleted( $token_id, $token ) {
	$gateway = new Robust_NMI_Gateway();

	if ( 'robust_nmi_gateway' === $token->get_gateway_id() ) {

		$nmi_adr = $gateway->api_url . '/api/transact.php?';

		$nmipay_args['security_key']          = $gateway->security_key;
		$nmipay_args['customer_vault']    = 'delete_customer';
		$nmipay_args['customer_vault_id'] = $token->get_token();

		$name_value_pairs = array();
		foreach ( $nmipay_args as $key => $value ) {
			$name_value_pairs[] = $key . '=' . urlencode( $value );
		}
		$gateway_values = implode( '&', $name_value_pairs );

		$response = wp_remote_post(
			$nmi_adr,
			array(
				'body'      => $gateway_values,
				'sslverify' => false,
				'timeout'   => 60,
			)
		);

		if ( ! is_wp_error( $response ) && $response['response']['code'] >= 200 && $response['response']['code'] < 300 ) {
			parse_str( $response['body'], $response );
			if ( $response['response'] == '1' ) {
				return true;
			} else {
				if ( strpos( $response['responsetext'], __( 'Invalid Customer Vault Id', 'robust-nmi-payment-gateway' ) ) !== false ) {
					return false;
				} else {
					/* translators: %1$s: Response code, %2$s: Response text */
					wc_add_notice( sprintf( __( 'Deleting card failed. %1$s-%2$s', 'robust-nmi-payment-gateway' ), esc_html( $response['response_code'] ), esc_html( $response['responsetext'] ) ), $notice_type = 'error' );
					
					if ( $gateway->debug == 'yes' ) {
						/* translators: %1$s: Response code, %2$s: Response text */
						$gateway->log->add( 'robust_nmi', sprintf( __( 'Deleting card failed. %1$s-%2$s', 'robust-nmi-payment-gateway' ), $response['response_code'], $response['responsetext'] ) );
					}

					return false;
				}
			}
		} else {
			wc_add_notice( __( 'There was error processing your request.', 'robust-nmi-payment-gateway' ), $notice_type = 'error' );

			if ( $gateway->debug == 'yes' ) {
				$gateway->log->add( 'robust_nmi', __( 'There was error processing your request.', 'robust-nmi-payment-gateway' ) );
			}

			return false;
		}
	}
}

class Robust_NMI_Gateway extends WC_Payment_Gateway_CC {

	public $notify_url;
    public $api_url;
    public $security_key;
    public $public_key;
    public $environment;
    public $payment_api_method;
    public $saved_cards;
    public $receipt;
    public $transtype;
    public $cardtypes;
    public $debug;
    public $log;
    public $branded_url = '';
    public $inline_card_fields = false;
    public $inline_challenge = false;
    public $checkout_public_key = '';
    public $enable_3dsecure = 'no';

	/**
	 * Validate saved token and check user ownership
	 * 
	 * @param int $token_id The token ID to validate
	 * @return object|false Returns the validated token object or false if invalid
	 */
	private function validate_saved_token($token_id) {
		if (!is_numeric($token_id)) {
			return false;
		}
		
		$token_id = wc_clean($token_id);
		$saved_token = WC_Payment_Tokens::get($token_id);
		
		if (!$saved_token || $saved_token->get_user_id() !== get_current_user_id()) {
			return false;
		}
		
		// Create a token object that mimics the CollectJS response
		return (object) array(
			'token' => $saved_token->get_token(),
			'card' => (object) array(
				'number' => '****' . $saved_token->get_last4(),
				'exp' => sprintf('%02d%s', $saved_token->get_expiry_month(), substr($saved_token->get_expiry_year(), -2)),
				'type' => $saved_token->get_card_type()
			)
		);
	}

	public function __construct() {
		global $woocommerce;
		$this->id = 'robust_nmi_gateway';
		$this->method_title       = __( 'NMI Payment Gateway for WooCommerce', 'robust-nmi-payment-gateway' );
		$this->method_description = __( 'Accept secure credit card payments via Network Merchants Inc (NMI). By Robust Softech.', 'robust-nmi-payment-gateway' );
		$this->icon               = apply_filters( 'robust_nmi_gateway_icon', plugins_url( '/images/nmi-icon.png', __FILE__ ) );
		$this->has_fields   = true;
		$this->notify_url   = add_query_arg( 'wc-api', 'robust_nmi_gateway', home_url() );
		$this->api_url      = 'https://secure.networkmerchants.com';
		$this->supports     = array(
			'products',
			'default_credit_card_form',
			'refunds',
			'tokenization',
			'subscriptions',
			'subscription_cancellation',
			'subscription_suspension',
			'subscription_reactivation',
			'subscription_payment_method_change',
			'gateway_scheduled_payments',
		);
		
		$default_card_type_options = array(
			'VISA' => 'VISA',
			'MC'   => 'MasterCard',
			'AMEX' => 'American Express',
			'DISC' => 'Discover',
			'DC'   => 'Diner\'s Club',
			'JCB'  => 'JCB Card',
		);

		$this->card_type_options = apply_filters( 'robust_nmi_gateway_card_types', $default_card_type_options );

		// Load the form fields.
		$this->init_form_fields();

		// Load the settings.
		$this->init_settings();

		// Define user set variables
		$this->enabled          	= $this->get_option( 'enabled' );
		$this->title          		= $this->get_option( 'title' );
		$this->description    		= $this->get_option( 'description' );
		$this->security_key       = $this->get_option( 'security_key' );
		$this->public_key         = $this->get_option( 'public_key' );
		$this->environment        = $this->get_option( 'environment', 'production' );
		$this->payment_api_method = $this->get_option( 'payment_api_method', 'collectjs' );
		$this->transtype       = $this->get_option( 'transtype' );
		$this->cardtypes       = $this->get_option( 'cardtypes' );
		$this->saved_cards     = 'yes' === $this->get_option( 'saved_cards' );
		$this->receipt         = 'yes' === $this->get_option( 'receipt' );
		$this->debug           = $this->get_option( 'debug' );

		if ( $this->transtype == '' ) {
			$this->transtype = 'sale';
		}

		// Initialize missing properties
		$this->checkout_public_key = $this->get_option( 'checkout_public_key', '' );
		$this->inline_card_fields = 'yes' === $this->get_option( 'inline_card_fields', 'no' );
		$this->inline_challenge = 'yes' === $this->get_option( 'inline_challenge', 'no' );
		$this->enable_3dsecure = $this->get_option( 'enable_3dsecure', 'no' );

		// Add support for blocks
		$this->supports = array(
			'products',
			'refunds',
			'tokenization',
			'add_payment_method',
			'subscriptions',
			'subscription_cancellation',
			'subscription_suspension',
			'subscription_reactivation',
			'subscription_amount_changes',
			'subscription_date_changes',
			'subscription_payment_method_change',
			'subscription_payment_method_change_customer',
			'subscription_payment_method_change_admin',
			'multiple_subscriptions',
		);

		if ( $this->branded_url != '' ) {
			$this->api_url = $this->branded_url;
		}

		// Logs
		if ( $this->debug == 'yes' ) {
			$this->log = new WC_Logger();
		}

		add_action( 'woocommerce_api_robust_nmi_gateway', array( $this, 'successful_request' ) );
		//add_action( 'valid-nmipay-ipn-request', array( $this, 'successful_request' ) );
		// Actions
		add_action( 'woocommerce_update_options_payment_gateways', array( $this, 'process_admin_options' ) );
		add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
		
		if ( class_exists( 'WC_Subscriptions_Order' ) ) {
			add_action( 'woocommerce_subscription_cancelled_' . $this->id, array( $this, 'cancelled_subscription' ), 10, 2 );
			add_action( 'woocommerce_subscription_on-hold_' . $this->id, array( $this, 'hold_subscription' ), 10, 2 );
			add_action( 'woocommerce_subscription_activated_' . $this->id, array( $this, 'activated_subscription' ), 10, 2 );
		}

		if( $this->enabled == 'yes' ){


			add_action( 'wp_enqueue_scripts', array( $this, 'payment_scripts' ) );

			add_action( 'wp_footer', array( $this, 'footer_payment_scripts' ) );


		}
		
		// Add hooks for block checkout payment processing
		add_filter( 'woocommerce_rest_pre_dispatch', array( $this, 'handle_block_checkout_data' ), 10, 3 );



		if ( ! $this->is_valid_for_use() ) {
			$this->enabled = false;
		}
	}

	/**
	 * cancelled_subscription function.
	 *
	 * @param float    $amount_to_charge the amount to charge
	 * @param WC_Order $renewal_order    a WC_Order object created to record the renewal payment
	 */
	public function cancelled_subscription( $order ) {
		// $profile_id = self::get_subscriptions_nmipay_id( $order );

		#$profile_id = get_post_meta( $order->parent_id, 'NMI Subscriber ID', true );
		$profile_id = get_metadata('order', $order->get_id(), 'NMI Subscriber ID', true);


		// Make sure a subscriptions status is active with NMI
		$nmipay_args['security_key']        = $this->security_key;
		$nmipay_args['recurring']       = 'delete_subscription';
		$nmipay_args['subscription_id'] = $profile_id;

		$name_value_pairs = array();
		foreach ( $nmipay_args as $key => $value ) {
			$name_value_pairs[] = $key . '=' . urlencode( $value );
		}
		$gateway_values = implode( '&', $name_value_pairs );

		$nmi_adr = $this->api_url . '/api/transact.php?';
		
		if ( $this->debug == 'yes' ) {
			// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug logging only when debug mode enabled
			$this->log->add( 'robust_nmi', 'Subscription Cancel Request : '. print_r($nmipay_args,true) );
		}

		$response = wp_remote_post(
			$nmi_adr,
			array(
				'body'      => $gateway_values,
				'sslverify' => false,
				'timeout'   => 60,
			)
		);
		
		if ( $this->debug == 'yes' ) {
			// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug logging only when debug mode enabled
			$this->log->add( 'robust_nmi', 'Subscription Cancel Response : '. print_r($response,true) );
		}

		if ( ! is_wp_error( $response ) && $response['response']['code'] >= 200 && $response['response']['code'] < 300 ) {
			parse_str( $response['body'], $response );

			if ( $response['response'] == '1' ) {
				$order->add_order_note( __( 'Subscription cancelled with NMI', 'robust-nmi-payment-gateway' ) );
			} else {
				$order->add_order_note( __( 'There was error cancelling the Subscription with NMI', 'robust-nmi-payment-gateway' ) );
			}
		}
	}

	/**
	 * hold_subscription function.
	 *
	 * @param float    $amount_to_charge the amount to charge
	 * @param WC_Order $renewal_order    a WC_Order object created to record the renewal payment
	 */
	public function hold_subscription( $order ) {
		// $profile_id = self::get_subscriptions_nmipay_id( $order );

		#$profile_id = get_post_meta( $order->parent_id, 'NMI Subscriber ID', true );
		$profile_id = get_metadata('order', $order->get_id(), 'NMI Subscriber ID', true);


		// Make sure a subscriptions status is active with NMI
		$nmipay_args['security_key']        = $this->security_key;
		$nmipay_args['recurring']       = 'update_subscription';
		$nmipay_args['subscription_id'] = $profile_id;
		$nmipay_args['paused_subscription'] = 'true';

		$name_value_pairs = array();
		foreach ( $nmipay_args as $key => $value ) {
			$name_value_pairs[] = $key . '=' . urlencode( $value );
		}
		$gateway_values = implode( '&', $name_value_pairs );

		$nmi_adr = $this->api_url . '/api/transact.php?';
		
		if ( $this->debug == 'yes' ) {
			// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug logging only when debug mode enabled
			$this->log->add( 'robust_nmi', 'Subscription Hold Request : '. print_r($nmipay_args,true) );
		}

		$response = wp_remote_post(
			$nmi_adr,
			array(
				'body'      => $gateway_values,
				'sslverify' => false,
				'timeout'   => 60,
			)
		);
		
		if ( $this->debug == 'yes' ) {
			// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug logging only when debug mode enabled
			$this->log->add( 'robust_nmi', 'Subscription Hold Response : '. print_r($response,true) );
		}

		if ( ! is_wp_error( $response ) && $response['response']['code'] >= 200 && $response['response']['code'] < 300 ) {
			parse_str( $response['body'], $response );

			if ( $response['response'] == '1' ) {
				$order->add_order_note( __( 'Subscription paused with NMI', 'robust-nmi-payment-gateway' ) );
			} else {
				$order->add_order_note( __( 'There was error pausing the Subscription with NMI', 'robust-nmi-payment-gateway' ) );
			}
		}
	}

	/**
	 * activated_subscription function.
	 *
	 * @param float    $amount_to_charge the amount to charge
	 * @param WC_Order $renewal_order    a WC_Order object created to record the renewal payment
	 */
	public function activated_subscription( $order ) {
		// $profile_id = self::get_subscriptions_nmipay_id( $order );

		#$profile_id = get_post_meta( $order->parent_id, 'NMI Subscriber ID', true );
		$profile_id = get_metadata('order', $order->get_id(), 'NMI Subscriber ID', true);


		// Make sure a subscriptions status is active with NMI
		$nmipay_args['security_key']        = $this->security_key;
		$nmipay_args['recurring']       = 'update_subscription';
		$nmipay_args['subscription_id'] = $profile_id;
		$nmipay_args['paused_subscription'] = 'false';

		$name_value_pairs = array();
		foreach ( $nmipay_args as $key => $value ) {
			$name_value_pairs[] = $key . '=' . urlencode( $value );
		}
		$gateway_values = implode( '&', $name_value_pairs );

		$nmi_adr = $this->api_url . '/api/transact.php?';
		
		if ( $this->debug == 'yes' ) {
			// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug logging only when debug mode enabled
			$this->log->add( 'robust_nmi', 'Subscription ReActivate Request : '. print_r($nmipay_args,true) );
		}

		$response = wp_remote_post(
			$nmi_adr,
			array(
				'body'      => $gateway_values,
				'sslverify' => false,
				'timeout'   => 60,
			)
		);
		
		if ( $this->debug == 'yes' ) {
			// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug logging only when debug mode enabled
			$this->log->add( 'robust_nmi', 'Subscription Cancel Response : '. print_r($response,true) );
		}

		if ( ! is_wp_error( $response ) && $response['response']['code'] >= 200 && $response['response']['code'] < 300 ) {
			parse_str( $response['body'], $response );

			if ( $response['response'] == '1' ) {
				$order->add_order_note( __( 'Subscription reactivated with NMI', 'robust-nmi-payment-gateway' ) );
			} else {
				$order->add_order_note( __( 'There was error reactivating the Subscription with NMI', 'robust-nmi-payment-gateway' ) );
			}
		}
	}

	/**
	 * Returns a NMI Subscription ID/Recurring Payment Profile ID based on a user ID and subscription key.
	 *
	 * @since 1.1
	 */
	public static function get_subscriptions_nmipay_id( $order ) {
		#$profile_id = get_post_meta( $order->id, 'NMI Subscriber ID', true );
		$profile_id = get_metadata('order', $order->get_id(), 'NMI Subscriber ID', true);

		return $profile_id;
	}

	/**
	 * Check if this gateway is enabled and available in the user's country.
	 */
	public function is_valid_for_use() {
		// Always return true - don't restrict by currency
		return true;
	}

	/**
	 * Check if this gateway is available.
	 */
	public function is_available() {
		// Always allow in admin to access settings
		if ( is_admin() ) {
			return true;
		}

		// If gateway is not enabled, return false
		if ( 'no' === $this->enabled ) {
			return false;
		}

		// Check if this gateway is valid for the currency
		if ( ! $this->is_valid_for_use() ) {
			return false;
		}

		// Always return true if enabled and valid for use
		// We'll validate keys during payment processing
		return true;
	}

	/**
	 * get_icon function.
	 *
	 * @return string
	 */
	public function get_icon() {
		global $woocommerce;

		$icon = '';
		if ( $this->icon ) {
			// default behavior
			$icon = '<img src="' . $this->force_ssl( $this->icon ) . '" alt="' . $this->title . '" />';
		} elseif ( $this->cardtypes ) {
			// display icons for the selected card types
			$icon = '';
			foreach ( $this->cardtypes as $cardtype ) {
				if ( file_exists( plugin_dir_path( __FILE__ ) . '/images/card-' . strtolower( $cardtype ) . '.png' ) ) {
					$icon .= '<img style="margin-left: 0.3em; height:30px" src="' . $this->force_ssl( plugins_url( '/images/card-' . strtolower( $cardtype ) . '.png', __FILE__ ) ) . '" alt="' . strtolower( $cardtype ) . '" />';
				}
			}
		}

		// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WooCommerce core hook
		return apply_filters( 'woocommerce_gateway_icon', $icon, $this->id );
	}

	private function force_ssl( $url ) {
		if ( 'yes' == get_option( 'woocommerce_force_ssl_checkout' ) ) {
			$url = str_replace( 'http:', 'https:', $url );
		}

		return $url;
	}

	/**
	 * Admin Panel Options
	 * - Options for bits like 'title' and availability on a country-by-country basis.
	 *
	 * @since 1.0.0
	 */
	public function admin_options() {       ?>
		<h3><?php echo esc_html__( 'Network Merchants Inc (NMI) by Robust', 'robust-nmi-payment-gateway' ); ?></h3>
		<p><?php echo esc_html__( 'Accept secure credit card payments on your WooCommerce store with the Network Merchants Inc (NMI) Payment Gateway. By Robust Softech.', 'robust-nmi-payment-gateway' ); ?>
		</p>
		<table class="form-table">
			<?php
			if ( $this->is_valid_for_use() ) :

				// Generate the HTML For the settings form.
				$this->generate_settings_html(); else :

					?>
			<div class="inline error">
				<p><strong><?php echo esc_html__( 'Gateway Disabled', 'robust-nmi-payment-gateway' ); ?></strong>:
					<?php echo esc_html__( 'NMI does not support your store currency.', 'robust-nmi-payment-gateway' ); ?></p>
			</div>
					<?php

			  endif;
				?>
		</table>
		<!--/.form-table-->
		<?php
	}

	// End admin_options()

	/**
	 *  Initialise Gateway Settings Form Fields.
	 */
	public function init_form_fields() {
		$this->form_fields = array(
			'enabled'        => array(
				'title'    => __( 'Enable/Disable', 'robust-nmi-payment-gateway' ),
				'type'     => 'checkbox',
				'label'    => __( 'Enable NMI Payment Gateway for WooCommerce', 'robust-nmi-payment-gateway' ),
				'default'  => 'no',
				'desc_tip' => true,
			),
			'title'          => array(
				'title'       => __( 'Title', 'robust-nmi-payment-gateway' ),
				'type'        => 'text',
				'description' => __( 'This controls the title which the user sees during checkout.', 'robust-nmi-payment-gateway' ),
				'default'     => __( 'Credit Card', 'robust-nmi-payment-gateway' ),
				'desc_tip'    => true,
			),
			'description'    => array(
				'title'       => __( 'Description', 'robust-nmi-payment-gateway' ),
				'type'        => 'textarea',
				'description' => __( 'This controls the description which the user sees during checkout.', 'robust-nmi-payment-gateway' ),
				'default'     => __( 'Pay securely via Network Merchants Inc (NMI). By Robust Softech.', 'robust-nmi-payment-gateway' ),
				'desc_tip'    => true,
			),
			'environment' => array(
				'title'       => __( 'Environment', 'robust-nmi-payment-gateway' ),
				'type'        => 'select',
				'description' => __( 'Choose between Production and Sandbox for testing.', 'robust-nmi-payment-gateway' ),
				'default'     => 'production',
				'options'     => array(
					'production' => __( 'Production', 'robust-nmi-payment-gateway' ),
					'sandbox'    => __( 'Sandbox', 'robust-nmi-payment-gateway' ),
				),
				'desc_tip'    => true,
			),
			'security_key'       => array(
				'title'       => __( 'Private Security key', 'robust-nmi-payment-gateway' ),
				'type'        => 'password',
				'description' => __( 'Please enter your Private Security key; this is needed in order to take payment.', 'robust-nmi-payment-gateway' ),
				'default'     => '',
				'desc_tip'    => true,
			),
		'public_key'       => array(
			'title'       => __( 'Public Key', 'robust-nmi-payment-gateway' ),
			'type'        => 'text',
			'description' => __( 'Please enter your Public Key for tokenization.', 'robust-nmi-payment-gateway' ),
			'default'     => '',
			'desc_tip'    => true,
		),
		'payment_api_method' => array(
			'title'       => __( 'Payment API Method', 'robust-nmi-payment-gateway' ),
			'type'        => 'select',
			'description' => __( 'Choose how to process payments. Collect.js is recommended for better security and PCI compliance.', 'robust-nmi-payment-gateway' ),
			'default'     => 'collectjs',
			'options'     => array(
				'collectjs'   => __( 'Collect.js (Recommended)', 'robust-nmi-payment-gateway' ),
				'direct_post' => __( 'Direct Post', 'robust-nmi-payment-gateway' ),
			),
			'desc_tip'    => true,
		),
		'receipt'        => array(
				'title'       => __( 'Enable/Disable Customer Receipt', 'robust-nmi-payment-gateway' ),
				'type'        => 'checkbox',
				'label'       => __( 'Enable Customer Receipt', 'robust-nmi-payment-gateway' ),
				'description' => __( 'If enabled, when the customer is charged, they will be sent a transaction receipt.', 'robust-nmi-payment-gateway' ),
				'default'     => 'yes',
				'desc_tip'    => true,
			),/*
			'inline_card_fields'    => array(
				'title'       => __( 'Display Credit Card Fields Inline', 'robust-nmi-payment-gateway' ),
				'label'       => __( 'Enable Display Credit Card Fields Inline', 'robust-nmi-payment-gateway' ),
				'type'        => 'checkbox',
				'description' => __( 'If enabled, users will be displayed Credit Card Fields Inline.', 'robust-nmi-payment-gateway' ),
				'default'     => 'no',
				'desc_tip'    => true,
			),
			'inline_challenge'    => array(
				'title'       => __( 'Display Challenge Inline', 'robust-nmi-payment-gateway' ),
				'label'       => __( 'Enable Display Challenge Inline', 'robust-nmi-payment-gateway' ),
				'type'        => 'checkbox',
				'description' => __( 'If enabled, users will be displayed 3D Secure challenge window inline.', 'robust-nmi-payment-gateway' ),
				'default'     => 'no',
				'desc_tip'    => true,
			),*/
			'enable_3dsecure'    => array(
				'title'       => __( 'Enable 3D Secure', 'robust-nmi-payment-gateway' ),
				'label'       => __( 'Enable 3D Secure Payer Authentication', 'robust-nmi-payment-gateway' ),
				'type'        => 'checkbox',
				'description' => __( 'If enabled, cards will be verified through Payer Authentication process.', 'robust-nmi-payment-gateway' ),
				'default'     => 'yes',
				'desc_tip'    => true,
			),
			'saved_cards'    => array(
				'title'       => __( 'Save Cards', 'robust-nmi-payment-gateway' ),
				'label'       => __( 'Enable Payment via Saved Cards', 'robust-nmi-payment-gateway' ),
				'type'        => 'checkbox',
				'description' => __( 'If enabled, users will be able to pay with a saved card during checkout. Card details are saved on NMI servers, not on your store.', 'robust-nmi-payment-gateway' ),
				'default'     => 'no',
				'desc_tip'    => true,
			),
			'send_details'   => array(
				'title'       => __( 'Send Cart Details', 'robust-nmi-payment-gateway' ),
				'label'       => __( 'Enable Send Cart Details', 'robust-nmi-payment-gateway' ),
				'type'        => 'checkbox',
				'description' => __( 'If enabled, plugin will send the product details to NMI.', 'robust-nmi-payment-gateway' ),
				'default'     => 'yes',
				'desc_tip'    => true,
			),
			'send_billing_method'   => array(
				'title'       => __( 'Send Billing Method', 'robust-nmi-payment-gateway' ),
				'label'       => __( 'Enable Send Billing Method', 'robust-nmi-payment-gateway' ),
				'type'        => 'checkbox',
				'description' => __( 'If enabled, plugin will send billing_method parameter in payment requests. Default is enabled.', 'robust-nmi-payment-gateway' ),
				'default'     => 'yes',
				'desc_tip'    => true,
			),
			'transtype'      => array(
				'title'       => __( 'Transaction Type', 'robust-nmi-payment-gateway' ),
				'type'        => 'select',
				'class'       => 'wc-enhanced-select',
				'options'     => array(
					'sale' => 'Sale (Authorize and Capture)',
					'auth' => 'Authorize Only',
				),
				'description' => __( 'Select your Transaction Type.', 'robust-nmi-payment-gateway' ),
				'default'     => 'sale',
				'desc_tip'    => true,
			),/*
			'provider'       => array(
				'title'       => __( 'Payment Gateway', 'robust-nmi-payment-gateway' ),
				'type'        => 'select',
				'class'       => 'wc-enhanced-select',
				'options'     => array(
					'nmi'         => 'Network Merchants Inc',
					'alphacard'   => 'Alpha Card Services',
					'llms'        => 'LL Merchant Solutions',
					'powerpay'    => 'PowerPay',
					'sbg'         => 'SkyBank',
					'mgg'         => 'MerchantGuy',
					'durango'     => 'Durango Merchant Services',
					'tnbci'       => 'TransNational Bankcard Inc',
					'payscape'    => 'Payscape',
					'paylinedata' => 'Payline Data',
					'inspire'     => 'Inspire Commerce',
					'safesave'    => 'SafeSave Payments',
					'tranzcrypt'  => 'Tranzcrypt',
					'planetauth'  => 'PlanetAuthorize',
					'cyogate'     => 'CyoGate',
					'fluidpay'    => 'Fluid Pay',
					'glacierpay'  => 'Glacier Payments',
				),
				'description' => __( 'Select your Merchant Account Provider.', 'robust-nmi-payment-gateway' ),
				'default'     => 'nmi',
				'desc_tip'    => true,
			),*/
			'cardtypes'      => array(
				'title'       => __( 'Accepted Cards', 'robust-nmi-payment-gateway' ),
				'class'       => 'wc-enhanced-select',
				'type'        => 'multiselect',
				'description' => __( 'Select which card types to accept. If you want to select multiple cards be sure to hold down the CTRL key on your keyboard and then click the names of the cards you want to add.', 'robust-nmi-payment-gateway' ),
				'default'     => 'VISA',
				'options'     => $this->card_type_options,
				'desc_tip'    => true,
			),
			'debug'          => array(
				'title'       => __( 'Debug log', 'robust-nmi-payment-gateway' ),
				'type'        => 'checkbox',
				'label'       => __( 'Enable logging', 'robust-nmi-payment-gateway' ),
				'default'     => 'no',
				/* translators: %s: Log file path */
				'description' => sprintf( __( 'Log NMI requests, inside %s', 'robust-nmi-payment-gateway' ), '<code>' . esc_html( WC_Log_Handler_File::get_log_file_path( 'nmipay' ) ) . '</code>' ),
			),
		);
	}

	// End init_form_fields()


	/**
	 * Successful Payment!
	 **/
	function successful_request() {
		global $woocommerce;


		
		
		$ip_array = array(
			'104.192.32.81',
			'104.192.32.82',
			'104.192.32.83',
			'104.192.32.84',
			'104.192.32.85',
			'104.192.32.86',
			'104.192.32.87',
			'104.192.36.81',
			'104.192.36.82',
			'104.192.36.83',
			'104.192.36.84',
			'104.192.36.85',
			'104.192.36.86',
			'104.192.36.87',
		);

		if( $this->webhook_key != '' ){


		
			if ( $this->debug == 'yes' ) {
				$this->log->add( 'robust_nmi', 'IPN RAW Response : '. file_get_contents("php://input") );
			}


			try {
				$signingKey = $this->webhook_key;
				$webhookBody = file_get_contents("php://input");
				$headers = getallheaders();
				$sigHeader = $headers['webhook-signature'];
				if ( $this->debug == 'yes' ) {
					$this->log->add( 'robust_nmi', "webhook signatureKey - ".$signingKey );
					// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug logging only when debug mode enabled
					$this->log->add( 'robust_nmi', "webhook signature - ".print_r($headers,true) );
				}
		
				if ( $this->debug == 'yes' ) {
					$this->log->add( 'robust_nmi', 'IPN Response received from  : '. $headers['X-Forwarded-For'] );
				}

				if( !in_array( $headers['CF-Connecting-IP'],$ip_array ) || !in_array( $headers['X-Forwarded-For'],$ip_array ) ){

					if ( $this->debug == 'yes' ) {
						$this->log->add( 'robust_nmi', "unrecognized webhook server" );
					}

					throw new Exception("unrecognized webhook server");

				}

				
				
				if (!is_null($sigHeader) && strlen($sigHeader) < 1) {
					if ( $this->debug == 'yes' ) {
						$this->log->add( 'robust_nmi', "invalid webhook - signature header missing" );
					}

					throw new Exception("invalid webhook - signature header missing");
				}

				if (preg_match('/t=(.*),s=(.*)/', $sigHeader, $matches)) {
					$nonce = $matches[1];
					$signature = $matches[2];
				} else {
					if ( $this->debug == 'yes' ) {
						$this->log->add( 'robust_nmi', "unrecognized webhook signature format" );
					}

					throw new Exception("unrecognized webhook signature format");
				}
				
				
				if (!$this->webhookIsVerified($webhookBody, $signingKey, $nonce, $signature)) {
					if ( $this->debug == 'yes' ) {
						$this->log->add( 'robust_nmi', "invalid webhook - invalid signature, cannot verify sender" );
					}

					throw new Exception("invalid webhook - invalid signature, cannot verify sender");
				}
				
				// webhook is now verified to have been sent by us, continue processing
				echo "webhook is verified";
				if ( $this->debug == 'yes' ) {
					$this->log->add( 'robust_nmi', "webhook is verified" );
				}

				$webhook_body_sanitized = sanitize_text_field( $webhookBody );
				$webhook = json_decode( $webhook_body_sanitized );
	
				$order_id = explode('-',$webhook->event_body->order_id)[0];
					
				if ( $this->debug == 'yes' ) {
					// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug logging only when debug mode enabled
					$this->log->add( 'robust_nmi', 'IPN Response For Order : '. $order_id .' => '. print_r($webhook,true) );
				}

				$order = wc_get_order( (int)$order_id);

				$title = "NMI - ".strtoupper(str_replace('.',' ',$webhook->event_type));


				if( $webhook->event_body->action->source == 'recurring' ){

					if ( function_exists( 'wcs_order_contains_subscription' ) || function_exists( 'wcs_is_subscription' ) ) {
						if ( wcs_order_contains_subscription( $order_id ) || wcs_is_subscription( $order_id ) ) {
	
	
							$subcriptions = wcs_get_subscriptions_for_order( $order_id, array( 'order_type' => array( 'any' ) ) );
					
							foreach( $subcriptions as $subscription_id => $subscription ) {
								// Now you can work with the $subscription object
								// For instance, you can get the status with $subscription->get_status()
	
								$subscription = wcs_get_subscription( $subscription_id );
								$subscription_order = wcs_create_renewal_order( $subscription );
		
								$subscription_order->update_status( 'pending', 'Created for IPN Response' );
		
								$subscription_order->payment_complete( $webhook->event_body->transaction_id );
		
								/* translators: %s: Transaction ID */
								$subscription_order->add_order_note( sprintf( __( 'IPN received for Subscription Payment. Transaction ID: %s', 'robust-nmi-payment-gateway' ), $webhook->event_body->transaction_id ) );
								/* translators: %1$s: Response text, %2$s: Response code */
								$subscription_order->add_order_note( sprintf( __( 'IPN received for Subscription Payment. Response: %1$s, Status: %2$s', 'robust-nmi-payment-gateway' ), $webhook->event_body->action->response_text, $webhook->event_body->action->response_code ) );
								if ( $this->debug == 'yes' ) {
									$this->log->add( 'robust_nmi', 'MArking Subcription order' );
								}
			
								// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug data storage
								$order->update_meta_data( $title, print_r($webhook,true) );
								$order->save();

							}
	
							//WC_Subscriptions_Manager::process_subscription_payments_on_order( $order );
						
						}
					}

				}else{
					// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug data storage
					$order->update_meta_data( $title, print_r($webhook,true) );
					$order->save();

					/* translators: %s: Transaction ID */
					$order->add_order_note( sprintf( __( 'IPN received for Payment. Transaction ID: %s', 'robust-nmi-payment-gateway' ), $webhook->event_body->transaction_id ) );
					/* translators: %1$s: Response text, %2$s: Response code */
					$order->add_order_note( sprintf( __( 'IPN received for Payment. Response: %1$s, Status: %2$s', 'robust-nmi-payment-gateway' ), $webhook->event_body->action->response_text, $webhook->event_body->action->response_code ) );
					if ( $this->debug == 'yes' ) {
						$this->log->add( 'robust_nmi', 'Marking Normal Order Complete' );
					}

				}


			} catch (Exception $e) {
				if ( $this->debug == 'yes' ) {
					$this->log->add( 'robust_nmi', 'Webhook processing error: ' . esc_html( $e->getMessage() ) );
				}
			}

		}
		
		echo 'Nothing Here.';

	}

	function webhookIsVerified($webhookBody, $signingKey, $nonce, $sig) {
		return $sig === hash_hmac("sha256", $nonce . "." . $webhookBody, $signingKey);
	}

	/* === FRONTEND METHODS === */

	/**
	 * Javascript library
	 *
	 * @since 1.0.0
	 */
	public function footer_payment_scripts() {

		global $wp;

		$time = time();

		if ( ( is_checkout() || is_add_payment_method_page() )  ){


			wp_register_script( 'patsatech-nmi-js', $this->force_ssl( plugins_url( '/js/nmi-checkout.js', __FILE__ ) ), array(
				'jquery',
				'jquery-blockui',
				//'nmi-js'
			), $time, true );

			
			wp_enqueue_script( 'patsatech-nmi-js' );

			$base_country   = new WC_Countries();
			

			try{

				$cart_total = WC()->cart->get_total();

				// Remove all HTML tags
				$cart_total = explode('</span>',$cart_total)[1];

				// Remove all non-numeric characters except for the decimal point
				$cart_total = preg_replace('/[^0-9.]/', '', $cart_total);

			}catch(Exception $e) {

				$cart_total = 0;

			}

			wp_localize_script( 'patsatech-nmi-js', 'nmi_info', array(
				'public_key' => $this->checkout_public_key,
				'currency_code'  => strtoupper( get_woocommerce_currency() ),
				'save_cards' => $this->saved_cards,
				'inline_3ds' => $this->inline_challenge,
				'inline_card' => $this->inline_card_fields,
				'submitted' => '0',
				'fields_loaded' => '0',
				'errors' => '',
				'base_country' => $base_country->get_base_country(),
				'cart_total' => $cart_total,
				'enable_3dsecure' => $this->enable_3dsecure,
			) );

		}

	}

	/**
	 * Javascript library
	 *
	 * @since 1.0.0
	 */
	public function payment_scripts() {
		global $wp;

		$time = time();
	
		
		if( is_add_payment_method_page() ){

			$user_id = get_current_user_id(); // Gets the ID of the currently logged in user

			$billing_address = array(
				'first_name' => get_user_meta($user_id, 'billing_first_name', true),
				'last_name'  => get_user_meta($user_id, 'billing_last_name', true),
				'company'    => get_user_meta($user_id, 'billing_company', true),
				'address_1'  => get_user_meta($user_id, 'billing_address_1', true),
				'address_2'  => get_user_meta($user_id, 'billing_address_2', true),
				'city'       => get_user_meta($user_id, 'billing_city', true),
				'postcode'   => get_user_meta($user_id, 'billing_postcode', true),
				'country'    => get_user_meta($user_id, 'billing_country', true),
				'state'      => get_user_meta($user_id, 'billing_state', true),
				'phone'      => get_user_meta($user_id, 'billing_phone', true),
				'email'      => get_user_meta($user_id, 'billing_email', true)
			);
			
			// Enqueue script for add payment method page
			wp_enqueue_script( 
				'robust-nmi-add-payment-method', 
				plugins_url( 'includes/js/nmi-checkout.js', __FILE__ ), 
				array( 'jquery' ), 
				'1.0.0', 
				true 
			);
			
			// Add inline script for billing address
			$inline_script = 'window.onload = function() {
				if (document.getElementById("add_payment_method")) {
					document.getElementById("add_payment_method").innerHTML += \'<span style="display:none;" class="order-total"><bdi><span class="woocommerce-Price-currencySymbol">T</span>1.00</bdi></span>\';
					document.getElementById("add_payment_method").innerHTML += \'<input type="hidden" id="billing_email" name="billing_email" value="' . esc_js( $billing_address['email'] ) . '"/>\';
					document.getElementById("add_payment_method").innerHTML += \'<input type="hidden" id="billing_phone" name="billing_phone" value="' . esc_js( $billing_address['phone'] ) . '"/>\';
					document.getElementById("add_payment_method").innerHTML += \'<input type="hidden" id="billing_city" name="billing_city" value="' . esc_js( $billing_address['city'] ) . '"/>\';
					document.getElementById("add_payment_method").innerHTML += \'<input type="hidden" id="billing_state" name="billing_state" value="' . esc_js( $billing_address['state'] ) . '"/>\';
					document.getElementById("add_payment_method").innerHTML += \'<input type="hidden" id="billing_address_1" name="billing_address_1" value="' . esc_js( $billing_address['address_1'] ) . '"/>\';
					document.getElementById("add_payment_method").innerHTML += \'<input type="hidden" id="billing_country" name="billing_country" value="' . esc_js( $billing_address['country'] ) . '"/>\';
					document.getElementById("add_payment_method").innerHTML += \'<input type="hidden" id="billing_first_name" name="billing_first_name" value="' . esc_js( $billing_address['first_name'] ) . '"/>\';
					document.getElementById("add_payment_method").innerHTML += \'<input type="hidden" id="billing_last_name" name="billing_last_name" value="' . esc_js( $billing_address['last_name'] ) . '"/>\';
					document.getElementById("add_payment_method").innerHTML += \'<input type="hidden" id="billing_postcode" name="billing_postcode" value="' . esc_js( $billing_address['postcode'] ) . '"/>\';
				}
			};';
			
			wp_add_inline_script( 'robust-nmi-add-payment-method', $inline_script );

		}

		
		if ( ( is_checkout() || is_add_payment_method_page() )  ){

			// Get public key from settings
			$public_key = $this->get_option( 'public_key', '' );
			
			if ( !empty( $public_key ) ) {
				// Enqueue Collect.js from NMI
				wp_enqueue_script( 
					'robust-nmi-collectjs', 
					esc_url( $this->api_url . '/token/Collect.js?v=' . $time ), 
					array(), 
					'1.0.0', 
					false 
				);
				
				// Add data attribute for tokenization key
				add_filter( 'script_loader_tag', function( $tag, $handle ) use ( $public_key ) {
					if ( 'robust-nmi-collectjs' === $handle ) {
						$tag = str_replace( ' src', ' data-tokenization-key="' . esc_attr( $public_key ) . '" src', $tag );
					}
					return $tag;
				}, 10, 2 );
				
				// Enqueue initialization script
				wp_enqueue_script( 
					'robust-nmi-checkout', 
					plugins_url( 'includes/js/nmi-checkout.js', __FILE__ ), 
					array( 'jquery', 'robust-nmi-collectjs' ), 
					'1.0.0', 
					true 
				);
				
				// Enqueue stylesheet for payment fields
				wp_enqueue_style(
					'robust-nmi-payment-fields',
					plugins_url( 'includes/css/nmi-payment-fields.css', __FILE__ ),
					array(),
					'1.0.0'
				);
			}
		}




	}
	
	/**
	 * There are no payment fields for nmi, but we want to show the description if set.
	 **/
	public function payment_fields() {
		$user                 = wp_get_current_user();
		$display_tokenization = $this->supports( 'tokenization' ) && is_checkout() && $this->saved_cards; /*&& $user->ID*/

		if ( $user->ID ) {
			$user_email = get_user_meta( $user->ID, 'billing_email', true );
			$user_email = $user_email ? $user_email : $user->user_email;
		} else {
			$user_email = '';
		}

		if ( is_add_payment_method_page() ) {
			$pay_button_text = __( 'Add Card', 'robust-nmi-payment-gateway' );
		} else {
			$pay_button_text = '';
		}

		if ( $this->description ) {
			echo wp_kses_post( wpautop( $this->description ) );
		}

		if ( $display_tokenization ) {
			$this->tokenization_script();
			$this->saved_payment_methods();
		}

		?>
		<fieldset id="wc-<?php echo esc_attr( $this->id ); ?>-cc-form" class="wc-credit-card-form wc-payment-form">
			<?php // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WooCommerce core hook
			do_action( 'woocommerce_credit_card_form_start', $this->id ); ?>
	
			<div class="form-row form-row-wide">
				<label for="nmi-card-number"><?php esc_html_e( 'Card Number', 'robust-nmi-payment-gateway' ); ?> <span class="required">*</span></label>
				<div class="nmi-card-group">
					<div id="nmi-ccnumber" class="wc-nmi-elements-field"></div>
					<i class="nmi-credit-card-brand nmi-card-brand" alt="Credit Card"></i>
				</div>
			</div>
	
			<div class="form-row form-row-first">
				<label for="nmi-card-expiry"><?php esc_html_e( 'Card Expiration', 'robust-nmi-payment-gateway' ); ?> <span class="required">*</span></label>
				<div id="nmi-ccexp" class="wc-nmi-elements-field"></div>
			</div>
	
			<div class="form-row form-row-last" style="width: 46%;">
				<label for="nmi-card-cvc"><?php esc_html_e( 'CVV Code', 'robust-nmi-payment-gateway' ); ?> <span class="required">*</span></label>
				<div id="nmi-cvv" class="wc-nmi-elements-field"></div>
			</div>
			<div class="clear"></div>
			<?php // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WooCommerce core hook
			do_action( 'woocommerce_credit_card_form_end', $this->id ); ?>
		</fieldset>
		<?php

		if ( $display_tokenization ) {
			$this->save_payment_method_checkbox();
		}
	}

	public function validate_fields() {
		 global $woocommerce;

		// Only validate saved tokens - new card tokens are handled by JavaScript
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- WooCommerce handles nonce verification for payment processing
		if ( isset( $_POST['wc-nmipay-payment-token'] ) && 'new' !== $_POST['wc-nmipay-payment-token'] ) {
			// phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- WooCommerce handles nonce verification, absint() sanitizes the value
			$token_id = absint( wp_unslash( $_POST['wc-nmipay-payment-token'] ) );
			$token    = WC_Payment_Tokens::get( $token_id );
			if ( $token->get_user_id() !== get_current_user_id() ) {
				// Optionally display a notice with `wc_add_notice`
				wc_add_notice( __( 'There was error processing payment using token please use the card details to continue the checkout.', 'robust-nmi-payment-gateway' ), $notice_type = 'error' );

				if ( $this->debug == 'yes' ) {
					$this->log->add( 'robust_nmi', __( 'There was error processing payment using token please use the card details to continue the checkout.', 'robust-nmi-payment-gateway' ) );
				}
			}
		}
		// For new cards, validation is handled by JavaScript and process_payment
	}

	/**
	 * Handle tokenization logic for both traditional and block checkout
	 * 
	 * @param array $nmipay_args The payment arguments array
	 * @param object $token The payment token object
	 * @param bool $is_saved_token Whether this is a saved token
	 * @param bool $save_card Whether to save the card
	 * @param array $tokens Array of existing tokens
	 * @param int $order_id The order ID
	 * @param bool $is_block_checkout Whether this is block checkout
	 * @return array Modified $nmipay_args
	 */
	private function handle_tokenization($nmipay_args, $token, $is_saved_token, $save_card, $tokens, $order_id, $is_block_checkout) {
		if ($is_saved_token) {
			// Using saved token - use customer_vault_id for the transaction
			$nmipay_args['customer_vault_id'] = $token->token;
			
			if ($this->debug == 'yes') {
				$checkout_type = $is_block_checkout ? 'Block Checkout' : 'Traditional Checkout';
				$this->log->add('robust_nmi', $order_id . ' - ' . $checkout_type . ': Using saved token with vault ID: ' . $token->token);
			}
		} else {
			// New card tokenization
			if ($is_block_checkout) {
				// Block checkout logic
				if (is_user_logged_in() && $save_card && count($tokens) == 0) {
					$nmipay_args['customer_vault'] = 'add_customer';
					$nmipay_args['payment_token'] = $token->token;

					if ($this->debug == 'yes') {
						$this->log->add('robust_nmi', $order_id . ' - Block Checkout: New customer vault');
					}
				} elseif (is_user_logged_in() && $save_card && count($tokens) > 0) {
					$existing_token = WC_Payment_Tokens::get(get_user_meta(get_current_user_id(), 'nmi_cc_token_id', true));
					if ($existing_token) {
						$nmipay_args['customer_vault'] = 'update_customer';
						$nmipay_args['customer_vault_id'] = $existing_token->get_token();
					}
					$nmipay_args['payment_token'] = $token->token;
					
					if ($this->debug == 'yes') {
						$this->log->add('robust_nmi', $order_id . ' - Block Checkout: Update customer vault');
					}
				} else {
					$nmipay_args['payment_token'] = $token->token;
					
					if ($this->debug == 'yes') {
						$this->log->add('robust_nmi', $order_id . ' - Block Checkout: New card with no tokenization');
					}
				}
			} else {
				// Traditional checkout logic
				// phpcs:ignore WordPress.Security.NonceVerification.Missing -- WooCommerce handles nonce verification for payment processing
				if (isset($_POST['wc-nmipay-new-payment-method']) && count($tokens) == 0) {
					$nmipay_args['customer_vault'] = 'add_customer';
					$nmipay_args['payment_token'] = $token->token;

					if ($this->debug == 'yes') {
						// phpcs:ignore WordPress.Security.NonceVerification.Missing -- WooCommerce handles nonce verification for payment processing
						$this->log->add('robust_nmi', $order_id . ' - Token Count: ' . count($tokens) . ' Token Param: ' . sanitize_text_field( wp_unslash( $_POST['wc-nmipay-new-payment-method'] ) ) );
					}
				// phpcs:ignore WordPress.Security.NonceVerification.Missing -- WooCommerce handles nonce verification for payment processing
				} elseif (isset($_POST['wc-nmipay-new-payment-method']) && isset($_POST['wc-nmipay-payment-token']) && 'new' == $_POST['wc-nmipay-payment-token'] && count($tokens) > 0) {
					$existing_token = WC_Payment_Tokens::get(get_user_meta(get_current_user_id(), 'nmi_cc_token_id', true));

					$nmipay_args['customer_vault'] = 'update_customer';
					$nmipay_args['customer_vault_id'] = $existing_token->get_token();
					$nmipay_args['payment_token'] = $token->token;

					if ($this->debug == 'yes') {
						// phpcs:ignore WordPress.Security.NonceVerification.Missing -- WooCommerce handles nonce verification for payment processing
						$this->log->add('robust_nmi', $order_id . ' - Custom Saved Token : ' . $existing_token->get_id() . ' Token Param: ' . sanitize_text_field( wp_unslash( $_POST['wc-nmipay-new-payment-method'] ) ) );
					}
				} else {
					$nmipay_args['payment_token'] = $token->token;

					if ($this->debug == 'yes') {
						$this->log->add('robust_nmi', $order_id . ' - New Card with no Tokenisation');
					}
				}
			}
		}
		
		return $nmipay_args;
	}

	/**
	 * Send request to NMI API
	 */
	private function send_request( $args ) {
		$name_value_pairs = array();
		foreach ( $args as $key => $value ) {
			$name_value_pairs[] = $key . '=' . urlencode( $value );
		}
		$gateway_values = implode( '&', $name_value_pairs );

		$api_url = $this->environment === 'sandbox' ? 'https://secure.networkmerchants.com' : 'https://secure.networkmerchants.com';
		$nmi_adr = $api_url . '/api/transact.php?';

		if ( $this->debug == 'yes' ) {
			$this->log->add( 'robust_nmi', 'NMI Request: ' . $gateway_values );
		}

		$response = wp_remote_post(
			$nmi_adr,
			array(
				'body'      => $gateway_values,
				'sslverify' => false,
				'timeout'   => 60,
			)
		);

		if ( is_wp_error( $response ) ) {
			if ( $this->debug == 'yes' ) {
				$this->log->add( 'robust_nmi', 'NMI Error: ' . $response->get_error_message() );
			}
			return false;
		}

		parse_str( $response['body'], $response_data );

		if ( $this->debug == 'yes' ) {
			// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug logging only when debug mode enabled
			$this->log->add( 'robust_nmi', 'NMI Response: ' . print_r( $response_data, true ) );
		}

		return $response_data;
	}

	/**
	 * Process the payment and return the result.
	 * 
	 * phpcs:disable WordPress.Security.NonceVerification.Missing -- WooCommerce handles nonce verification for payment processing
	 **/
	public function process_payment( $order_id ) {
		global $woocommerce;

		$order = wc_get_order( (int)$order_id);

		// Check payment method type selection
		// Process Credit Card payment
		// Handle both traditional checkout and block checkout
		$token = null;
		$tds = null;
		
		// Check if this is a block checkout request - look for the block checkout data format
		$is_block_checkout = false;
		
		// First check if we have the WooCommerce block checkout context
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash -- REQUEST_URI is used for string comparison only
		if (defined('REST_REQUEST') && REST_REQUEST && isset($_SERVER['REQUEST_URI']) && 
			strpos( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ), '/wp-json/wc/store/v1/checkout') !== false) {
			$is_block_checkout = true;
			
			if ($this->debug == 'yes') {
					$this->log->add('robust_nmi', $order_id . ' - Block checkout REST request detected');
				// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug logging only when debug mode enabled
				$this->log->add('robust_nmi', $order_id . ' - POST data: ' . print_r($_POST, true));
			}
		}
		
		// Handle block checkout data format
		if ($is_block_checkout) {
			// In block checkout, the payment data comes in a different format
			// Look for payment_method_data first (if already processed)
			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- WooCommerce handles nonce verification for payment processing
			if (isset($_POST['payment_method_data']) && is_array($_POST['payment_method_data'])) {
				// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash -- Data sanitized below
				$payment_method_data_raw = $_POST['payment_method_data'];
				$payment_method_data = array();
				foreach ( $payment_method_data_raw as $key => $value ) {
					$payment_method_data[ sanitize_key( $key ) ] = sanitize_text_field( wp_unslash( $value ) );
				}
				
				// Check for saved token usage first
				if (isset($payment_method_data['wc-nmipay-payment-token']) && 
					$payment_method_data['wc-nmipay-payment-token'] !== 'new' &&
					is_numeric($payment_method_data['wc-nmipay-payment-token'])) {
					// This is a saved token, not a new card
					$token = $this->validate_saved_token($payment_method_data['wc-nmipay-payment-token']);
					
					if ($token) {
						if ($this->debug == 'yes') {
							$this->log->add('robust_nmi', $order_id . ' - Block checkout using saved token: ' . sanitize_text_field( wp_unslash( $payment_method_data['wc-nmipay-payment-token'] ) ) );
						}
					} else {
						if ($this->debug == 'yes') {
							$this->log->add('robust_nmi', $order_id . ' - Invalid saved token or user mismatch');
						}
						wc_add_notice('Invalid saved payment method. Please try again.', 'error');
						return array(
							'result' => 'failure',
							'redirect' => ''
						);
					}
				} else {
					// This is a new card token
					if (isset($payment_method_data['nmipay_payment_token'])) {
						$token_data = sanitize_text_field( wp_unslash( $payment_method_data['nmipay_payment_token'] ) );
						$token = json_decode( stripslashes( $token_data ) );
					}
				}
				
				if (isset($payment_method_data['nmipay_payment_3ds'])) {
					$tds_data = sanitize_text_field( wp_unslash( $payment_method_data['nmipay_payment_3ds'] ) );
					$tds = json_decode( stripslashes( $tds_data ) );
				}
				
				if ($this->debug == 'yes') {
					$this->log->add('robust_nmi', $order_id . ' - Block checkout using payment_method_data');
				}
			}
			// If not found, try direct POST fields (fallback)
			else if (isset($_POST['nmipay_payment_token'])) {
				$token_data = sanitize_text_field( wp_unslash( $_POST['nmipay_payment_token'] ) );
				$token = json_decode( stripslashes( $token_data ) );
				
				if (isset($_POST['nmipay_payment_3ds'])) {
					$tds_data = sanitize_text_field( wp_unslash( $_POST['nmipay_payment_3ds'] ) );
					$tds = json_decode( stripslashes( $tds_data ) );
				}
				
				if ($this->debug == 'yes') {
					$this->log->add('robust_nmi', $order_id . ' - Block checkout using direct POST fields');
				}
			}
			// Check for saved token in the token field from payload
			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- WooCommerce handles nonce verification for payment processing
			else if (isset($_POST['token']) && is_numeric($_POST['token'])) {
				// This is a saved token from the payload
				$token_id = absint( wp_unslash( $_POST['token'] ) );
				$token = $this->validate_saved_token($token_id);
				
				if ($token) {
					if ($this->debug == 'yes') {
						$this->log->add('robust_nmi', $order_id . ' - Block checkout using saved token from payload: ' . $token_id);
					}
				} else {
					if ($this->debug == 'yes') {
						$this->log->add('robust_nmi', $order_id . ' - Invalid saved token from payload or user mismatch');
					}
					wc_add_notice('Invalid saved payment method. Please try again.', 'error');
					return array(
						'result' => 'failure',
						'redirect' => ''
					);
				}
			}
		} else {
			// Traditional checkout
			// Check for saved token first
			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- WooCommerce handles nonce verification for payment processing
			if (isset($_POST['wc-nmipay-payment-token']) && 
				$_POST['wc-nmipay-payment-token'] !== 'new' &&
				is_numeric($_POST['wc-nmipay-payment-token'])) {
				// This is a saved token, not a new card
				$token_id = absint( wp_unslash( $_POST['wc-nmipay-payment-token'] ) );
				$saved_token = WC_Payment_Tokens::get($token_id);
				
				if ($saved_token && $saved_token->get_user_id() === get_current_user_id()) {
					// Create a token object that mimics the CollectJS response
					$token = (object) array(
						'token' => $saved_token->get_token(),
						'card' => (object) array(
							'number' => '****' . $saved_token->get_last4(),
							'exp' => sprintf('%02d%s', $saved_token->get_expiry_month(), substr($saved_token->get_expiry_year(), -2)),
							'type' => $saved_token->get_card_type()
						)
					);
					
					if ($this->debug == 'yes') {
						$this->log->add('robust_nmi', $order_id . ' - Traditional checkout using saved token: ' . $token_id);
					}
				} else {
					if ($this->debug == 'yes') {
						$this->log->add('robust_nmi', $order_id . ' - Invalid saved token or user mismatch in traditional checkout');
					}
					wc_add_notice('Invalid saved payment method. Please try again.', 'error');
					return array(
						'result' => 'failure',
						'redirect' => ''
					);
				}
			} else {
				// This is a new card, get token from CollectJS
				if( isset($_POST['nmipay_payment_token']) ){
					$token_data = sanitize_text_field( wp_unslash( $_POST['nmipay_payment_token'] ) );
					$token = json_decode( stripslashes( $token_data ) );
					
					if ($this->debug == 'yes') {
						$this->log->add('robust_nmi', $order_id . ' - Received payment token from POST');
						// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug logging only when debug mode enabled
						$this->log->add('robust_nmi', $order_id . ' - POST data: ' . print_r($_POST, true));
					}
				} else {
					if ($this->debug == 'yes') {
						$this->log->add('robust_nmi', $order_id . ' - nmipay_payment_token not in POST');
						// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug logging only when debug mode enabled
						$this->log->add('robust_nmi', $order_id . ' - POST keys: ' . print_r(array_keys($_POST), true));
					}
				}
			}

			if( isset($_POST['nmipay_payment_3ds']) ){
				$tds_data = sanitize_text_field( wp_unslash( $_POST['nmipay_payment_3ds'] ) );
				$tds = json_decode( stripslashes( $tds_data ) );
			}
			
			if ($this->debug == 'yes') {
				$this->log->add('robust_nmi', $order_id . ' - Traditional checkout detected');
			}
		}
		
		// Validate that we have a payment token
		if (!$token || !isset($token->token)) {
			if ($this->debug == 'yes') {
				$this->log->add('robust_nmi', $order_id . ' - No valid payment token found');
				// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug logging only when debug mode enabled
				$this->log->add('robust_nmi', $order_id . ' - Token object: ' . print_r($token, true));
				// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug logging only when debug mode enabled
				$this->log->add('robust_nmi', $order_id . ' - All POST data: ' . print_r($_POST, true));
			}
			
			wc_add_notice('Payment Token not received. Please try again.', 'error');
			return array(
				'result' => 'failure',
				'redirect' => ''
			);
		}

		$last_four_digits = substr( $token->card->number, -4 );
		$ccexp_expiry = $token->card->exp;
		$cardtype =  $token->card->type;

		$nmi_adr = $this->api_url . '/api/transact.php?';

		$tokens = WC_Payment_Tokens::get_customer_tokens( get_current_user_id(), 'nmipay' );

		if ( $this->debug == 'yes' ) {
			$this->log->add( 'robust_nmi', $order_id . ' - CC Processing Started' );
		}

		// Handle tokenization logic for both traditional and block checkout
		$is_saved_token = false;
		$save_card = false;
		
		if ($is_block_checkout) {
			// Check multiple possible locations for saved token indicator
			if ((isset($_POST['payment_method_data']['wc-nmipay-payment-token']) && 
				 $_POST['payment_method_data']['wc-nmipay-payment-token'] !== 'new' &&
				 is_numeric($_POST['payment_method_data']['wc-nmipay-payment-token'])) ||
				(isset($_POST['token']) && is_numeric($_POST['token']))) {
				$is_saved_token = true;
			}
			
			// Check if user wants to save the card
			if (isset($_POST['payment_method_data']['wc-nmipay-new-payment-method']) && 
				$_POST['payment_method_data']['wc-nmipay-new-payment-method'] === true) {
				$save_card = true;
			}
		} else {
			// Traditional checkout - check if this is a saved token
			if (isset($_POST['wc-nmipay-payment-token']) && 
				$_POST['wc-nmipay-payment-token'] !== 'new' &&
				is_numeric($_POST['wc-nmipay-payment-token'])) {
				$is_saved_token = true;
			}
		}
		
		// Use the unified tokenization method
		$nmipay_args = $this->handle_tokenization($nmipay_args, $token, $is_saved_token, $save_card, $tokens, $order_id, $is_block_checkout);

		if ( $this->receipt ) {
			$nmipay_args['customer_receipt'] = $this->receipt;
		}

		// Processing subscription
		if ( function_exists( 'wcs_order_contains_subscription' ) || function_exists( 'wcs_is_subscription' ) ) {
			if ( wcs_order_contains_subscription( $order_id ) || wcs_is_subscription( $order_id ) ) {
				$nmipay_args['type']      = $this->transtype;
				$nmipay_args['payment']   = 'creditcard';
				// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- IP address from server variable
				$nmipay_args['ipaddress'] = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '';
				$nmipay_args['security_key']  = $this->security_key;
				$nmipay_args['currency']  = get_woocommerce_currency();

				$nmipay_args['orderid'] = $order->get_order_number() . '-' . time();

				$nmipay_args = $this->set_billing_and_shipping_address( $nmipay_args, $order );

				$nmipay_args['email'] = $order->get_billing_email();

				$nmipay_args['invoice'] = $order->get_order_key();

				$AmountInput = number_format( $order->get_total(), 2, '.', '' );

				$nmipay_args['amount'] = $AmountInput;

				if ( in_array( $order->get_billing_country(), array( 'US', 'CA' ) ) ) {
					$order->billing_phone = str_replace( array( '( ', '-', ' ', ' )', '.' ), '', $order->get_billing_phone() );
					$nmipay_args['phone'] = $order->billing_phone;
				} else {
					$nmipay_args['phone'] = $order->get_billing_phone();
				}
				// var_dump($order->get_total_tax());die;
				// Tax
				$nmipay_args['tax'] = $order->get_total_tax();

				if ( $this->send_details ) {
					// Cart Contents
					$item_loop = 0;
					if ( sizeof( $order->get_items() ) > 0 ) {
						foreach ( $order->get_items() as $item ) {
							if ( $item->get_quantity() > 0 ) {
								++$item_loop;

								$item_name = $item->get_name();
								$item_meta = wp_strip_all_tags(
									wc_display_item_meta(
										$item,
										array(
											'before'    => '',
											'separator' => ', ',
											'after'     => '',
											'echo'      => false,
											'autop'     => false,
										)
									)
								);
								if ( $item_meta ) {
									$item_name .= ' (' . $item_meta . ')';
								}

								$product = $item->get_product();

								$sku = $product->get_sku();
								if ( empty( $product->get_sku() ) || $product->get_sku() == '' ) {
									$sku = 'N/A';
								}

								$nmipay_args[ 'item_product_code_' . $item_loop ] = $sku;
								$nmipay_args[ 'item_tax_amount_' . $item_loop ]   = $item->get_total_tax();
								$nmipay_args[ 'item_description_' . $item_loop ]  = $item_name;
								$nmipay_args[ 'item_unit_cost_' . $item_loop ]    = $order->get_item_subtotal( $item, false );
								$nmipay_args[ 'item_quantity_' . $item_loop ]     = $item->get_quantity();
								$item_total_amount                                = $order->get_item_subtotal( $item, false ) * $item->get_quantity();
								$nmipay_args[ 'item_total_amount_' . $item_loop ] = $item_total_amount;
							}
						}
					}
				}

				// Discount
				if ( $order->get_total_discount() > 0 ) {
					$nmipay_args['discount_amount'] = number_format( $order->get_total_discount(), 2, '.', '' );
				}

				// Shipping Cost item - nmipay only allows shipping per item, we want to send shipping for the order
				if ( $order->get_total_shipping() > 0 ) {
					$nmipay_args['shipping'] = number_format( $order->get_total_shipping(), 2, '.', '' );
				}

				$subscriptions = wcs_get_subscriptions_for_order( $order );

				$subscription = array_pop( $subscriptions );

				if ( ! empty( $subscription ) ) {
					$order_items = $order->get_items();

					$unconverted_periods = array(
						'billing_period' => $subscription->billing_period,
						'trial_period'   => $subscription->trial_period,
					);

					$converted_periods = array();

					// Convert period strings into PayPay's format
					foreach ( $unconverted_periods as $key => $period ) {
						switch ( strtolower( $period ) ) {
							case 'day':
								$converted_periods[ $key ] = 'day';
								break;
							case 'week':
								$converted_periods[ $key ] = 'week';
								break;
							case 'year':
								$converted_periods[ $key ] = 'year';
								break;
							case 'month':
							default:
								$converted_periods[ $key ] = 'month';
								break;
						}
					}

					$sign_up_fee            = $subscription->get_sign_up_fee();
					$price_per_period       = $subscription->get_total();
					$subscription_interval  = $subscription->billing_interval;
					$start_timestamp        = $subscription->get_time( 'start' );
					$trial_end_timestamp    = $subscription->get_time( 'trial_end' );
					$next_payment_timestamp = $subscription->get_time( 'next_payment' );

					$is_synced_subscription = WC_Subscriptions_Synchroniser::subscription_contains_synced_product( $subscription->id );

					if ( $is_synced_subscription ) {
						$length_from_timestamp = $next_payment_timestamp;
					} elseif ( $trial_end_timestamp > 0 ) {
						$length_from_timestamp = $trial_end_timestamp;
					} else {
						$length_from_timestamp = $start_timestamp;
					}

					$subscription_length = wcs_estimate_periods_between( $length_from_timestamp, $subscription->get_time( 'end' ), $subscription->billing_period );

					$subscription_installments = $subscription_length / $subscription_interval;

					$initial_payment = $order->get_total();

					if ( $initial_payment == '0.00' ) {
						$initial_payment = '0.01';
					}

					if ( $subscription_trial_length > 0 ) {
						$trial_until = wcs_calculate_paypal_trial_periods_until( $next_payment_timestamp );

						$subscription_trial_length         = $trial_until['first_trial_length'];
						$converted_periods['trial_period'] = $trial_until['first_trial_period'];

						$dateformat = 'Ymd';
						$todayDate  = gmdate( $dateformat );
						$startdate  = gmdate( $dateformat, strtotime( gmdate( $dateformat, strtotime( $todayDate ) ) . ' +' . $subscription_trial_length . ' ' . $converted_periods['trial_period'] ) );

						$nmipay_args['plan_payments'] = $subscription_installments;

						if ( $subscription_installments > 1 ) {
							$nmipay_args['plan_payments'] = $subscription_installments - 1;
						}

						$nmipay_args['amount'] = $initial_payment;

						$nmipay_args['plan_amount'] = $price_per_period;

						if ( $converted_periods['billing_period'] == 'day' ) {
							$nmipay_args['day_frequency'] = $subscription_interval;
						} elseif ( $converted_periods['billing_period'] == 'week' ) {
							$nmipay_args['day_frequency'] = $subscription_interval * 7;
						} elseif ( $converted_periods['billing_period'] == 'year' ) {
							$nmipay_args['month_frequency'] = $subscription_interval * 12;
							$timestamp                      = strtotime( $startdate );
							$day                            = gmdate( 'd', $timestamp );
							$nmipay_args['day_of_month']    = $day;
						} else {
							$nmipay_args['month_frequency'] = $subscription_interval;
							$timestamp                      = strtotime( $startdate );
							$day                            = gmdate( 'd', $timestamp );
							$nmipay_args['day_of_month']    = $day;
						}
					} else {
						$dateformat = 'Ymd';
						$startdate  = gmdate( $dateformat );

						$nmipay_args['plan_payments'] = $subscription_installments;

						if ( $subscription_installments > 1 ) {
							$nmipay_args['plan_payments'] = $subscription_installments - 1;
						}

						$nmipay_args['amount'] = $initial_payment;

						$nmipay_args['plan_amount'] = $price_per_period;

						if ( $converted_periods['billing_period'] == 'day' ) {
							$nmipay_args['day_frequency'] = $subscription_interval;
							$startdate                    = gmdate( $dateformat, strtotime( gmdate( $dateformat, strtotime( $startdate ) ) . ' +1 day' ) );
						} elseif ( $converted_periods['billing_period'] == 'week' ) {
							$nmipay_args['day_frequency'] = $subscription_interval * 7;
							$startdate                    = gmdate( $dateformat, strtotime( gmdate( $dateformat, strtotime( $startdate ) ) . ' +1 week' ) );
						} elseif ( $converted_periods['billing_period'] == 'year' ) {
							$nmipay_args['month_frequency'] = $subscription_interval * 12;
							$startdate                      = gmdate( $dateformat, strtotime( gmdate( $dateformat, strtotime( $startdate ) ) . ' +1 year' ) );
							$timestamp                      = strtotime( $startdate );
							$day                            = gmdate( 'd', $timestamp );
							$nmipay_args['day_of_month']    = $day;
						} else {
							$nmipay_args['month_frequency'] = $subscription_interval;
							$timestamp                      = strtotime( $startdate );
							$day                            = gmdate( 'd', $timestamp );
							$nmipay_args['day_of_month']    = $day;
							$startdate                      = gmdate( $dateformat, strtotime( gmdate( $dateformat, strtotime( $startdate ) ) . ' +1 month' ) );
						}
					}

					if( $subscription->get_date('next_payment') != '' ){

						$date = new DateTime($subscription->get_date('next_payment'));
						$formatted_date = $date->format('Ymd'); // Format as YYYYMMDD
						
						if ( $this->debug == 'yes' ) {
							
	
							$this->log->add( 'robust_nmi', $order_id . ' - Next Renewal Date' . $formatted_date );

						}
						
					}else{
						
						if ( $this->debug == 'yes' ) {
							
	
							$this->log->add( 'robust_nmi', $order_id . ' - No Renewal Date Provided' );

						}
						

					}
					

					$nmipay_args['start_date'] = $formatted_date;

					$nmipay_args['recurring'] = 'add_subscription';

					// Add billing_method if enabled
					if ( $this->send_billing_method == 'yes' ) {
						$nmipay_args['billing_method'] = 'recurring';
					}
					
				}
			} else {
				$nmipay_args['type']      = $this->transtype;
				$nmipay_args['payment']   = 'creditcard';
				// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- IP address from server variable
				$nmipay_args['ipaddress'] = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '';
				$nmipay_args['security_key']  = $this->security_key;
				$nmipay_args['currency']  = get_woocommerce_currency();

				$nmipay_args['orderid'] = $order->get_order_number() . '-' . time();

				$nmipay_args = $this->set_billing_and_shipping_address( $nmipay_args, $order );

				$nmipay_args['email'] = $order->get_billing_email();

				$nmipay_args['invoice'] = $order->get_order_key();

				$AmountInput = number_format( $order->get_total(), 2, '.', '' );

				$nmipay_args['amount'] = $AmountInput;

				if ( in_array( $order->get_billing_country(), array( 'US', 'CA' ) ) ) {
					$order->billing_phone = str_replace( array( '( ', '-', ' ', ' )', '.' ), '', $order->get_billing_phone() );
					$nmipay_args['phone'] = $order->billing_phone;
				} else {
					$nmipay_args['phone'] = $order->get_billing_phone();
				}
				// var_dump($order->get_total_tax());die;
				// Tax
				$nmipay_args['tax'] = $order->get_total_tax();

				if ( $this->send_details ) {
					// Cart Contents
					$item_loop = 0;
					if ( sizeof( $order->get_items() ) > 0 ) {
						foreach ( $order->get_items() as $item ) {
							if ( $item->get_quantity() > 0 ) {
								++$item_loop;

								$item_name = $item->get_name();
								$item_meta = wp_strip_all_tags(
									wc_display_item_meta(
										$item,
										array(
											'before'    => '',
											'separator' => ', ',
											'after'     => '',
											'echo'      => false,
											'autop'     => false,
										)
									)
								);
								if ( $item_meta ) {
									$item_name .= ' (' . $item_meta . ')';
								}

								$product = $item->get_product();
								$sku     = $product->get_sku();
								if ( empty( $product->get_sku() ) || $product->get_sku() == '' ) {
									$sku = 'N/A';
								}

								$nmipay_args[ 'item_product_code_' . $item_loop ] = $sku;
								$nmipay_args[ 'item_tax_amount_' . $item_loop ]   = $item->get_total_tax();
								$nmipay_args[ 'item_description_' . $item_loop ]  = $item_name;
								$nmipay_args[ 'item_unit_cost_' . $item_loop ]    = $order->get_item_subtotal( $item, false );
								$nmipay_args[ 'item_quantity_' . $item_loop ]     = $item->get_quantity();
								$item_total_amount                                = $order->get_item_subtotal( $item, false ) * $item->get_quantity();
								$nmipay_args[ 'item_total_amount_' . $item_loop ] = $item_total_amount;
							}
						}
					}
				}

				// Discount
				if ( $order->get_total_discount() > 0 ) {
					$nmipay_args['discount_amount'] = number_format( $order->get_total_discount(), 2, '.', '' );
				}

				// Shipping Cost item - nmipay only allows shipping per item, we want to send shipping for the order
				if ( $order->get_total_shipping() > 0 ) {
					$nmipay_args['shipping'] = number_format( $order->get_total_shipping(), 2, '.', '' );
				}
			}

			// Processing standard
		} else {

			$nmipay_args['type']      = $this->transtype;
			$nmipay_args['payment']   = 'creditcard';
			// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- IP address from server variable
			$nmipay_args['ipaddress'] = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '';
			$nmipay_args['security_key']  = $this->security_key;
			$nmipay_args['currency']  = get_woocommerce_currency();

			$nmipay_args['orderid'] = $order->get_order_number() . '-' . time();

			$nmipay_args = $this->set_billing_and_shipping_address( $nmipay_args, $order );

			$nmipay_args['email'] = $order->get_billing_email();

			$nmipay_args['invoice'] = $order->get_order_key();

			$AmountInput = number_format( $order->get_total(), 2, '.', '' );

			$nmipay_args['amount'] = $AmountInput;

			if ( in_array( $order->get_billing_country(), array( 'US', 'CA' ) ) ) {
				$order->billing_phone = str_replace( array( '( ', '-', ' ', ' )', '.' ), '', $order->get_billing_phone() );
				$nmipay_args['phone'] = $order->billing_phone;
			} else {
				$nmipay_args['phone'] = $order->get_billing_phone();
			}
			// var_dump($order->get_total_tax());die;
			// Tax
			$nmipay_args['tax'] = $order->get_total_tax();

			if ( $this->send_details ) {
				// Cart Contents
				$item_loop = 0;
				if ( sizeof( $order->get_items() ) > 0 ) {
					foreach ( $order->get_items() as $item ) {
						if ( $item->get_quantity() > 0 ) {
							++$item_loop;

							$item_name = $item->get_name();
							$item_meta = wp_strip_all_tags(
								wc_display_item_meta(
									$item,
									array(
										'before'    => '',
										'separator' => ', ',
										'after'     => '',
										'echo'      => false,
										'autop'     => false,
									)
								)
							);
							if ( $item_meta ) {
								$item_name .= ' (' . $item_meta . ')';
							}

							$product = $item->get_product();
							$sku     = $product->get_sku();
							if ( empty( $product->get_sku() ) || $product->get_sku() == '' ) {
								$sku = 'N/A';
							}

							$nmipay_args[ 'item_product_code_' . $item_loop ] = $sku;
							$nmipay_args[ 'item_tax_amount_' . $item_loop ]   = $item->get_total_tax();
							$nmipay_args[ 'item_description_' . $item_loop ]  = $item_name;
							$nmipay_args[ 'item_unit_cost_' . $item_loop ]    = $order->get_item_subtotal( $item, false );
							$nmipay_args[ 'item_quantity_' . $item_loop ]     = $item->get_quantity();
							$item_total_amount                                = $order->get_item_subtotal( $item, false ) * $item->get_quantity();
							$nmipay_args[ 'item_total_amount_' . $item_loop ] = $item_total_amount;
						}
					}
				}

				if ( ! empty( $nmipay_args['discount_amount'] ) ) {
					++$item_loop;

					$nmipay_args[ 'item_product_code_' . $item_loop ] = 'N/A';
					$nmipay_args[ 'item_tax_amount_' . $item_loop ]   = 0;
					$nmipay_args[ 'item_description_' . $item_loop ]  = 'Discount';
					$nmipay_args[ 'item_unit_cost_' . $item_loop ]    = -$nmipay_args['discount_amount'];
					$nmipay_args[ 'item_quantity_' . $item_loop ]     = 1;
					$nmipay_args[ 'item_total_amount_' . $item_loop ] = -$nmipay_args['discount_amount'];
				}
			}

			// Discount
			if ( $order->get_total_discount() > 0 ) {
				$nmipay_args['discount_amount'] = number_format( $order->get_total_discount(), 2, '.', '' );
			}

			// Shipping Cost item - nmipay only allows shipping per item, we want to send shipping for the order
			if ( $order->get_total_shipping() > 0 ) {
				$nmipay_args['shipping'] = number_format( $order->get_total_shipping(), 2, '.', '' );
			}
			
			// Add billing_method if enabled
			if ( $this->send_billing_method == 'yes' ) {
				$nmipay_args['billing_method'] = 'creditcard';
			}
		}

		// Handle descriptor for both traditional and block checkout
		if ($is_block_checkout) {
			// For block checkout, use gateway settings
			if ( ! empty( $this->descriptor ) ) {
				$nmipay_args['descriptor'] = $this->descriptor;
			}
			if ( ! empty( $this->descriptor_url ) ) {
				$nmipay_args['descriptor_url'] = $this->descriptor_url;
			}
		} else {
			// Traditional checkout can override descriptor
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- WooCommerce handles nonce verification for payment processing
		if ( ! empty( $_POST['descriptor'] ) && isset( $_POST['descriptor'] ) ) {
			$nmipay_args['descriptor'] = sanitize_text_field( wp_unslash( $_POST['descriptor'] ) );
		} elseif ( ! empty( $this->descriptor ) ) {
			$nmipay_args['descriptor'] = $this->descriptor;
		}

		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- WooCommerce handles nonce verification for payment processing
		if ( ! empty( $_POST['descriptor_url'] ) && isset( $_POST['descriptor_url'] ) ) {
			$nmipay_args['descriptor_url'] = esc_url_raw( wp_unslash( $_POST['descriptor_url'] ) );
		} elseif ( ! empty( $this->descriptor_url ) ) {
			$nmipay_args['descriptor_url'] = $this->descriptor_url;
		}
		}

		// Handle processor_id and other fields for both traditional and block checkout
		if ($is_block_checkout) {
			// For block checkout, use gateway settings
			if ( ! empty( $this->processor_id ) ) {
				$nmipay_args['processor_id'] = $this->processor_id;
			}
			
			if ( ! empty( $this->dup_seconds ) && (int) $this->dup_seconds > 0 ) {
				$nmipay_args['dup_seconds'] = $this->dup_seconds;
			}
			
			// Add merchant defined field 1 (blog name)
			$nmipay_args['merchant_defined_field_1'] = get_bloginfo( 'name' );
		} else {
			// Traditional checkout can override processor_id
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- WooCommerce handles nonce verification for payment processing
		if ( ! empty( $_POST['processor_id'] ) && isset( $_POST['processor_id'] ) ) {
			$nmipay_args['processor_id'] = sanitize_text_field( wp_unslash( $_POST['processor_id'] ) );
		} elseif ( ! empty( $this->processor_id ) ) {
			$nmipay_args['processor_id'] = $this->processor_id;
		}

		if ( ! empty( $this->dup_seconds ) && (int) $this->dup_seconds > 0 ) {
			$nmipay_args['dup_seconds'] = $this->dup_seconds;
		}

		for ( $fn = 1; $fn < 21; ++$fn ) {
			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- WooCommerce handles nonce verification for payment processing
			if ( ! empty( $_POST[ "merchant_defined_field_$fn" ] ) ) {
				$nmipay_args[ "merchant_defined_field_$fn" ] = sanitize_text_field( wp_unslash( $_POST[ "merchant_defined_field_$fn" ] ) );
			}
		}

		if ( empty( $_POST['merchant_defined_field_1'] ) ) {
			$nmipay_args['merchant_defined_field_1'] = get_bloginfo( 'name' );
		}
		}





		// Handle 3DS data for both traditional and block checkout
		if( !empty($tds) && $this->checkout_public_key != '' && $this->enable_3dsecure == 'yes' ){
			// Handle both object and array format
			$cardHolderAuth = is_object($tds) ? $tds->cardHolderAuth : $tds['cardHolderAuth'];
			
			if( $cardHolderAuth == 'verified' ){
				$nmipay_args['cavv'] = is_object($tds) ? $tds->cavv : $tds['cavv'];
				$nmipay_args['xid'] = is_object($tds) ? $tds->xid : $tds['xid'];
				$nmipay_args['eci'] = is_object($tds) ? $tds->eci : $tds['eci'];
				$nmipay_args['cardholder_auth'] = $cardHolderAuth;
				$nmipay_args['three_ds_version'] = is_object($tds) ? $tds->threeDsVersion : $tds['threeDsVersion'];

				// FIX: Only access as object or array, not both
				if (is_object($tds)) {
					if (isset($tds->directoryServiceId)) {
				$nmipay_args['directory_server_id'] = $tds->directoryServiceId;
			}
					if (isset($tds->directoryServerId)) {
				$nmipay_args['directory_server_id'] = $tds->directoryServerId;
					}
				} elseif (is_array($tds)) {
					if (isset($tds['directoryServiceId'])) {
						$nmipay_args['directory_server_id'] = $tds['directoryServiceId'];
					}
					if (isset($tds['directoryServerId'])) {
						$nmipay_args['directory_server_id'] = $tds['directoryServerId'];
					}
			}
			
			// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug data storage
			$order->update_meta_data( 'NMI 3DS Response', print_r($tds,true) );
			$order->save();

			} else if( $cardHolderAuth != 'verified' ){
				/* translators: %s: Card holder authentication response */
				$order->add_order_note( sprintf( __( '3DS Auth Failed. %s', 'robust-nmi-payment-gateway' ), print_r( $cardHolderAuth, true ) ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug data in order note

			if ( $this->debug == 'yes' ) {
				/* translators: %s: 3DS authentication response */
				$error_message = __( '3DS Auth Failed. %s', 'robust-nmi-payment-gateway' );
				// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug logging only when debug mode enabled
				$this->log->add( 'robust_nmi', $order_id . ' - ' . sprintf( $error_message, print_r( $tds, true ) ) );
			}
			
				if ($is_block_checkout) {
					return array(
						'result' => 'failure',
						'message' => __( '3DS Check Failed.', 'robust-nmi-payment-gateway' )
					);
				} else {
					wc_add_notice( __( '3DS Check Failed.', 'robust-nmi-payment-gateway' ), $notice_type = 'error' );
			return;
				}
			}
			
			// Check for null/empty 3DS response
			$xid = is_object($tds) ? $tds->xid : $tds['xid'];
			$cavv = is_object($tds) ? $tds->cavv : $tds['cavv'];
			$eci = is_object($tds) ? $tds->eci : $tds['eci'];
			$threeDsVersion = is_object($tds) ? $tds->threeDsVersion : $tds['threeDsVersion'];
			
			if( $xid == '' && $cavv == '' && $eci == '' && $cardHolderAuth == '' && $threeDsVersion == '' ){
			$order->add_order_note( __( '3DS Auth Failed. Received Null Response.', 'robust-nmi-payment-gateway' ) );
				
			if ( $this->debug == 'yes' ) {
				$this->log->add( 'robust_nmi', $order_id . ' - ' . __( '3DS Auth Failed. Received Null Response.', 'robust-nmi-payment-gateway' ) );
			}
			
				if ($is_block_checkout) {
					return array(
						'result' => 'failure',
						'message' => __( 'Unable to verify card through 3D Secure. Please try again.', 'robust-nmi-payment-gateway' )
					);
				} else {
					wc_add_notice( __( 'Unable to verify card through 3D Secure. Please try again.', 'robust-nmi-payment-gateway' ), $notice_type = 'error' );
			return;
				}
			}
		}




		$name_value_pairs = array();
		foreach ( $nmipay_args as $key => $value ) {
			$name_value_pairs[] = $key . '=' . urlencode( $value );
		}
		$gateway_values = implode( '&', $name_value_pairs );

		$response = wp_remote_post(
			$nmi_adr,
			array(
				'body'      => $gateway_values,
				'sslverify' => false,
				'timeout'   => 60,
			)
		);

		if ( $this->debug == 'yes' ) {
			$nmipay_args['ccnumber'] = 'XXXX-XXXX-XXXX-' . $last_four_digits;
			$nmipay_args['cvv']      = 'XXX';
			// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug logging only when debug mode enabled
			$this->log->add( 'robust_nmi', $order_id . ' - NMI CC Order Response: ' . print_r( $nmipay_args, true ) );
		}

		if ( ! is_wp_error( $response ) && $response['response']['code'] >= 200 && $response['response']['code'] < 300 ) {
			parse_str( $response['body'], $response );

			if ( $this->debug == 'yes' ) {
				// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug logging only when debug mode enabled
				$this->log->add( 'robust_nmi', $order_id . ' - NMI CC Order Response: ' . print_r( $response, true ) );
			}

			if ( $response['response'] == '1' ) {
				// Payment completed
				/* translators: %1$s: Transaction ID, %2$s: Card type, %3$s: Last four digits, %4$s: Expiry date */
				$order->add_order_note( sprintf( __( 'The NMI Payment transaction is successful. The Transaction Id is %1$s. %2$s Card with last digits %3$s and expiry %4$s', 'robust-nmi-payment-gateway' ), $response['transactionid'], $cardtype, $last_four_digits, $ccexp_expiry ) );
				$order->payment_complete( $response['transactionid'] );

		
				$order->update_meta_data( 'NMI Transaction ID', $response['transactionid'] );

				if ( isset( $response['subscription_id'] ) ) {

					$order->update_meta_data( 'NMI Subscriber ID', $response['subscription_id'] );
					if ( class_exists( 'WC_Subscriptions_Order' ) ) {
						WC_Subscriptions_Manager::activate_subscriptions_for_order( $order );
					}
				}

				if ( isset( $response['avsresponse'] ) ) {
					/* translators: %1$s: AVS response code, %2$s: AVS response description */
					$text = sprintf( __( '%1$s => %2$s', 'robust-nmi-payment-gateway' ), $response['avsresponse'], $this->getAVSresponse( $response['avsresponse'] ) );
					$order->update_meta_data( 'AVS Response', $text );
				}

				if ( isset( $response['cvvresponse'] ) ) {
					/* translators: %1$s: CVV response code, %2$s: CVV response description */
					$text = sprintf( __( '%1$s => %2$s', 'robust-nmi-payment-gateway' ), $response['cvvresponse'], $this->getCVVresponse( $response['cvvresponse'] ) );
					$order->update_meta_data( 'CVV Response', $text );
				}

				if ( isset( $response['response_code'] ) ) {
					/* translators: %1$s: Response code, %2$s: Response description */
					$text = sprintf( __( '%1$s => %2$s', 'robust-nmi-payment-gateway' ), $response['response_code'], $this->getCoderesponse( $response['response_code'] ) );
					$order->update_meta_data( 'NMI Response', $text );
				}

				$order->save();



				// Handle tokenization for both traditional and block checkout
				if ( isset( $response['customer_vault_id'] ) && !empty($response['customer_vault_id']) && is_user_logged_in() ) {
					if ($is_block_checkout) {
						// Check if this was a saved token or new card
						$is_saved_token = false;
						if ((isset($_POST['payment_method_data']['wc-nmipay-payment-token']) && 
							 $_POST['payment_method_data']['wc-nmipay-payment-token'] !== 'new' &&
							 is_numeric($_POST['payment_method_data']['wc-nmipay-payment-token'])) ||
							(isset($_POST['token']) && is_numeric($_POST['token']))) {
							$is_saved_token = true;
						}
						
						if ($is_saved_token) {
							// Using saved token - no need to save new token
							if ($this->debug == 'yes') {
								$this->log->add('robust_nmi', $order_id . ' - Block Checkout: Used saved token, no new tokenization needed');
							}
						} else {
							// New card tokenization - only save if user requested it
							$save_card = false;
							if (isset($_POST['payment_method_data']['wc-nmipay-new-payment-method']) && 
								$_POST['payment_method_data']['wc-nmipay-new-payment-method'] === true) {
								$save_card = true;
							}
							
							if ($save_card && count( $tokens ) == 0 ) {
					// Build the token
								$saved_token = new WC_Payment_Token_CC();
								$saved_token->set_token( $response['customer_vault_id'] ); // Token comes from payment processor
								$saved_token->set_gateway_id( 'nmipay' );
								$saved_token->set_last4( $last_four_digits );
								$saved_token->set_expiry_year( '20' . substr( $ccexp_expiry, 2, 7 ) );
								$saved_token->set_expiry_month( substr( $ccexp_expiry, 0, 2 ) );
								$saved_token->set_card_type( $cardtype );
								$saved_token->set_user_id( get_current_user_id() );
					// Save the new token to the database
								$saved_token->save();

								update_user_meta( get_current_user_id(), 'nmi_cc_token_id', $saved_token->get_id() );

					if ( $this->debug == 'yes' ) {
									$this->log->add( 'robust_nmi', $order_id . ' - Block Checkout: New Token Saved : ' . $saved_token->get_id() );
					}
							} elseif ($save_card && count( $tokens ) > 0 ) {
					$token_id = get_user_meta( get_current_user_id(), 'nmi_cc_token_id', true );
								$saved_token = WC_Payment_Tokens::get( $token_id );
								if ($saved_token) {
									$saved_token->set_token( $response['customer_vault_id'] ); // Token comes from payment processor
									$saved_token->set_gateway_id( 'nmipay' );
									$saved_token->set_last4( $last_four_digits );
									$saved_token->set_expiry_year( '20' . substr( $ccexp_expiry, 2, 7 ) );
									$saved_token->set_expiry_month( substr( $ccexp_expiry, 0, 2 ) );
									$saved_token->set_card_type( $cardtype );
									$saved_token->set_user_id( get_current_user_id() );
					// Save the new token to the database
									$saved_token->save();

									update_user_meta( get_current_user_id(), 'nmi_cc_token_id', $saved_token->get_id() );

					if ( $this->debug == 'yes' ) {
										$this->log->add( 'robust_nmi', $order_id . ' - Block Checkout: Token Updated : ' . $saved_token->get_id() );
									}
								}
							}
						}
						
					} else {
						// Traditional checkout tokenization
						// Check if this was a saved token or new card
						$is_saved_token = false;
						if (isset($_POST['wc-nmipay-payment-token']) && 
							$_POST['wc-nmipay-payment-token'] !== 'new' &&
							is_numeric($_POST['wc-nmipay-payment-token'])) {
							$is_saved_token = true;
						}
						
						if ($is_saved_token) {
							// Using saved token - no need to save new token
							if ($this->debug == 'yes') {
								$this->log->add('robust_nmi', $order_id . ' - Traditional Checkout: Used saved token, no new tokenization needed');
							}
						} else {
							// New card tokenization
							if ( ( isset( $_POST['wc-nmipay-new-payment-method'] ) || ( isset( $_POST['wc-nmipay-payment-token'] ) && $_POST['wc-nmipay-payment-token'] == 'new' ) )
								&& count( $tokens ) == 0 ) {
								// Build the token
								$saved_token = new WC_Payment_Token_CC();
								$saved_token->set_token( $response['customer_vault_id'] ); // Token comes from payment processor
								$saved_token->set_gateway_id( 'nmipay' );
								$saved_token->set_last4( $last_four_digits );
								$saved_token->set_expiry_year( '20' . substr( $ccexp_expiry, 2, 7 ) );
								$saved_token->set_expiry_month( substr( $ccexp_expiry, 0, 2 ) );
								$saved_token->set_card_type( $cardtype );
								$saved_token->set_user_id( get_current_user_id() );
								// Save the new token to the database
								$saved_token->save();

								update_user_meta( get_current_user_id(), 'nmi_cc_token_id', $saved_token->get_id() );

								if ( $this->debug == 'yes' ) {
									$this->log->add( 'robust_nmi', $order_id . ' - New Token Saved : ' . $saved_token->get_id() );
								}
							} elseif ( ( isset( $_POST['wc-nmipay-new-payment-method'] ) || ( isset( $_POST['wc-nmipay-payment-token'] ) && $_POST['wc-nmipay-payment-token'] == 'new' ) )
								&& count( $tokens ) > 0 ) {
								$token_id = get_user_meta( get_current_user_id(), 'nmi_cc_token_id', true );
								$saved_token = WC_Payment_Tokens::get( $token_id );
								$saved_token->set_token( $response['customer_vault_id'] ); // Token comes from payment processor
								$saved_token->set_gateway_id( 'nmipay' );
								$saved_token->set_last4( $last_four_digits );
								$saved_token->set_expiry_year( '20' . substr( $ccexp_expiry, 2, 7 ) );
								$saved_token->set_expiry_month( substr( $ccexp_expiry, 0, 2 ) );
								$saved_token->set_card_type( $cardtype );
								$saved_token->set_user_id( get_current_user_id() );
								// Save the new token to the database
								$saved_token->save();

								update_user_meta( get_current_user_id(), 'nmi_cc_token_id', $saved_token->get_id() );

								if ( $this->debug == 'yes' ) {
									$this->log->add( 'robust_nmi', $order_id . ' - Old Token Deleted : ' . $token_id . ' - New Token Saved : ' . $saved_token->get_id() );
								}
							}
						}
					}
				}

				if ( $this->debug == 'yes' ) {
					$this->log->add( 'robust_nmi', $order_id . ' - Redirecting User to order received page. : ' . $this->get_return_url( $order ) );
				}

				return array(
					'result'   => 'success',
					'redirect' => $this->get_return_url( $order ),
				);
			} else {
				if ( strpos( $response['responsetext'], 'Invalid Customer Vault Id' ) !== false ) {// Build the token
					$token_id = get_user_meta( get_current_user_id(), 'nmi_cc_token_id', true );
					if ( ! empty( $token_id ) ) {
						$token = new WC_Payment_Tokens();
						$token->delete( $token_id );
					}
					if ( $this->debug == 'yes' ) {
						$this->log->add( 'robust_nmi', $order_id . ' - Token Deleted : ' . $token_id . ' - because of error : ' . $response['responsetext'] );
					}

					return array(
						'result'   => 'success',
						'redirect' => $order->get_checkout_payment_url(),
					);
				} else {
					/* translators: %1$s: Response code, %2$s: Response text */
					$order->add_order_note( sprintf( __( 'Transaction Failed. %1$s-%2$s', 'robust-nmi-payment-gateway' ), $response['response_code'], $response['responsetext'] ) );
					/* translators: %1$s: Response code, %2$s: Response text */
					wc_add_notice( sprintf( __( 'Transaction Failed. %1$s-%2$s', 'robust-nmi-payment-gateway' ), $response['response_code'], $response['responsetext'] ), $notice_type = 'error' );
					if ( $this->debug == 'yes' ) {
						/* translators: %1$s: Response code, %2$s: Response text */
						$this->log->add( 'robust_nmi', $order_id . ' - ' . sprintf( __( 'Transaction Failed. %1$s-%2$s', 'robust-nmi-payment-gateway' ), $response['response_code'], $response['responsetext'] ) );
					}
				}
			}
		} else {
			/* translators: %s: Error response details */
			$order->add_order_note( sprintf( __( 'Gateway Error. Please Notify the Store Owner about this error. %s', 'robust-nmi-payment-gateway' ), print_r( $response, true ) ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug data in order note
			wc_add_notice( __( 'Gateway Error. Please Notify the Store Owner about this error.', 'robust-nmi-payment-gateway' ), $notice_type = 'error' );
			if ( $this->debug == 'yes' ) {
				/* translators: %s: Error response details */
				$error_message = __( 'Gateway Error. Please Notify the Store Owner about this error. %s', 'robust-nmi-payment-gateway' );
				// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug logging only when debug mode enabled
				$this->log->add( 'robust_nmi', $order_id . ' - ' . sprintf( $error_message, print_r( $response, true ) ) );
			}
		}
		// phpcs:enable WordPress.Security.NonceVerification.Missing


	


	}

	/**
	 * Set Billing and Shipping Address.
	 *
	 * @param int   $order_id
	 * @param array $nmipay_args
	 *
	 * @return array $nmipay_args
	 */
	public function set_billing_and_shipping_address( $nmipay_args, $order ) {
		$nmipay_args['firstname'] = $order->get_billing_first_name();
		$nmipay_args['lastname']  = $order->get_billing_last_name();
		$nmipay_args['company']   = $order->get_billing_company();
		$nmipay_args['address1']  = $order->get_billing_address_1();
		$nmipay_args['address2']  = $order->get_billing_address_2();
		$nmipay_args['city']      = $order->get_billing_city();
		$nmipay_args['state']     = $order->get_billing_state();
		$nmipay_args['zip']       = $order->get_billing_postcode();
		$nmipay_args['country']   = $order->get_billing_country();

		$ship_name = $order->get_shipping_first_name();

		if ( empty( $ship_name ) ) {
			$nmipay_args['shipping_firstname'] = $order->get_billing_first_name();
			$nmipay_args['shipping_lastname']  = $order->get_billing_last_name();
			$nmipay_args['shipping_company']   = $order->get_billing_company();
			$nmipay_args['shipping_address1']  = $order->get_billing_address_1();
			$nmipay_args['shipping_address2']  = $order->get_billing_address_2();
			$nmipay_args['shipping_city']      = $order->get_billing_city();
			$nmipay_args['shipping_state']     = $order->get_billing_state();
			$nmipay_args['shipping_zip']       = $order->get_billing_postcode();
			$nmipay_args['shipping_country']   = $order->get_billing_country();
		} else {
			$nmipay_args['shipping_firstname'] = $order->get_shipping_first_name();
			$nmipay_args['shipping_lastname']  = $order->get_shipping_last_name();
			$nmipay_args['shipping_company']   = $order->get_shipping_company();
			$nmipay_args['shipping_address1']  = $order->get_shipping_address_1();
			$nmipay_args['shipping_address2']  = $order->get_shipping_address_2();
			$nmipay_args['shipping_city']      = $order->get_shipping_city();
			$nmipay_args['shipping_state']     = $order->get_shipping_state();
			$nmipay_args['shipping_zip']       = $order->get_shipping_postcode();
			$nmipay_args['shipping_country']   = $order->get_shipping_country();
		}

		return $nmipay_args;
	}

	/**
	 * Process a refund if supported.
	 *
	 * @param int    $order_id
	 * @param float  $amount
	 * @param string $reason
	 *
	 * @return bool|wp_error True or false based on success, or a WP_Error object
	 */
	public function process_refund( $order_id, $amount = null, $reason = '' ) {
		 $order = wc_get_order( $order_id );

		if ( ! $order || ! $order->get_transaction_id() ) {
			return false;
		}

		$nmi_adr = $this->api_url . '/api/transact.php?';

		if ( ! is_null( $amount ) ) {
			$nmipay_args['type']          = 'refund';
			$nmipay_args['security_key']      = $this->security_key;
			$nmipay_args['transactionid'] = $order->get_transaction_id();
			$nmipay_args['amount']        = number_format( $amount, 2, '.', '' );
		}

		$name_value_pairs = array();
		foreach ( $nmipay_args as $key => $value ) {
			$name_value_pairs[] = $key . '=' . urlencode( $value );
		}
		$gateway_values = implode( '&', $name_value_pairs );

		$response = wp_remote_post(
			$nmi_adr,
			array(
				'body'      => $gateway_values,
				'sslverify' => false,
				'timeout'   => 60,
			)
		);

		if ( is_wp_error( $response ) ) {
			return $response;
		}

		if ( empty( $response['body'] ) ) {
			return new WP_Error( 'nmi-error', __( 'Empty NMI response.', 'robust-nmi-payment-gateway' ) );
		}

		parse_str( $response['body'], $response );

		if ( $response['response'] == '1' ) {
			/* translators: %1$s: Refund response text, %2$s: Refund transaction ID */
			$order->add_order_note( sprintf( __( 'Refund %1$s - Refund ID: %2$s', 'robust-nmi-payment-gateway' ), $response['responsetext'], $response['transactionid'] ) );

			return true;
		} elseif ( $response['response'] == '2' ) {
			$order->add_order_note( __( 'Transaction Declined', 'robust-nmi-payment-gateway' ) );

			return true;
		} elseif ( $response['response'] == '3' ) {
			$order->add_order_note( __( 'Error in transaction data or system error.', 'robust-nmi-payment-gateway' ) );

			return true;
		}

		return false;
	}




	/**
	 * Add payment method via account screen.
	 * We don't store the token locally, but to the NMI API.
	 *
	 * @since 3.0.0
	 */
	public function add_payment_method() {
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- WooCommerce handles nonce verification for payment method addition
		$token_data = isset( $_POST['nmipay_payment_token'] ) ? sanitize_text_field( wp_unslash( $_POST['nmipay_payment_token'] ) ) : '';
		$token = json_decode( stripslashes( $token_data ) );

		if( isset($token->token) ){
				
			$last_four_digits = substr( $token->card->number, -4 );
			$ccexp_expiry = $token->card->exp;

			$cardtype = $token->card->type;

			$nmi_adr = $this->api_url . '/api/transact.php?';

			$tokens = WC_Payment_Tokens::get_customer_tokens( get_current_user_id(), 'nmipay' );

			if ( count( $tokens ) == 0 ) {
				$nmipay_args['customer_vault'] = 'add_customer';

				$nmipay_args['payment_token']       = $token->token;
				
			} elseif ( count( $tokens ) > 0 ) {
				$token = WC_Payment_Tokens::get( get_user_meta( get_current_user_id(), 'nmi_cc_token_id', true ) );

				$nmipay_args['customer_vault']    = 'update_customer';
				$nmipay_args['customer_vault_id'] = $token->get_token();

				$nmipay_args['payment_token']       = $token->token;
			}

			$nmipay_args['security_key'] = $this->security_key;

			$name_value_pairs = array();
			foreach ( $nmipay_args as $key => $value ) {
				$name_value_pairs[] = $key . '=' . urlencode( $value );
			}
			$gateway_values = implode( '&', $name_value_pairs );

			$response = wp_remote_post(
				$nmi_adr,
				array(
					'body'      => $gateway_values,
					'sslverify' => false,
					'timeout'   => 60,
				)
			);

			if ( $this->debug == 'yes' ) {
				// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug logging only when debug mode enabled
				$this->log->add( 'robust_nmi', "Saving Card Response. - ".print_r($response['body'],true)  );
			}

			if ( ! is_wp_error( $response ) && $response['response']['code'] >= 200 && $response['response']['code'] < 300 ) {
				parse_str( $response['body'], $response );
				if ( $response['response'] == '1' ) {
					if ( count( $tokens ) == 0 ) {

						if ( $this->debug == 'yes' ) {
							$this->log->add( 'robust_nmi', "Trying to save card." );
						}
			
						// Build the token
						$token = new WC_Payment_Token_CC();
						$token->set_token( $response['customer_vault_id'] ); // Token comes from payment processor
						$token->set_gateway_id( 'nmipay' );
						$token->set_last4( $last_four_digits );
						$token->set_expiry_year( '20' . substr( $ccexp_expiry, 2, 7 ) );
						$token->set_expiry_month( substr( $ccexp_expiry, 0, 2 ) );
						$token->set_card_type( $cardtype );
						$token->set_user_id( get_current_user_id() );
						// Save the new token to the database
						$token->save();

						update_user_meta( get_current_user_id(), 'nmi_cc_token_id', $token->get_id() );
					} elseif ( count( $tokens ) > 0 ) {

						if ( $this->debug == 'yes' ) {
							$this->log->add( 'robust_nmi', "Trying to updated saved card." );
						}

						$token_id = get_user_meta( get_current_user_id(), 'nmi_cc_token_id', true );
						$token    = WC_Payment_Tokens::get( $token_id );
						$token->set_token( $response['customer_vault_id'] ); // Token comes from payment processor
						$token->set_gateway_id( 'nmipay' );
						$token->set_last4( $last_four_digits );
						$token->set_expiry_year( '20' . substr( $ccexp_expiry, 2, 7 ) );
						$token->set_expiry_month( substr( $ccexp_expiry, 0, 2 ) );
						$token->set_card_type( $cardtype );
						$token->set_user_id( get_current_user_id() );
						// Save the new token to the database
						$token->save();

						update_user_meta( get_current_user_id(), 'nmi_cc_token_id', $token->get_id() );
					}

					return array(
						'result'   => 'success',
						'redirect' => wc_get_endpoint_url( 'payment-methods' ),
					);
				} else {
					/* translators: %1$s: Response code, %2$s: Response text */
					wc_add_notice( sprintf( __( 'Transaction Failed. %1$s-%2$s', 'robust-nmi-payment-gateway' ), $response['response_code'], $response['responsetext'] ), $notice_type = 'error' );

					if ( $this->debug == 'yes' ) {
						/* translators: %1$s: Response code, %2$s: Response text */
						$this->log->add( 'robust_nmi', sprintf( __( 'Transaction Failed. %1$s-%2$s', 'robust-nmi-payment-gateway' ), $response['response_code'], $response['responsetext'] ) );
					}

					return;
				}
			} else {
				wc_add_notice( __( 'Please make sure you have entered the Credit Card details.', 'robust-nmi-payment-gateway' ), $notice_type = 'error' );

				if ( $this->debug == 'yes' ) {
					// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug logging only when debug mode enabled
					$this->log->add( 'robust_nmi', __( 'Please make sure you have entered the Credit Card details.', 'robust-nmi-payment-gateway' ) . ' ' . print_r( $response, true ) );
				}

				return;
			}
		}else {
			wc_add_notice( __( 'Failed to save the Card.', 'robust-nmi-payment-gateway' ), $notice_type = 'error' );

			if ( $this->debug == 'yes' ) {
				// phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.PHP.DevelopmentFunctions.error_log_print_r -- WooCommerce handles nonce verification, debug logging only when debug mode enabled
				$this->log->add( 'robust_nmi', __( 'Failed to save the Card.', 'robust-nmi-payment-gateway' ) . ' ' . print_r( $_REQUEST, true ) );
			}

			return;
		}

	}



	public function getAVSresponse( $code ) {
		$avsresponse = array(
			'X' => 'Exact match, 9-character numeric ZIP',
			'Y' => 'Exact match, 5-character numeric ZIP',
			'D' => 'Exact match, 5-character numeric ZIP',
			'M' => 'Exact match, 5-character numeric ZIP',
			'2' => 'Exact match, 5-character numeric ZIP, customer name',
			'6' => 'Exact match, 5-character numeric ZIP, customer name',
			'A' => 'Address match only',
			'B' => 'Address match only',
			'3' => 'Address, customer name match only',
			'7' => 'Address, customer name match only',
			'W' => '9-character numeric ZIP match only',
			'Z' => '5-character ZIP match only',
			'P' => '5-character ZIP match only',
			'L' => '5-character ZIP match only',
			'1' => '5-character ZIP, customer name match only',
			'5' => '5-character ZIP, customer name match only',
			'N' => 'No address or ZIP match only',
			'C' => 'No address or ZIP match only',
			'4' => 'No address or ZIP or customer name match only',
			'8' => 'No address or ZIP or customer name match only',
			'U' => 'Address unavailable',
			'G' => 'Non-U.S. issuer does not participate',
			'I' => 'Non-U.S. issuer does not participate',
			'R' => 'Issuer system unavailable',
			'E' => 'Not a mail/phone order',
			'S' => 'Service not supported',
			'0' => 'AVS not available',
			'O' => 'AVS not available',
			'B' => 'AVS not available',
		);

		return $avsresponse[ $code ];
	}

	public function getCVVresponse( $code ) {
		$cvvresponse = array(
			'M' => 'CVV2/CVC2 match',
			'N' => 'CVV2/CVC2 no match',
			'P' => 'Not processed',
			'S' => 'Merchant has indicated that CVV2/CVC2 is not present on card',
			'U' => 'Issuer is not certified and/or has not provided Visa encryption keys',
		);

		return $cvvresponse[ $code ];
	}

	public function getCoderesponse( $code ) {
		$response = array(
			'100' => 'Transaction was approved.',
			'200' => 'Transaction was declined by processor.',
			'201' => 'Do not honor.',
			'202' => 'Insufficient funds.',
			'203' => 'Over limit.',
			'204' => 'Transaction not allowed.',
			'220' => 'Incorrect payment information.',
			'221' => 'No such card issuer.',
			'222' => 'No card number on file with issuer.',
			'223' => 'Expired card.',
			'224' => 'Invalid expiration date.',
			'225' => 'Invalid card security code.',
			'226' => 'Invalid PIN.',
			'240' => 'Call issuer for further information.',
			'250' => 'Pick up card.',
			'251' => 'Lost card.',
			'252' => 'Stolen card.',
			'253' => 'Fraudulent card.',
			'260' => 'Declined with further instructions available. (See response text)',
			'261' => 'Declined-Stop all recurring payments.',
			'262' => 'Declined-Stop this recurring program.',
			'263' => 'Declined-Update cardholder data available.',
			'264' => 'Declined-Retry in a few days.',
			'300' => 'Transaction was rejected by gateway.',
			'400' => 'Transaction error returned by processor.',
			'410' => 'Invalid merchant configuration.',
			'411' => 'Merchant account is inactive.',
			'420' => 'Communication error.',
			'421' => 'Communication error with issuer.',
			'430' => 'Duplicate transaction at processor.',
			'440' => 'Processor format error.',
			'441' => 'Invalid transaction information.',
			'460' => 'Processor feature not available.',
			'461' => 'Unsupported card type.',
		);

		return $response[ $code ];
	}

	/**
	 * Handle block checkout data format conversion
	 */
	public function handle_block_checkout_data($result, $server, $request) {
		// Only process checkout requests for our payment method
		if ($request->get_route() !== '/wc/store/v1/checkout' || 
			$request->get_method() !== 'POST' ||
			$request->get_param('payment_method') !== 'nmipay') {
			return $result;
		}
		
		$payment_data = $request->get_param('payment_data');
		
		if ($this->debug == 'yes') {
			// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug logging only when debug mode enabled
			$this->log->add('robust_nmi', 'Block checkout data intercepted: ' . print_r($payment_data, true));
		}
		
		if (is_array($payment_data)) {
			$converted_data = array();
			foreach ($payment_data as $item) {
				if (isset($item['key']) && isset($item['value'])) {
					$converted_data[$item['key']] = $item['value'];
				}
			}
			
			// Set the converted data in $_POST for process_payment to access
			$_POST['payment_method_data'] = $converted_data;
			
			// Also set individual fields for backward compatibility
			foreach ($converted_data as $key => $value) {
				$_POST[$key] = $value;
			}
			
			if ($this->debug == 'yes') {
				// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Debug logging only when debug mode enabled
				$this->log->add('robust_nmi', 'Converted block checkout data: ' . print_r($converted_data, true));
			}
		}
		
		return $result;
	}
	

	

}

?>
