<?php
/**
 * Upsell Payment Gateway for Square
 *
 * @package FunnelKit_Square
 * @subpackage Payment
 */

namespace FKWCSQ\Includes\Modules\Payment\Upsell;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use FKWCSQ\Includes\Logger;
use FKWCSQ\Square;
use FKWCSQ\Includes\API;
use Square\Models\Money;
use Square\Models\CreatePaymentRequest;
use Square\Models\RefundPaymentRequest;
use Square\Exceptions\ApiException;
use WFOCU_Common;
use WC_Order;

/**
 * WFOCU_SQUARE_Gateway_Integration class.
 * Extends FunnelKit's WFOCU_Gateway for Square upsell support.
 */
class Card extends \WFOCU_Gateway {

	/**
	 * Singleton instance.
	 *
	 * @var self
	 */
	protected static $instance = null;

	/**
	 * Payment gateway key.
	 *
	 * @var string
	 */
	public $key = 'fkwcsq_square';

	/**
	 * Payment token.
	 *
	 * @var string|bool
	 */
	public $token = false;

	/**
	 * General plugin settings.
	 *
	 * @var array
	 */
	protected $general_settings;

	/**
	 * Whether logging is enabled.
	 *
	 * @var bool
	 */
	protected static $logging_enabled = false;

	/**
	 * API instance for Square integration.
	 *
	 * @var \FKWCSQ\Includes\API
	 */
	protected $api;

	/**
	 * Constructor.
	 *
	 * Initializes the gateway and sets up hooks.
	 */
	public function __construct() {
		parent::__construct();
		add_action( 'wfocu_footer_before_print_scripts', array( $this, 'maybe_render_in_offer_transaction_scripts' ), 999 );
		add_filter( 'wfocu_allow_ajax_actions_for_charge_setup', array( $this, 'allow_check_action' ) );
		$this->refund_supported = true;
		$this->api              = \FKWCSQ\Includes\API::get_instance();
		$this->general_settings = get_option( 'fkwcsq_settings', array() );
		self::$logging_enabled  = isset( $this->general_settings['enable_logging'] ) && $this->general_settings['enable_logging'] === 'yes';
	}
	/**
	 * Get singleton instance.
	 *
	 * @return self Instance of this class.
	 */
	public static function get_instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}

		return self::$instance;
	}

	/**
	 * Retrieve the Square payment token from the parent order.
	 */
	public function has_token( $order ) {
		$this->token = WFOCU_Common::get_order_meta( $order, '_square_payment_token' );

		return ! empty( $this->token );
	}

	/**
	 * Render JS for in-offer transaction processing.
	 * Integrates with FunnelKit's event system and Square's JS SDK.
	 */
	public function maybe_render_in_offer_transaction_scripts() {
		$order = WFOCU_Core()->data->get_current_order();
		if ( ! $order instanceof WC_Order || $this->get_key() !== $order->get_payment_method() ) {
			return;
		}
		$application_id = Square::get_application_id();
		$url            = \FKWCSQ\Square::get_web_sdk_url();
		$location_id    = $this->api->get_location_id();
		?>
		<?php wp_enqueue_script( 'square-js-sdk', esc_url( $url ), array(), FKWCSQ_VERSION, true ); ?>
		<script>
			(function ($) {
				"use strict";
				var squareUpsell = {
					bucket: null,
					payments: null,
					card: null,
					isInitialized: false,
					verificationInProgress: false,

					async initSquare() {
						if (this.isInitialized) return;
						this.payments = await Square.payments(<?php echo wp_json_encode( $application_id ); ?>, <?php echo wp_json_encode( $location_id ); ?>);
						this.card = await this.payments.card();
						this.isInitialized = true;
					},

					async processUpsell() {
						try {
							await this.initSquare();
							var postData = $.extend(this.bucket.getBucketSendData(), {
								action: 'wfocu_front_handle_fkwcsq_square_payments'
							});

							$.ajax({
								url: wfocu_vars.wc_ajax_url.toString().replace('%%endpoint%%', 'wfocu_front_handle_fkwcsq_square_payments'),
								type: 'POST',
								data: postData,
								dataType: 'text',
								success: async (textResponse) => {
									try {

										let data;

										if (textResponse.includes('<br/>') || textResponse.includes('<b>')) {

											const jsonStart = textResponse.indexOf('{');
											if (jsonStart >= 0) {
												data = JSON.parse(textResponse.substring(jsonStart));
											} else {
												throw new Error('No JSON found in response');
											}
										} else {

											data = JSON.parse(textResponse);
										}

										if (data && data.result === "success") {
											this.handleSuccess(data);
										} else if (data && data.result === "action_required") {
											try {
												if (this.verificationInProgress) {
													console.log('Verification already in progress');
													return;
												}
												this.verificationInProgress = true;

												// Handle 3DS verification
												const verificationResult = await this.payments.verifyBuyer(
													data.verification_details.sourceId,
													{
														amount: data.verification_details.amount,
														currencyCode: data.verification_details.currency,
														billingContact: {
															addressLines: [data.billingAddress.address_1, data.billingAddress.address_2],
															city: data.billingAddress.city,
															countryCode: data.billingAddress.country,
															postalCode: data.billingAddress.postcode
														},
														intent: 'CHARGE'
													}
												);

												var verificationData = $.extend(this.bucket.getBucketSendData(), {
													action: 'wfocu_front_handle_fkwcsq_square_payments',
													verification_token: verificationResult.token,
													sessionId: data.verification_details.paymentId
												});


												$.ajax({
													url: wfocu_vars.wc_ajax_url.toString().replace('%%endpoint%%', 'wfocu_front_handle_fkwcsq_square_payments'),
													type: 'POST',
													data: verificationData,
													dataType: 'text',
													success: (textResponse) => {
														try {
															console.log('Verification raw response:', textResponse);

															let response;
															if (textResponse.includes('<br/>') || textResponse.includes('<b>')) {
																console.log('Warning text detected in verification response');
																const jsonStart = textResponse.indexOf('{');
																if (jsonStart >= 0) {
																	response = JSON.parse(textResponse.substring(jsonStart));
																} else {
																	throw new Error('No JSON found in verification response');
																}
															} else {
																response = JSON.parse(textResponse);
															}

															console.log('Processed verification response:', response);

															if (response && response.result === "success") {
																this.handleSuccess(response);
															} else {
																this.handleError();
															}
														} catch (error) {
															console.error('Error processing verification response:', error);
															this.handleError();
														} finally {
															this.verificationInProgress = false;
														}
													},
													error: (jqXHR, textStatus, errorThrown) => {
														console.error('Verification AJAX request failed:', textStatus, errorThrown);
														this.handleError();
														this.verificationInProgress = false;
													}
												});

											} catch (verifyError) {
												console.error('3DS verification failed:', verifyError);
												this.handleError();
												this.verificationInProgress = false;
											}
										} else {
											console.error('Unexpected response format:', data);
											this.handleError();
										}
									} catch (error) {
										console.error('Error processing response:', error, textResponse);
										this.handleError();
									}
								},
								error: (jqXHR, textStatus, errorThrown) => {
									console.error('AJAX request failed:', textStatus, errorThrown);
									this.handleError();
								}
							});
						} catch (e) {
							console.error('Square payment error:', e);
							this.handleError();
						}
					},

					handleSuccess: function (data) {
						console.log('Payment successful');
						this.verificationInProgress = false;

						if (this.bucket) {
							this.bucket.inOfferTransaction = false;
						}

						this.bucket.swal.show({
							'text': wfocu_vars.messages.offer_success_message_pop,
							'type': 'success'
						});

						if (data.response && data.response.redirect_url) {
							setTimeout(function () {
								window.location = data.response.redirect_url;
							}, 1500);
						} else if (typeof wfocu_vars.order_received_url !== 'undefined') {
							setTimeout(function () {
								window.location = wfocu_vars.order_received_url +
									'&ec=square_success_but_no_redirect';
							}, 1500);
						}
					},

					handleError: function () {
						console.log('Payment failed');
						this.verificationInProgress = false;

						if (this.bucket) {
							this.bucket.inOfferTransaction = false;
						}

						this.bucket.swal.show({
							'text': wfocu_vars.messages.offer_msg_pop_failure,
							'type': 'warning'
						});

						if (typeof wfocu_vars.order_received_url !== 'undefined') {
							setTimeout(function () {
								window.location = wfocu_vars.order_received_url +
									'&ec=square_payment_failed';
							}, 1500);
						}
					}
				};

				$(document).on('wfocuBucketCreated', function (e, Bucket) {
					squareUpsell.bucket = Bucket;
				});
				$(document).on('wfocu_external', function (e, Bucket) {
					if (0 !== Bucket.getTotal()) {
						Bucket.inOfferTransaction = true;
						squareUpsell.processUpsell();
					}
				});

			})(jQuery);
		</script>
		<?php
	}

	/**
	 * Allow AJAX action for upsell payment.
	 */
	public function allow_check_action( $actions ) {
		$actions[] = 'wfocu_front_handle_fkwcsq_square_payments';

		return $actions;
	}

	/**
	 * AJAX handler for processing upsell payments.
	 */
	public static function process_client_payment() {
		check_ajax_referer( 'wfocu_front_charge', 'nonce' );

		try {
			if ( self::$logging_enabled ) {
				Logger::log( 'Processing Square upsell payment' );
			}
			$offer       = WFOCU_Core()->data->get( 'current_offer' );
			$offer_meta  = WFOCU_Core()->offers->get_offer_meta( $offer );
			$posted_data = WFOCU_Core()->process_offer->parse_posted_data( $_POST ); //phpcs:ignore WordPress.Security.NonceVerification.Missing, FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- Frontend payment processing, nonce handled by FunnelKit, guest users allowed
			if ( false === \WFOCU_AJAX_Controller::validate_charge_request( $posted_data ) ) {
				self::send_error_response( 'Invalid charge request' );

				return;
			}
			WFOCU_Core()->data->set( '_offer_result', true );
			WFOCU_Core()->process_offer->execute( $offer_meta );

			$upsell_package = WFOCU_Core()->data->get( '_upsell_package' );
			if ( ! is_array( $upsell_package ) || ! isset( $upsell_package['total'] ) ) {
				self::send_error_response( 'Could not resolve upsell package' );
				return;
			}
			$amount = (int) round( (float) $upsell_package['total'] * 100 );
			if ( $amount <= 0 ) {
				self::send_error_response( 'Invalid upsell amount' );
				return;
			}

			$parent_order = WFOCU_Core()->data->get_parent_order();
			$token        = $parent_order->get_meta( '_square_payment_token' );
			if ( empty( $token ) ) {
				self::send_error_response( 'Payment token not found' );

				return;
			}
			$customer_id = $parent_order->get_meta( '_square_customer_id' );
			Logger::log( 'process customer ID from user meta: ' . $customer_id );
			$api = \FKWCSQ\Includes\API::get_instance();
			if ( isset( $_POST['sessionId'] ) && isset( $_POST['verification_token'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Missing, FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- Frontend payment processing, nonce handled by FunnelKit, guest users allowed
				self::process_3ds_verification( $api, $token, $customer_id, $parent_order, $amount );

				return;
			}
			self::process_initial_payment( $api, $token, $customer_id, $parent_order, $amount );
		} catch ( \Exception | \Error $e ) {
			if ( self::$logging_enabled ) {
				Logger::error( 'Upsell payment error: ' . $e->getMessage() );
			}
			self::send_error_response( __( 'Payment processing failed. Please try again.', 'funnelkit-payment-gateway-square-for-woocommerce' ) );

			return;
		}
	}

	/**
	 * Process the 3DS verification after user completes the challenge
	 */
	private static function process_3ds_verification( $api, $token, $customer_id, $parent_order, $amount ) {
		if ( self::$logging_enabled ) {
			Logger::log( 'Processing post-3DS verification payment' );
		}

		$verification_token = isset( $_POST['verification_token'] ) ? sanitize_text_field( wp_unslash( $_POST['verification_token'] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing, FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- Frontend payment processing, nonce handled by FunnelKit, guest users allowed
		if ( empty( $verification_token ) ) {
			self::send_error_response( 'Verification token is required' );
			return;
		}

		try {
			$client = $api->get_client();
			if ( ! $client ) {
				self::send_error_response( 'Square client not initialized' );
				return;
			}

			// Check if token is a saved card token (starts with ccof:)
			$is_saved_card = ( strpos( $token, 'ccof:' ) === 0 );

			// For saved cards, customer_id is required
			if ( $is_saved_card && empty( $customer_id ) ) {
				// Try to find customer ID from user meta if it exists
				$user_id = $parent_order->get_customer_id();
				if ( $user_id ) {
					$customer_id = get_user_meta( $user_id, '_square_customer_id', true );
					if ( ! empty( $customer_id ) ) {
						if ( self::$logging_enabled ) {
							Logger::log( 'Found customer ID from user meta: ' . $customer_id );
						}
					} else {
						self::send_error_response( 'Customer ID is required for saved card payments' );
						return;
					}
				} else {
					self::send_error_response( 'Customer ID is required for saved card payments' );
					return;
				}
			}

			$money = new Money();
			$money->setAmount( $amount );
			$money->setCurrency( $parent_order->get_currency() );
			$body = new CreatePaymentRequest( $token, fkwcsq_idempotency_key( 'fkwcsq_upsell_vrf_' ), $money );
			$body->setAmountMoney( $money );
			$body->setAutocomplete( true );
			$body->setVerificationToken( $verification_token );
			$body->setNote( 'FunnelKit Upsell Payment (Post-3DS)' );
			// Set reference_id to prevent duplicate order creation via webhook
			$body->setReferenceId( 'up:' . $parent_order->get_id() );
			// Only set customer_id if it's not empty
			if ( ! empty( $customer_id ) ) {
				$body->setCustomerId( $customer_id );
			}

			// Handle application fee for Sublium subscriptions in upsells
			try {
				if (
					$api->is_application_fee_supported( $parent_order->get_currency() ) &&
					class_exists( '\Sublium_WCS\Includes\Helpers\AccessPermission' ) &&
					\Sublium_WCS\Includes\Helpers\AccessPermission::is_application_fee_applicable()
				) {
					$get_package = \WFOCU_Core()->data->get( '_upsell_package' );
					if ( ! empty( $get_package ) ) {
						$application_fee_amount = \Sublium_WCS\Includes\Helpers\AccessPermission::get_application_fee_by_order( $get_package );

						if ( $application_fee_amount > 0 ) {
							$app_fee_money = new Money();
							$app_fee_money->setAmount( (int) ( $application_fee_amount * 100 ) ); // Convert to cents
							$app_fee_money->setCurrency( $parent_order->get_currency() );
							$body->setAppFeeMoney( $app_fee_money );
							if ( self::$logging_enabled ) {
								Logger::log( 'Application fee added to upsell: ' . $application_fee_amount );
							}
						}
					}
				}
			} catch ( \Throwable $e ) {
				if ( self::$logging_enabled ) {
					Logger::log( 'Application fee calculation error: ' . $e->getMessage() );
				}
			}

			if ( self::$logging_enabled ) {
				Logger::log( sprintf(
					'Square upsell 3DS request | parent_order=%d | amount=%d %s | source_type=%s | has_customer=%s',
					$parent_order->get_id(),
					$amount,
					$parent_order->get_currency(),
					$is_saved_card ? 'saved_card' : 'card_nonce',
					! empty( $customer_id ) ? 'yes' : 'no'
				) );
			}

			$response = $client->getPaymentsApi()->createPayment( $body );

			if ( self::$logging_enabled ) {
				Logger::log( sprintf(
					'Square upsell 3DS response | status_code=%s | success=%s',
					method_exists( $response, 'getStatusCode' ) ? $response->getStatusCode() : 'n/a',
					( $response && $response->isSuccess() ) ? 'yes' : 'no'
				) );
			}

			// Check if the response is successful and has a valid result before accessing getPayment()
			if ( $response && $response->isSuccess() && $response->getResult() ) {
				$payment = $response->getResult()->getPayment();

				if ( $payment && $payment->getStatus() === 'COMPLETED' ) {
					WFOCU_Core()->data->set( '_transaction_id', $payment->getId() );
					$data = WFOCU_Core()->process_offer->_handle_upsell_charge( true );
					if ( self::$logging_enabled ) {
						Logger::log( sprintf(
							'Square upsell 3DS payment completed | parent_order=%d | square_payment_id=%s | status=%s | amount=%d %s',
							$parent_order->get_id(), $payment->getId(), $payment->getStatus(), $amount, $parent_order->get_currency()
						) );
					}
					wp_send_json(
						array(
							'result'   => 'success',
							'response' => $data,
						)
					);
					return;
				} elseif ( $payment ) {
					if ( self::$logging_enabled ) {
						Logger::error( 'Square upsell 3DS payment status not completed | parent_order=' . $parent_order->get_id() . ' | square_payment_id=' . $payment->getId() . ' | status=' . $payment->getStatus() );
					}
				}
			} else {
				// Handle error cases
				$errors = $response->getErrors();
				if ( ! empty( $errors ) ) {
					$error = $errors[0];
					if ( self::$logging_enabled ) {
						Logger::error( 'Square upsell 3DS payment errors | parent_order=' . $parent_order->get_id() . ' | errors=' . wp_json_encode( $errors ) );
					}
					self::send_error_response( __( 'Payment processing failed. Please try again.', 'funnelkit-payment-gateway-square-for-woocommerce' ) );
					return;
				}
			}

			WFOCU_Core()->process_offer->_handle_upsell_charge( false );
			self::send_error_response( 'Payment completion failed after 3DS verification' );
		} catch ( ApiException $e ) {
			if ( self::$logging_enabled ) {
				Logger::error( 'Exception in 3DS verification: ' . $e->getMessage() );
			}
			self::send_error_response( __( 'Payment processing failed. Please try again.', 'funnelkit-payment-gateway-square-for-woocommerce' ) );
		}
	}
	/**
	 * Process the initial payment attempt
	 */
	private static function process_initial_payment( $api, $token, $customer_id, $parent_order, $amount ) {
		$currency = $parent_order->get_currency();

		try {
			$client = $api->get_client();
			if ( ! $client ) {
				self::send_error_response( 'Square client not initialized' );
				return;
			}

			// Check if token is a saved card token (starts with ccof:)
			$is_saved_card = ( strpos( $token, 'ccof:' ) === 0 );

			// For saved cards, customer_id is required
			if ( $is_saved_card && empty( $customer_id ) ) {
				// Try to find customer ID from user meta if it exists
				$user_id = $parent_order->get_customer_id();
				if ( $user_id ) {
					$customer_id = get_user_meta( $user_id, '_square_customer_id', true );
					if ( ! empty( $customer_id ) ) {
						if ( self::$logging_enabled ) {
							Logger::log( 'Found customer ID from user meta: ' . $customer_id );
						}
					} else {
						self::send_error_response( 'Customer ID is required for saved card payments' );
						return;
					}
				} else {
					self::send_error_response( 'Customer ID is required for saved card payments' );
					return;
				}
			}

			$money = new Money();
			$money->setAmount( $amount );
			$money->setCurrency( $currency );
			$body = new CreatePaymentRequest( $token, fkwcsq_idempotency_key( 'fkwcsq_upsell_' ), $money );
			$body->setAmountMoney( $money );
			$body->setAutocomplete( true );
			$body->setNote( 'FunnelKit Upsell Payment' );
			// Set reference_id to prevent duplicate order creation via webhook
			$body->setReferenceId( 'up:' . $parent_order->get_id() );

			// Only set customer_id if it's not empty
			if ( ! empty( $customer_id ) ) {
				$body->setCustomerId( $customer_id );
			}

			// Handle application fee for Sublium subscriptions in upsells
			try {
				if (
					$api->is_application_fee_supported( $currency ) &&
					class_exists( '\Sublium_WCS\Includes\Helpers\AccessPermission' ) &&
					\Sublium_WCS\Includes\Helpers\AccessPermission::is_application_fee_applicable()
				) {
					$get_package = \WFOCU_Core()->data->get( '_upsell_package' );
					if ( ! empty( $get_package ) ) {
						$application_fee_amount = \Sublium_WCS\Includes\Helpers\AccessPermission::get_application_fee_by_order( $get_package );

						if ( $application_fee_amount > 0 ) {
							$app_fee_money = new Money();
							$app_fee_money->setAmount( (int) ( $application_fee_amount * 100 ) ); // Convert to cents
							$app_fee_money->setCurrency( $currency );
							$body->setAppFeeMoney( $app_fee_money );
							if ( self::$logging_enabled ) {
								Logger::log( 'Application fee added to upsell: ' . $application_fee_amount );
							}
						}
					}
				}
			} catch ( \Throwable $e ) {
				if ( self::$logging_enabled ) {
					Logger::log( 'Application fee calculation error: ' . $e->getMessage() );
				}
			}

			if ( self::$logging_enabled ) {
				Logger::log( sprintf(
					'Square upsell payment request | parent_order=%d | amount=%d %s | source_type=%s | has_customer=%s',
					$parent_order->get_id(),
					$amount,
					$currency,
					$is_saved_card ? 'saved_card' : 'card_nonce',
					! empty( $customer_id ) ? 'yes' : 'no'
				) );
			}

			$response = $client->getPaymentsApi()->createPayment( $body );

			if ( self::$logging_enabled ) {
				Logger::log( sprintf(
					'Square upsell payment response | status_code=%s | success=%s',
					method_exists( $response, 'getStatusCode' ) ? $response->getStatusCode() : 'n/a',
					( $response && $response->isSuccess() ) ? 'yes' : 'no'
				) );
			}

			// Check if the response is successful and has a valid result before accessing getPayment()
			if ( $response && $response->isSuccess() && $response->getResult() ) {
				$payment = $response->getResult()->getPayment();

				if ( $payment && $payment->getStatus() === 'COMPLETED' ) {
					WFOCU_Core()->data->set( '_transaction_id', $payment->getId() );
					$data = WFOCU_Core()->process_offer->_handle_upsell_charge( true );
					if ( self::$logging_enabled ) {
						Logger::log( sprintf(
							'Square upsell payment completed | parent_order=%d | square_payment_id=%s | status=%s | amount=%d %s',
							$parent_order->get_id(), $payment->getId(), $payment->getStatus(), $amount, $currency
						) );
					}
					wp_send_json(
						array(
							'result'   => 'success',
							'response' => $data,
						)
					);
					return;
				}
			} else {
				// Handle error cases
				$errors = $response->getErrors();
				if ( ! empty( $errors ) ) {
					$error = $errors[0];

					if ( self::$logging_enabled ) {
						Logger::error( 'Square upsell payment errors | parent_order=' . $parent_order->get_id() );
					}

					// Handle 3DS verification requirement
					if ( $error->getCode() === 'CARD_DECLINED_VERIFICATION_REQUIRED' ) {
						// We need a payment ID for verification, but the payment failed
						// Use a temporary ID that will be replaced in the verification step
						$temp_payment_id = 'pending_verification_' . uniqid();

						$billing_address = array(
							'address_1' => $parent_order->get_billing_address_1(),
							'address_2' => $parent_order->get_billing_address_2(),
							'city'      => $parent_order->get_billing_city(),
							'country'   => $parent_order->get_billing_country(),
							'postcode'  => $parent_order->get_billing_postcode(),
						);

						wp_send_json(
							array(
								'result'               => 'action_required',
								'verification_details' => array(
									'sourceId'  => $token,
									'paymentId' => $temp_payment_id,
									'amount'    => (string) ( $amount / 100 ),
									'currency'  => $currency,
								),
								'billingAddress'       => $billing_address,
							)
						);
						return;
					}

					self::send_error_response( __( 'Payment processing failed. Please try again.', 'funnelkit-payment-gateway-square-for-woocommerce' ) );
					return;
				}
			}

			self::send_error_response( __( 'Payment processing failed. Please try again.', 'funnelkit-payment-gateway-square-for-woocommerce' ) );
		} catch ( ApiException $e ) {
			if ( self::$logging_enabled ) {
				Logger::error( 'Exception in initial payment: ' . $e->getMessage() );
			}
			self::send_error_response( __( 'Payment processing failed. Please try again.', 'funnelkit-payment-gateway-square-for-woocommerce' ) );
		}
	}
	/**
	 * Helper function to send error responses
	 */
	private static function send_error_response( $message ) {
		if ( self::$logging_enabled ) {
			Logger::error( 'Payment error: ' . $message );
		}
		wp_send_json(
			array(
				'result'  => 'error',
				'message' => $message,
			)
		);
	}

	/**
	 * Refund support for upsell transactions.
	 *
	 * @param WC_Order $order The order object.
	 *
	 * @return string|bool Refund ID on success, false on failure.
	 * @throws \Exception When payment ID is missing or refund fails.
	 */
	public function process_refund_offer( $order ) {
		try {
			if ( self::$logging_enabled ) {
				Logger::log( 'Processing Square upsell refund' );
			}

			// Validate POST data
			$refund_data = wc_clean( $_POST ); //phpcs:ignore WordPress.Security.NonceVerification.Missing,FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- Frontend payment processing, nonce handled by FunnelKit, guest users allowed
			if ( ! isset( $refund_data['amt'] ) || ! isset( $refund_data['txn_id'] ) ) {
				if ( self::$logging_enabled ) {
					Logger::error( 'Missing required refund data' );
				}
				return false;
			}

			$refund_amount = (float) $refund_data['amt'];
			$refund_reason = isset( $refund_data['refund_reason'] ) ? $refund_data['refund_reason'] : '';
			$payment_id    = $refund_data['txn_id'];

			if ( empty( $payment_id ) ) {
				if ( self::$logging_enabled ) {
					Logger::error( 'Missing payment ID for refund' );
				}
				throw new \Exception( 'Payment ID is required for refund' );
			}

			if ( ! is_numeric( $refund_data['amt'] ) || $refund_amount <= 0 ) {
				if ( self::$logging_enabled ) {
					Logger::error( 'Invalid refund amount: ' . $refund_data['amt'] );
				}
				return false;
			}

			$api    = API::get_instance();
			$client = $api->get_client();
			if ( ! $client ) {
				if ( self::$logging_enabled ) {
					Logger::error( 'Square client not initialized' );
				}
				return false;
			}

			// Format amount for Square (in cents) using round() to avoid float precision errors.
			$amount_in_cents = (int) round( $refund_amount * 100 );

			// Generate cryptographically random idempotency key.
			$idempotency_key = fkwcsq_idempotency_key( 'fkwcsq_upsell_refund_' );

			if ( self::$logging_enabled ) {
				Logger::log(
					'Creating refund for payment: ' . $payment_id .
							', Amount: ' . $refund_amount . ' (' . $amount_in_cents . ' cents)' .
					', Currency: ' . $order->get_currency()
				);
			}

			// Create money object
			$money = new Money();
			$money->setAmount( $amount_in_cents );
			$money->setCurrency( $order->get_currency() );

			$body = new RefundPaymentRequest( $idempotency_key, $money );
			$body->setPaymentId( $payment_id );

			if ( ! empty( $refund_reason ) ) {
				$body->setReason( $refund_reason );
			} else {
				$body->setReason( 'Merchant initiated' );
			}

			if ( self::$logging_enabled ) {
				Logger::log( sprintf(
					'Square upsell refund request | order=%d | square_payment_id=%s | amount=%d %s | body=%s',
					$order->get_id(), $payment_id, $amount_in_cents, $order->get_currency(), wp_json_encode( $body )
				) );
			}

			// Execute the refund
			$response = $client->getRefundsApi()->refundPayment( $body );

			if ( self::$logging_enabled ) {
				Logger::log( sprintf(
					'Square upsell refund response | status_code=%s | success=%s | result=%s | errors=%s',
					method_exists( $response, 'getStatusCode' ) ? $response->getStatusCode() : 'n/a',
					( $response && $response->isSuccess() ) ? 'yes' : 'no',
					( $response && $response->getResult() ) ? wp_json_encode( $response->getResult() ) : 'null',
					( $response && $response->getErrors() ) ? wp_json_encode( $response->getErrors() ) : 'null'
				) );
			}

			// Check if response is valid
			if ( $response && $response->isSuccess() && $response->getResult() ) {
				$result = $response->getResult();

				if ( $result->getRefund() ) {
					$refund = $result->getRefund();

					if ( self::$logging_enabled ) {
						Logger::log( sprintf(
							'Square upsell refund successful | order=%d | refund_id=%s | square_payment_id=%s | amount=%d %s',
							$order->get_id(), $refund->getId(), $payment_id, $amount_in_cents, $order->get_currency()
						) );
					}

					return $refund->getId();
				}
			}

			// Handle error response
			if ( $response && $response->getErrors() ) {
				$errors = $response->getErrors();
				if ( ! empty( $errors ) && self::$logging_enabled ) {
					Logger::error( 'Square upsell refund errors | order=' . $order->get_id() . ' | errors=' . wp_json_encode( $errors ) );
				}
			} elseif ( self::$logging_enabled ) {
				Logger::error( 'Square upsell refund failed | order=' . $order->get_id() . ' | reason=Invalid response' );
			}

			return false;

		} catch ( ApiException $e ) {
			if ( self::$logging_enabled ) {
				Logger::error( 'Square API exception in refund processing: ' . $e->getMessage() );
			}
			return false;
		} catch ( \Exception $e ) {
			if ( self::$logging_enabled ) {
				Logger::error( 'General exception in refund processing: ' . $e->getMessage() );
			}
			return false;
		}
	}
}
