<?php
/**
 * ConvesioPay hooks.
 *
 * @package PeachPay
 */

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

// ConvesioPay-specific hooks can be added here
// Gateway registration is handled by the PeachPay_Payment_Integration trait 

// Transaction creation now handled by centralized PeachPay endpoint

// Required PeachPay standard hooks
add_filter( 'peachpay_register_feature', 'peachpay_convesiopay_register_feature' );
add_action( 'peachpay_settings_admin_action', 'peachpay_convesiopay_handle_admin_actions', 10, 1 );

/**
 * Renders ConvesioPay logo in the order number column when payment method is ConvesioPay.
 * Respects the "Show ConvesioPay logo in order list" setting (default: visible).
 *
 * @param WC_Order|false $order Order object (legacy hook passes post ID; caller resolves via wc_get_order).
 */
function peachpay_render_convesiopay_logo( $order ) {
	if ( ! $order instanceof WC_Order ) {
		return;
	}

	if ( get_option( 'peachpay_convesiopay_show_order_list_logo', 'yes' ) === 'no' ) {
		return;
	}

	if ( ! PeachPay_ConvesioPay_Integration::is_payment_gateway( $order->get_payment_method() ) ) {
		return;
	}

	$logo_url = PeachPay::get_asset_url( 'img/marks/convesiopay/convesiopay.svg' );

	printf(
		'<span class="pp-order-id-logo" style="display:inline-flex;align-items:center;vertical-align:middle;margin-right:4px;">
			<img src="%s" alt="ConvesioPay" style="width:48px;height:auto;" />
		</span>',
		esc_url( $logo_url )
	);
}

// Order list: show ConvesioPay logo next to order number (HPOS + legacy). Only register in admin.
if ( is_admin() ) {
	add_action( 'manage_woocommerce_page_wc-orders_custom_column', function ( $column, $order ) {
		if ( 'order_number' === $column ) {
			peachpay_render_convesiopay_logo( $order );
		}
	}, 10, 2 );

	add_action( 'manage_shop_order_posts_custom_column', function ( $column, $post_id ) {
		if ( 'order_number' === $column ) {
			peachpay_render_convesiopay_logo( wc_get_order( $post_id ) );
		}
	}, 10, 2 );
}

// Force cart recalculation after Store API requests to pick up session changes
add_action( 'woocommerce_store_api_cart_select_payment_method', 'peachpay_convesiopay_force_fee_recalculation' );
add_action( 'rest_api_init', 'peachpay_convesiopay_register_store_api_hooks' );

// Sync unified gateway position with Card gateway position on checkout
// The unified gateway is hidden from admin, so we position it where the Card gateway is set
// This ensures the checkout order matches what users set in WooCommerce > Settings > Payments
add_filter( 'woocommerce_available_payment_gateways', 'peachpay_convesiopay_position_unified_gateway', 100 );
// Preserve mounted ConvesioPay secured fields during classic checkout updates.
// When unified is selected, skip replacing .woocommerce-checkout-payment fragment.
add_filter( 'woocommerce_update_order_review_fragments', 'peachpay_convesiopay_preserve_unified_payment_fragment', 20 );

// Store credit / wallet gateways: PeachPay must not remove or hide them. We restore any known store-credit
// gateway when it is registered and enabled but missing from the available list (e.g. filtered out earlier).
// When and how the gateway appears (full vs partial balance, cart deductions, etc.) is determined by the
// wallet plugin; we only ensure it is not dropped and is visible when the wallet plugin has it enabled.
add_filter( 'woocommerce_available_payment_gateways', 'peachpay_ensure_store_credit_gateways_available', 999 );

// Ensure wallet/store-credit gateways are registered in WooCommerce when PeachPay is active.
// 1) Late filter on woocommerce_payment_gateways so the wallet is in the list when WC builds it
//    (covers admin Settings > Payments and any early build).
// 2) ensure_store_credit calls peachpay_ensure_wallet_gateway_registered() so wallet is injected
//    if the list was already built without it (covers checkout when gateways exist).
// 3) Before the Payments table is rendered, inject the wallet so it appears in the gateways list.
// 4) Before the checkout tab output or save runs, inject the wallet so section=wallet (gateway settings) works.
add_filter( 'woocommerce_payment_gateways', 'peachpay_add_wallet_to_payment_gateways_list', 999 );
add_action( 'woocommerce_init', 'peachpay_ensure_wallet_gateway_registered', 999 );
add_action( 'woocommerce_admin_field_payment_gateways', 'peachpay_ensure_wallet_gateway_registered', 1 );
add_action( 'woocommerce_settings_checkout', 'peachpay_ensure_wallet_in_gateways_before_checkout_output', 1 );
add_action( 'woocommerce_settings_save_checkout', 'peachpay_ensure_wallet_in_gateways_before_checkout_output', 1 );

/**
 * Position the unified gateway where the Card gateway would be.
 * Since the unified gateway is hidden from WooCommerce Payments admin,
 * we use the Card gateway's position to determine where unified should appear on checkout.
 *
 * This filter only reorders gateways; it must never remove or hide other gateways
 * (e.g. Terra Wallet / store credit), so they remain visible when PeachPay is active.
 *
 * @param array $available_gateways Available payment gateways.
 * @return array Reordered gateways.
 */
function peachpay_convesiopay_position_unified_gateway( $available_gateways ) {
	if ( empty( $available_gateways ) || ! is_array( $available_gateways ) ) {
		return $available_gateways;
	}

	// Check if unified gateway is present
	if ( ! isset( $available_gateways['peachpay_convesiopay_unified'] ) ) {
		return $available_gateways;
	}

	// Get the saved gateway order
	$gateway_order = get_option( 'woocommerce_gateway_order', array() );

	// Find the Card gateway's position (this is what users can drag in admin)
	if ( ! isset( $gateway_order['peachpay_convesiopay_card'] ) ) {
		// If Card gateway has no saved position, leave unified where WooCommerce put it
		return $available_gateways;
	}

	$card_position = (int) $gateway_order['peachpay_convesiopay_card'];

	// Remove unified gateway from its current position
	$unified_gateway = $available_gateways['peachpay_convesiopay_unified'];
	unset( $available_gateways['peachpay_convesiopay_unified'] );

	// Rebuild the array with unified at the Card gateway's position. Preserve every other gateway.
	$result = array();
	$unified_inserted = false;

	foreach ( $available_gateways as $gateway_id => $gateway ) {
		// Get this gateway's saved position
		$this_position = isset( $gateway_order[ $gateway_id ] ) ? (int) $gateway_order[ $gateway_id ] : 999;

		// Insert unified gateway when we reach or pass the card's position
		if ( ! $unified_inserted && $this_position >= $card_position ) {
			$result['peachpay_convesiopay_unified'] = $unified_gateway;
			$unified_inserted = true;
		}

		$result[ $gateway_id ] = $gateway;
	}

	// If unified wasn't inserted yet (card position is at the end), add it now
	if ( ! $unified_inserted ) {
		$result['peachpay_convesiopay_unified'] = $unified_gateway;
	}

	// Ensure no gateway was dropped (defensive).
	foreach ( array_keys( $available_gateways ) as $gateway_id ) {
		if ( ! isset( $result[ $gateway_id ] ) ) {
			$result[ $gateway_id ] = $available_gateways[ $gateway_id ];
		}
	}

	return $result;
}

/**
 * Extract the place-order row from Woo payment fragment HTML.
 *
 * @param string $payment_fragment_html Full .woocommerce-checkout-payment fragment HTML.
 * @return string Place-order row HTML or empty string when extraction fails.
 */
function peachpay_convesiopay_extract_place_order_fragment( $payment_fragment_html ) {
	if ( empty( $payment_fragment_html ) || ! is_string( $payment_fragment_html ) ) {
		return '';
	}

	if ( ! class_exists( 'DOMDocument' ) ) {
		return '';
	}

	$previous_libxml_setting = libxml_use_internal_errors( true );
	$document                = new DOMDocument();

	$wrapped_html = '<!DOCTYPE html><html><body><div id="peachpay-payment-fragment-root">' . $payment_fragment_html . '</div></body></html>';
	$loaded       = $document->loadHTML( $wrapped_html );

	if ( ! $loaded ) {
		libxml_clear_errors();
		libxml_use_internal_errors( $previous_libxml_setting );
		return '';
	}

	$xpath = new DOMXPath( $document );
	$nodes = $xpath->query( "//div[contains(concat(' ', normalize-space(@class), ' '), ' form-row ') and contains(concat(' ', normalize-space(@class), ' '), ' place-order ')]" );

	libxml_clear_errors();
	libxml_use_internal_errors( $previous_libxml_setting );

	if ( ! $nodes || 0 === $nodes->length ) {
		return '';
	}

	$place_order_node = $nodes->item(0);
	if ( ! $place_order_node ) {
		return '';
	}

	return trim( $document->saveHTML( $place_order_node ) );
}

/**
 * Preserve checkout payment fragment when ConvesioPay unified is present.
 *
 * Why:
 * Replacing .woocommerce-checkout-payment destroys mounted secured-field iframes
 * (card number/expiry/cvc) and clears user input. Preserving this fragment keeps
 * the mounted ConvesioPay DOM stable even when customers temporarily choose
 * another gateway (e.g. COD) and then return.
 *
 * @param array $fragments WooCommerce checkout fragments.
 * @return array
 */
function peachpay_convesiopay_preserve_unified_payment_fragment( $fragments ) {
	if ( empty( $fragments ) || ! is_array( $fragments ) ) {
		return $fragments;
	}

	$payment_fragment_html = isset( $fragments['.woocommerce-checkout-payment'] ) && is_string( $fragments['.woocommerce-checkout-payment'] )
		? $fragments['.woocommerce-checkout-payment']
		: '';

	// Only preserve when unified gateway exists in the current payment fragment.
	// This avoids touching checkouts that do not include ConvesioPay.
	if ( false === strpos( $payment_fragment_html, 'payment_method_peachpay_convesiopay_unified' ) ) {
		return $fragments;
	}

	$selected_gateway = '';
	if ( isset( $_POST['payment_method'] ) ) {
		$selected_gateway = sanitize_text_field( wp_unslash( $_POST['payment_method'] ) );
	} elseif ( isset( $_POST['post_data'] ) && is_string( $_POST['post_data'] ) ) {
		$post_data = array();
		parse_str( wp_unslash( $_POST['post_data'] ), $post_data );
		if ( isset( $post_data['payment_method'] ) ) {
			$selected_gateway = sanitize_text_field( $post_data['payment_method'] );
		}
	}
	if ( empty( $selected_gateway ) && function_exists( 'WC' ) && WC()->session ) {
		$selected_gateway = (string) WC()->session->get( 'chosen_payment_method' );
	}

	if ( 'peachpay_convesiopay_unified' !== $selected_gateway ) {
		return $fragments;
	}

	$place_order_fragment = peachpay_convesiopay_extract_place_order_fragment( $payment_fragment_html );

	// If extraction fails, keep Woo default full-fragment replacement for correctness.
	if ( empty( $place_order_fragment ) ) {
		return $fragments;
	}

	// Preserve mounted payment-method list (secured card iframes), but keep place-order
	// area fresh so terms/tokens/conditional checkout fields are updated each refresh.
	$fragments['.woocommerce-checkout-payment .form-row.place-order'] = $place_order_fragment;
	if ( isset( $fragments['.woocommerce-checkout-payment'] ) ) {
		unset( $fragments['.woocommerce-checkout-payment'] );
	}

	return $fragments;
}

/**
 * Restore store-credit / wallet gateways when they are registered and enabled but missing from available.
 *
 * PeachPay must not remove or hide wallet/store-credit gateways. If a known store-credit gateway is in
 * WC's registered list and enabled but missing from the available list (e.g. filtered out earlier), we add
 * it back. When and how the gateway appears (balance rules, partial payment, cart deductions, etc.) is
 * determined by the wallet plugin; we only ensure it is not dropped.
 *
 * Known gateway ids: "wallet" (TeraWallet / Woo-Wallet). Others can be added via filter
 * peachpay_store_credit_gateway_ids. If the gateway never appears in the registered list when PeachPay
 * is active, use the wallet registration hooks (peachpay_add_wallet_to_payment_gateways_list, etc.).
 *
 * @param array $available_gateways Available payment gateways (after other filters).
 * @return array Gateways with store-credit gateways restored when appropriate.
 */
function peachpay_ensure_store_credit_gateways_available( $available_gateways ) {

	if ( ! is_array( $available_gateways ) ) {
		return $available_gateways;
	}

	$is_checkout = is_checkout();
	$is_endpoint = is_wc_endpoint_url();
	$is_add_pm  = is_add_payment_method_page();

	if ( ! $is_checkout || $is_endpoint || $is_add_pm ) {
		return $available_gateways;
	}
	if ( ! function_exists( 'WC' ) || ! WC()->payment_gateways ) {
		return $available_gateways;
	}

	// Register wallet gateway into WC if the wallet plugin is active but was never added (e.g. built too early).
	// Do this while we know WC()->payment_gateways exists (inside this filter), then re-read the full list.
	peachpay_ensure_wallet_gateway_registered();

	// Known store-credit / wallet gateway IDs. TeraWallet = "wallet". Others can be added via filter.
	$store_credit_gateway_ids = array( 'wallet' );
	$store_credit_gateway_ids = apply_filters( 'peachpay_store_credit_gateway_ids', $store_credit_gateway_ids );

	$all_gateways = WC()->payment_gateways->payment_gateways();

	if ( empty( $all_gateways ) || ! is_array( $all_gateways ) ) {
		return $available_gateways;
	}

	foreach ( $store_credit_gateway_ids as $gateway_id ) {
		$in_available = isset( $available_gateways[ $gateway_id ] );
		$in_all       = isset( $all_gateways[ $gateway_id ] ) && is_object( $all_gateways[ $gateway_id ] );

		if ( $in_available ) {
			continue;
		}
		if ( ! $in_all ) {
			continue;
		}
		$gateway = $all_gateways[ $gateway_id ];
		if ( ! $gateway instanceof WC_Payment_Gateway ) {
			continue;
		}
		$enabled = $gateway->get_option( 'enabled', 'no' );
		if ( 'yes' !== $enabled ) {
			continue;
		}
		// Re-include when enabled and missing. Do not call is_available() here, because some wallet
		// gateways return false when PeachPay (or similar) is active; we want them visible anyway.
		// The gateway still enforces balance/validation in process_payment or form validation.
		$available_gateways[ $gateway_id ] = $gateway;
	}

	return $available_gateways;
}

/**
 * Adds wallet gateway to the gateways list when WC builds it (woocommerce_payment_gateways filter).
 * Runs at priority 999 so we run after the wallet plugin's own filter; if the wallet was never
 * added (e.g. wallet loads after this filter ran, or init order), we add it here.
 * This fixes the wallet missing in WooCommerce > Settings > Payments and at checkout.
 *
 * @param array $load_gateways Array of gateway class names or objects.
 * @return array Same array with wallet gateway added if the plugin is active and not already present.
 */
function peachpay_add_wallet_to_payment_gateways_list( $load_gateways ) {
	if ( ! is_array( $load_gateways ) ) {
		return $load_gateways;
	}
	$wallet_class = 'Woo_Gateway_Wallet_payment';
	foreach ( $load_gateways as $g ) {
		if ( $g === $wallet_class || ( is_object( $g ) && is_a( $g, $wallet_class ) ) ) {
			return $load_gateways;
		}
	}
	if ( class_exists( $wallet_class ) ) {
		$load_gateways[] = $wallet_class;
	}
	return $load_gateways;
}

/**
 * Ensures the wallet gateway is in WC's registry before the checkout settings tab output runs.
 * Runs on woocommerce_settings_checkout priority 1 so that when section=wallet, output() finds
 * the wallet in the gateways list and can run admin_options for it (same as other gateways).
 */
function peachpay_ensure_wallet_in_gateways_before_checkout_output() {
	if ( ! function_exists( 'WC' ) ) {
		return;
	}
	WC()->payment_gateways;
	peachpay_ensure_wallet_gateway_registered();
}

/**
 * Registers wallet/store-credit gateways into WC's registry when the gateway list was already
 * built without them (e.g. first use was get_available_payment_gateways on checkout).
 * Called from ensure_store_credit when we know WC()->payment_gateways exists.
 *
 * Supported: Woo-Wallet / TeraWallet (class Woo_Gateway_Wallet_payment, id "wallet").
 * Others can be added via the peachpay_wallet_gateways_to_register filter.
 */
function peachpay_ensure_wallet_gateway_registered() {
	if ( ! function_exists( 'WC' ) || ! WC()->payment_gateways ) {
		return;
	}

	$wallet_gateways = array(
		array(
			'class' => 'Woo_Gateway_Wallet_payment',
			'id'    => 'wallet',
		),
	);
	$wallet_gateways = apply_filters( 'peachpay_wallet_gateways_to_register', $wallet_gateways );

	$registered = WC()->payment_gateways->payment_gateways();
	$wg         = WC()->payment_gateways;

	foreach ( $wallet_gateways as $def ) {
		if ( empty( $def['class'] ) || empty( $def['id'] ) ) {
			continue;
		}
		if ( isset( $registered[ $def['id'] ] ) && is_object( $registered[ $def['id'] ] ) ) {
			continue;
		}
		if ( ! class_exists( $def['class'] ) ) {
			continue;
		}
		$gateway = new $def['class']();
		if ( ! $gateway instanceof WC_Payment_Gateway ) {
			continue;
		}
		$keys = array_keys( $wg->payment_gateways );
		$pos  = empty( $keys ) ? 999 : ( (int) max( $keys ) + 1 );
		$wg->payment_gateways[ $pos ] = $gateway;
	}
}

/**
 * Register hooks for Store API to ensure proper fee calculation.
 */
function peachpay_convesiopay_register_store_api_hooks() {
	// Hook early in cart calculation to ensure session-based method is used
	add_filter( 'woocommerce_cart_calculate_fees', 'peachpay_convesiopay_ensure_method_in_cart_calculation', 5 );
}

/**
 * Ensure the ConvesioPay method is properly read during cart calculation.
 * This hook ensures the session method is available before fee calculation.
 *
 * @param WC_Cart $cart Cart object.
 */
function peachpay_convesiopay_ensure_method_in_cart_calculation( $cart ) {
	// This runs before fees are calculated - the actual logic is in the gateway.
	// The session method is read by the unified gateway during fee calculation.
}

/**
 * Force fee recalculation after payment method selection.
 *
 * Store API can call this before all checkout/session fields are in sync, so we
 * also persist selected gateway here to avoid stale unified fee state on COD/etc.
 *
 * @param mixed $payment_method Selected gateway id from Store API hook.
 */
function peachpay_convesiopay_force_fee_recalculation( $payment_method = '' ) {
	$selected_gateway = '';
	if ( is_string( $payment_method ) ) {
		$selected_gateway = sanitize_text_field( $payment_method );
	} elseif ( is_array( $payment_method ) && isset( $payment_method['payment_method'] ) ) {
		$selected_gateway = sanitize_text_field( $payment_method['payment_method'] );
	} elseif ( is_object( $payment_method ) && isset( $payment_method->payment_method ) ) {
		$selected_gateway = sanitize_text_field( $payment_method->payment_method );
	}

	if ( ! empty( $selected_gateway ) && WC()->session ) {
		WC()->session->set( 'chosen_payment_method', $selected_gateway );
		if ( 'peachpay_convesiopay_unified' !== $selected_gateway ) {
			WC()->session->set( 'convesiopay_selected_method', '' );
		}
	}

	if ( WC()->cart ) {
		WC()->cart->calculate_fees();
		WC()->cart->calculate_totals();
	}
}


// Only correct an invalid chosen payment method on checkout; never force ConvesioPay as default when none is chosen.
// Forcing a default when chosen_payment_method is empty can cause other gateways (e.g. Terra Wallet / store credit)
// to hide themselves on fragment/update_checkout, because some gateways only show when they are selected or when
// no other gateway has been forced. So we only overwrite when the current choice is no longer available.
add_action( 'template_redirect', function() {
    // Only run on checkout page (not on order endpoints like order-received)
    if ( ! is_checkout() || is_wc_endpoint_url() ) {
        return;
    }

    // Check if WooCommerce session is available
    if ( ! WC()->session ) {
        return;
    }

    $chosen_payment_method = WC()->session->get( 'chosen_payment_method' );

    // If nothing is chosen yet, do not set a default. Let WooCommerce/theme decide so that
    // store-credit and other gateways that depend on "first load" state are not hidden.
    if ( empty( $chosen_payment_method ) ) {
        return;
    }

    // Validate chosen method by ID and enabled only (no get_available_payment_gateways to avoid N× is_available()).
    $gateways = WC()->payment_gateways->payment_gateways();
    if ( isset( $gateways[ $chosen_payment_method ] ) && 'yes' === $gateways[ $chosen_payment_method ]->enabled ) {
        return;
    }

    // Chosen method is missing or disabled; pick the first enabled ConvesioPay gateway as fallback
    $convesiopay_gateway_ids = array(
        'peachpay_convesiopay_unified',
        'peachpay_convesiopay_card',
    );

    foreach ( $convesiopay_gateway_ids as $gateway_id ) {
        if ( isset( $gateways[ $gateway_id ] ) && 'yes' === $gateways[ $gateway_id ]->enabled ) {
            WC()->session->set( 'chosen_payment_method', $gateway_id );
            break;
        }
    }
}, 10 );


/**
 * Add AJAX endpoint for updating ConvesioPay payment methods
 */
add_action('wp_ajax_peachpay_convesiopay_update_payment_methods', 'peachpay_convesiopay_update_payment_methods');

/**
 * Add AJAX endpoint for updating ConvesioPay checkout theme
 */
add_action('wp_ajax_peachpay_convesiopay_update_theme', 'peachpay_convesiopay_update_theme');

/**
 * Add AJAX endpoint for updating ConvesioPay unified gateway label
 */
add_action('wp_ajax_peachpay_convesiopay_update_unified_label', 'peachpay_convesiopay_update_unified_label');

/**
 * Add AJAX endpoint for updating ConvesioPay card icons setting
 */
add_action('wp_ajax_peachpay_convesiopay_update_card_icons', 'peachpay_convesiopay_update_card_icons');

/**
 * Add AJAX endpoint for updating ConvesioPay order list logo visibility
 */
add_action( 'wp_ajax_peachpay_convesiopay_update_order_list_logo', 'peachpay_convesiopay_update_order_list_logo' );

/**
 * Add AJAX endpoint for updating accelerated checkout settings
 */
add_action( 'wp_ajax_peachpay_convesiopay_update_accelerated_checkout_settings', 'peachpay_convesiopay_update_accelerated_checkout_settings' );

/**
 * Add AJAX endpoint for creating BTCPay sessions
 */
add_action('wp_ajax_peachpay_convesiopay_create_btcpay_session', 'peachpay_convesiopay_create_btcpay_session');
add_action('wp_ajax_nopriv_peachpay_convesiopay_create_btcpay_session', 'peachpay_convesiopay_create_btcpay_session');

/**
 * Add AJAX endpoint for creating BTCPay intents
 */
add_action('wp_ajax_peachpay_convesiopay_create_btcpay_intent', 'peachpay_convesiopay_create_btcpay_intent');
add_action('wp_ajax_nopriv_peachpay_convesiopay_create_btcpay_intent', 'peachpay_convesiopay_create_btcpay_intent');

/**
 * Add AJAX endpoint for checking BTCPay payment status
 */
add_action('wp_ajax_peachpay_convesiopay_check_btcpay_status', 'peachpay_convesiopay_check_btcpay_status');
add_action('wp_ajax_nopriv_peachpay_convesiopay_check_btcpay_status', 'peachpay_convesiopay_check_btcpay_status');

/**
 * Build a lightweight cart snapshot for Blocks sync responses.
 *
 * Returns fee rows and totals in minor units (cents) so the frontend can
 * mirror canonical backend-calculated values without guessing.
 *
 * @return array|null
 */
function peachpay_convesiopay_build_cart_snapshot() {
	if ( ! function_exists( 'WC' ) || ! WC()->cart ) {
		return null;
	}

	WC()->cart->calculate_fees();
	WC()->cart->calculate_totals();

	$to_minor = static function( $amount ) {
		return (string) round( (float) $amount * 100 );
	};

	$fees = array();
	foreach ( WC()->cart->get_fees() as $fee ) {
		$fee_total     = isset( $fee->total ) ? (float) $fee->total : 0.0;
		$fee_total_tax = isset( $fee->tax ) ? (float) $fee->tax : 0.0;
		$fees[]        = array(
			'name'   => isset( $fee->name ) ? (string) $fee->name : '',
			'total'  => $to_minor( $fee_total ),
			'totals' => array(
				'total'       => $to_minor( $fee_total ),
				'total_price' => $to_minor( $fee_total ),
				'total_tax'   => $to_minor( $fee_total_tax ),
			),
		);
	}

	$cart = WC()->cart;
	$totals = array(
		'total_price'        => $to_minor( $cart->get_total( 'edit' ) ),
		'currency_symbol'    => (string) get_woocommerce_currency_symbol(),
		'currency_code'      => (string) get_woocommerce_currency(),
		'total_fees'         => $to_minor( $cart->get_fee_total() ),
		'total_fees_tax'     => $to_minor( $cart->get_fee_tax() ),
		'total_shipping'     => $to_minor( $cart->get_shipping_total() ),
		'total_shipping_tax' => $to_minor( $cart->get_shipping_tax() ),
		'total_tax'          => $to_minor( $cart->get_total_tax() ),
		'total_discount'     => $to_minor( $cart->get_discount_total() ),
	);

	return array(
		'fees'   => $fees,
		'totals' => $totals,
	);
}

/**
 * Add AJAX endpoint for storing ConvesioPay selected method in session (for Express Checkout)
 */
add_action('wp_ajax_peachpay_store_convesiopay_method', 'peachpay_store_convesiopay_method');
add_action('wp_ajax_nopriv_peachpay_store_convesiopay_method', 'peachpay_store_convesiopay_method');

/**
 * AJAX endpoint for requesting ConvesioPay Card Manager session link (WC Subscriptions – Update cards on file).
 * Logged-in only; no nopriv.
 */
add_action( 'wp_ajax_peachpay_convesiopay_request_card_manager_link', 'peachpay_convesiopay_request_card_manager_link' );

/**
 * WC Subscriptions: show "Update cards on file" on My Account → Subscriptions list and on single subscription view.
 * List: button in actions column via woocommerce_my_subscriptions_actions.
 * Single subscription: button inside the same Actions row (with Change payment, Cancel) via wcs_view_subscription_actions filter.
 */
add_action( 'woocommerce_my_subscriptions_actions', 'peachpay_convesiopay_my_subscriptions_card_manager_button', 10, 1 );
add_filter( 'wcs_view_subscription_actions', 'peachpay_convesiopay_add_card_manager_to_subscription_actions', 10, 3 );

/**
 * Store the selected ConvesioPay internal method in WC session.
 * This is used for checkout to apply correct fees based on card/applepay/btcpay selection.
 */
function peachpay_store_convesiopay_method() {
	// phpcs:ignore WordPress.Security.NonceVerification.Missing
	$method = isset( $_POST['convesiopay_selected_method'] ) ? sanitize_text_field( wp_unslash( $_POST['convesiopay_selected_method'] ) ) : '';
	// phpcs:ignore WordPress.Security.NonceVerification.Missing
	$selected_gateway = isset( $_POST['selected_gateway'] ) ? sanitize_text_field( wp_unslash( $_POST['selected_gateway'] ) ) : '';

	if ( empty( $method ) ) {
		wp_send_json_error( array( 'message' => 'No method provided' ) );
		return;
	}

	// Store in WC session for fee calculation during order placement.
	if ( WC()->session ) {
		WC()->session->set( 'convesiopay_selected_method', $method );
		if ( ! empty( $selected_gateway ) ) {
			WC()->session->set( 'chosen_payment_method', $selected_gateway );
			if ( 'peachpay_convesiopay_unified' !== $selected_gateway ) {
				WC()->session->set( 'convesiopay_selected_method', '' );
			}
		}
	}

	$cart = peachpay_convesiopay_build_cart_snapshot();
	wp_send_json_success(
		array(
			'method' => $method,
			'cart'   => $cart,
		)
	);
}

/**
 * Set WooCommerce chosen payment method in session (Blocks checkout).
 * Called by the Blocks frontend when the user selects a payment gateway so that
 * cart/totals (and fee calculation) use the correct gateway on the next request.
 *
 * Supports both logged-in and guest checkout (nopriv).
 */
function peachpay_convesiopay_blocks_set_chosen_payment_method() {
	if ( ! WC()->session ) {
		wp_send_json_error( array( 'message' => 'No session' ) );
		return;
	}

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

	if ( '' === $payment_method ) {
		wp_send_json_error( array( 'message' => 'No payment_method provided' ) );
		return;
	}

	WC()->session->set( 'chosen_payment_method', $payment_method );

	if ( 'peachpay_convesiopay_unified' !== $payment_method ) {
		WC()->session->set( 'convesiopay_selected_method', '' );
	}

	$cart = peachpay_convesiopay_build_cart_snapshot();
	wp_send_json_success(
		array(
			'payment_method' => $payment_method,
			'cart'           => $cart,
		)
	);
}

add_action( 'wp_ajax_peachpay_convesiopay_blocks_set_chosen_payment_method', 'peachpay_convesiopay_blocks_set_chosen_payment_method' );
add_action( 'wp_ajax_nopriv_peachpay_convesiopay_blocks_set_chosen_payment_method', 'peachpay_convesiopay_blocks_set_chosen_payment_method' );
/**
 * Whether a subscription was migrated from legacy ConvesioPay (cpay) to PeachPay.
 *
 * @param WC_Subscription|null $subscription Subscription object.
 * @return bool
 */
function peachpay_convesiopay_is_legacy_cpay_migrated_subscription( $subscription ) {
	if ( ! $subscription || ! is_callable( array( $subscription, 'get_meta' ) ) ) {
		return false;
	}
	return 'cpay' === (string) $subscription->get_meta( '_pp_migration_source' );
}

/**
 * Derive Card Manager customer id from subscription billing email (legacy migrated subs).
 *
 * @param WC_Subscription $subscription Subscription object.
 * @return string MD5 hash of billing email, or empty when unavailable.
 */
function peachpay_convesiopay_get_card_manager_customer_id_from_billing_email( $subscription ) {
	if ( ! $subscription || ! is_callable( array( $subscription, 'get_billing_email' ) ) ) {
		return '';
	}
	$email = sanitize_email( (string) $subscription->get_billing_email() );
	if ( '' === $email ) {
		return '';
	}
	return md5( strtolower( $email ) );
}

/**
 * Get ConvesioPay customer ID for a subscription or user.
 * Used for Card Manager (Update cards on file) and subscription renewal.
 *
 * @param WC_Subscription|null $subscription Optional. Subscription to get customer ID from (via parent order). If null, uses user_id to get from user meta.
 * @param int|null             $user_id     Optional. User ID. If subscription provided, derived from subscription; otherwise required for user-meta lookup.
 * @return string Empty if not found; otherwise ConvesioPay customer ID.
 */
function peachpay_convesiopay_get_card_manager_customer_id( $subscription = null, $user_id = null ) {
	if ( $subscription && is_callable( array( $subscription, 'get_parent_id' ) ) ) {
		$parent_id = $subscription->get_parent_id();
		if ( $parent_id ) {
			$parent_order = wc_get_order( $parent_id );
			if ( $parent_order ) {
				$customer_id = $parent_order->get_meta( '_convesiopay_customer_id' );
				if ( ! empty( $customer_id ) ) {
					return (string) $customer_id;
				}
			}
		}
	}
	// For legacy-migrated subscriptions, skip user meta entirely.
	// User meta _convesiopay_customer_id may belong to an unrelated native checkout or
	// profile. Using it here would open the Card Manager for the wrong ConvesioPay
	// customer and then persist that wrong ID to this subscription's parent order.
	// md5(billing_email) is the identity ConvesioPay uses for this subscription's cards.
	if ( $subscription && peachpay_convesiopay_is_legacy_cpay_migrated_subscription( $subscription ) ) {
		$legacy_customer_id = peachpay_convesiopay_get_card_manager_customer_id_from_billing_email( $subscription );
		if ( '' !== $legacy_customer_id ) {
			return $legacy_customer_id;
		}
	}

	// Non-migrated path: fall back to user meta.
	$uid = $user_id;
	if ( $subscription && is_callable( array( $subscription, 'get_customer_id' ) ) ) {
		$uid = $subscription->get_customer_id();
	}
	if ( $uid ) {
		$customer_id = get_user_meta( (int) $uid, '_convesiopay_customer_id', true );
		if ( is_string( $customer_id ) && '' !== $customer_id ) {
			return $customer_id;
		}
	}

	return '';
}

/**
 * Request ConvesioPay Card Manager session link (emailed to customer by API).
 * Called via AJAX from My Account → Subscriptions. Server-side only; no card data in WordPress.
 */
function peachpay_convesiopay_request_card_manager_link() {
	if ( ! is_user_logged_in() ) {
		wp_send_json_error( array( 'message' => __( 'You must be logged in to update your payment methods.', 'peachpay-for-woocommerce' ) ) );
		return;
	}

	$nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
	if ( ! wp_verify_nonce( $nonce, 'peachpay_convesiopay_card_manager' ) ) {
		wp_send_json_error( array( 'message' => __( 'Security check failed. Please refresh and try again.', 'peachpay-for-woocommerce' ) ) );
		return;
	}

	$user_id = get_current_user_id();
	$subscription_id = isset( $_POST['subscription_id'] ) ? absint( $_POST['subscription_id'] ) : 0;

	if ( ! class_exists( 'PeachPay_ConvesioPay_Integration' ) || ! PeachPay_ConvesioPay_Integration::connected() ) {
		wp_send_json_error( array( 'message' => __( 'Payment provider is not connected. Please contact the store.', 'peachpay-for-woocommerce' ) ) );
		return;
	}

	$subscription = null;
	if ( $subscription_id && function_exists( 'wcs_is_subscription' ) ) {
		$subscription = wcs_get_subscription( $subscription_id );
		if ( ! $subscription || ! wcs_is_subscription( $subscription ) ) {
			wp_send_json_error( array( 'message' => __( 'Subscription not found.', 'peachpay-for-woocommerce' ) ) );
			return;
		}
		if ( (int) $subscription->get_customer_id() !== $user_id ) {
			wp_send_json_error( array( 'message' => __( 'You do not have permission to manage this subscription.', 'peachpay-for-woocommerce' ) ) );
			return;
		}
		if ( ! PeachPay_ConvesioPay_Integration::is_payment_gateway( $subscription->get_payment_method() ) ) {
			wp_send_json_error( array( 'message' => __( 'This subscription is not paid with the supported payment method for updating cards.', 'peachpay-for-woocommerce' ) ) );
			return;
		}
	}

	$customer_id = peachpay_convesiopay_get_card_manager_customer_id( $subscription, $user_id );
	if ( empty( $customer_id ) ) {
		wp_send_json_error( array( 'message' => __( "We don't have a saved payment profile for this account. If you just subscribed, try again after your first payment is confirmed.", 'peachpay-for-woocommerce' ) ) );
		return;
	}

	if ( ! $subscription && function_exists( 'wcs_get_users_subscriptions' ) ) {
		$user_subs = wcs_get_users_subscriptions( $user_id );
		$has_convesiopay = false;
		foreach ( $user_subs as $sub ) {
			if ( PeachPay_ConvesioPay_Integration::is_payment_gateway( $sub->get_payment_method() ) ) {
				$has_convesiopay = true;
				break;
			}
		}
		if ( ! $has_convesiopay ) {
			wp_send_json_error( array( 'message' => __( 'No ConvesioPay subscription found for your account.', 'peachpay-for-woocommerce' ) ) );
			return;
		}
	}

	$config = PeachPay_ConvesioPay_Integration::config();
	$secret_key = $config['secret_key'] ?? '';
	if ( empty( $secret_key ) ) {
		wp_send_json_error( array( 'message' => __( 'Payment provider configuration error. Please contact the store.', 'peachpay-for-woocommerce' ) ) );
		return;
	}

	$api_url = peachpay_is_test_mode() ? 'https://api-qa.convesiopay.com' : 'https://api.convesiopay.com';
	$card_session_url = $api_url . '/v1/customers/' . rawurlencode( $customer_id ) . '/cards/session';

	$response = wp_remote_post(
		$card_session_url,
		array(
			'method'  => 'POST',
			'timeout' => 30,
			'headers' => array(
				'Authorization' => $secret_key,
				'Content-Type'  => 'application/json',
			),
			'body'    => '{}',
		)
	);

	if ( is_wp_error( $response ) ) {
		peachpay_log( 'error', 'ConvesioPay Card Manager: request failed - ' . $response->get_error_message() );
		wp_send_json_error( array( 'message' => __( 'Something went wrong. Please try again later.', 'peachpay-for-woocommerce' ) ) );
		return;
	}

	$response_code = wp_remote_retrieve_response_code( $response );
	$response_body = wp_remote_retrieve_body( $response );

	if ( $response_code === 200 ) {
		peachpay_log( 'info', 'ConvesioPay Card Manager: session requested successfully for customer ' . $customer_id );

		// Persist the resolved customer ID to the parent order so the card selector
		// can look up the token store on next page load without recomputing the MD5 hash.
		if ( $subscription ) {
			$parent_order_id = $subscription->get_parent_id();
			if ( $parent_order_id ) {
				$parent_order = wc_get_order( $parent_order_id );
				if ( $parent_order && '' === (string) $parent_order->get_meta( '_convesiopay_customer_id' ) ) {
					$parent_order->update_meta_data( '_convesiopay_customer_id', $customer_id );
					$parent_order->save_meta_data();
				}
			}
		}

		wp_send_json_success(
			array(
				'message' => __( 'A secure link to update your cards has been sent to your email. The link expires in 15 minutes.', 'peachpay-for-woocommerce' ),
			)
		);
		return;
	}

	$error_data = json_decode( $response_body, true );
	$api_message = is_array( $error_data ) && isset( $error_data['message'] ) ? $error_data['message'] : '';

	if ( $response_code === 401 ) {
		peachpay_log( 'error', 'ConvesioPay Card Manager: authorization error (401)' );
		wp_send_json_error( array( 'message' => __( 'Payment provider configuration error. Please contact the store.', 'peachpay-for-woocommerce' ) ) );
		return;
	}
	if ( $response_code === 404 ) {
		peachpay_log( 'error', 'ConvesioPay Card Manager: customer not found (404)' );
		wp_send_json_error( array( 'message' => __( 'Customer not found with the payment provider.', 'peachpay-for-woocommerce' ) ) );
		return;
	}
	if ( $response_code === 500 ) {
		peachpay_log( 'error', 'ConvesioPay Card Manager: server error (500) - ' . $api_message );
		wp_send_json_error( array( 'message' => __( 'Too many update requests. Please try again in a few minutes.', 'peachpay-for-woocommerce' ) ) );
		return;
	}

	peachpay_log( 'error', 'ConvesioPay Card Manager: unexpected response ' . $response_code . ' - ' . $response_body );
	wp_send_json_error(
		array(
			'message' => ! empty( $api_message ) ? $api_message : __( 'Something went wrong. Please try again later.', 'peachpay-for-woocommerce' ),
		)
	);
}

/**
 * Output "Update cards on file" button on My Account → Subscriptions table (per row).
 *
 * @param WC_Subscription $subscription Subscription object.
 */
function peachpay_convesiopay_my_subscriptions_card_manager_button( $subscription ) {
	if ( ! $subscription || ! function_exists( 'wcs_is_subscription' ) || ! wcs_is_subscription( $subscription ) ) {
		return;
	}
	if ( ! class_exists( 'PeachPay_ConvesioPay_Integration' ) || ! PeachPay_ConvesioPay_Integration::connected() ) {
		return;
	}
	if ( ! PeachPay_ConvesioPay_Integration::is_payment_gateway( $subscription->get_payment_method() ) ) {
		return;
	}
	$customer_id = peachpay_convesiopay_get_card_manager_customer_id( $subscription, null );
	if ( empty( $customer_id ) ) {
		return;
	}
	$url = '#';
	printf(
		'<a href="%1$s" class="woocommerce-button button peachpay-convesiopay-subscriptions-update-cards-on-file-btn" data-subscription-id="%2$s" aria-label="%3$s">%4$s</a> ',
		esc_url( $url ),
		esc_attr( (string) $subscription->get_id() ),
		esc_attr__( 'Update cards on file', 'peachpay-for-woocommerce' ),
		esc_html__( 'Update cards on file', 'peachpay-for-woocommerce' )
	);
}

/**
 * Add "Update cards on file" to the subscription view actions array (same row as Change payment, Cancel).
 * Rendered by WC Subscriptions template; key becomes CSS class so JS can bind to .peachpay-convesiopay-subscriptions-update-cards-on-file-btn.
 *
 * @param array            $actions     Existing actions.
 * @param WC_Subscription  $subscription Subscription object.
 * @param int              $user_id    User ID.
 * @return array Modified actions.
 */
function peachpay_convesiopay_add_card_manager_to_subscription_actions( $actions, $subscription, $user_id ) {
	if ( ! $subscription || ! function_exists( 'wcs_is_subscription' ) || ! wcs_is_subscription( $subscription ) ) {
		return $actions;
	}
	if ( ! class_exists( 'PeachPay_ConvesioPay_Integration' ) || ! PeachPay_ConvesioPay_Integration::connected() ) {
		return $actions;
	}
	if ( ! PeachPay_ConvesioPay_Integration::is_payment_gateway( $subscription->get_payment_method() ) ) {
		return $actions;
	}
	$customer_id = peachpay_convesiopay_get_card_manager_customer_id( $subscription, $user_id );
	if ( empty( $customer_id ) ) {
		return $actions;
	}
	$actions['peachpay-convesiopay-subscriptions-update-cards-on-file-btn'] = array(
		'url'       => '#',
		'name'      => __( 'Update cards on file', 'peachpay-for-woocommerce' ),
		'block_ui'  => false,
	);
	return $actions;
}

/**
 * Get ConvesioPay customer id for a subscription
 *
 * @param WC_Subscription $subscription Subscription object.
 * @return string ConvesioPay customer id or empty string.
 */
function peachpay_convesiopay_get_subscription_customer_id( $subscription ) {

	if ( ! $subscription || ! is_callable( array( $subscription, 'get_meta' ) ) ) {
		peachpay_log( 'debug', 'Card for renewals: get_subscription_customer_id – no subscription or get_meta, return empty' );
		return '';
	}

	$subscription_id      = $subscription->get_id();
	$customer_id = $subscription->get_meta( '_convesiopay_customer_id' );

	// If customer id is set in subscription meta, return it
	if ( $customer_id !== '' && $customer_id !== null ) {
		peachpay_log( 'debug', 'Card for renewals: get_subscription_customer_id – subscription_id=' . $subscription_id . ' source=subscription_meta customer_id=' . $customer_id );
		return (string) $customer_id;
	}

	// If customer id is not set in subscription meta, check parent order
	$parent_order_id = $subscription->get_parent_id();
	if ( $parent_order_id ) {
		$parent = wc_get_order( $parent_order_id );
		if ( $parent ) {
			$customer_id = $parent->get_meta( '_convesiopay_customer_id' );
			if ( $customer_id !== '' && $customer_id !== null ) {
				peachpay_log( 'debug', 'Card for renewals: get_subscription_customer_id – subscription_id=' . $subscription_id . ' source=parent_order parent_id=' . $parent_order_id . ' customer_id=' . $customer_id );
				return (string) $customer_id;
			}
		}
	}

	// Legacy cpay migrated: fall back to md5(billing email) so the card selector can
	// query the token store using the same ID that Card Manager used before a canonical
	// customer ID was written back to the parent order.
	if ( peachpay_convesiopay_is_legacy_cpay_migrated_subscription( $subscription ) ) {
		$md5_customer_id = peachpay_convesiopay_get_card_manager_customer_id_from_billing_email( $subscription );
		if ( '' !== $md5_customer_id ) {
			peachpay_log( 'debug', 'Card for renewals: get_subscription_customer_id – subscription_id=' . $subscription_id . ' source=md5_email customer_id=' . $md5_customer_id );
			return $md5_customer_id;
		}
	}

	// If customer id is not set in subscription meta or parent order, return empty
	peachpay_log( 'debug', 'Card for renewals: get_subscription_customer_id – subscription_id=' . $subscription_id . ' no customer_id found, return empty' );
	return '';
}

/**
 * Get stored payment methods for display only (id + last4 + brand – no sensitive data).
 * Data source: custom customer token table keyed by ConvesioPay customerId.
 *
 * @param int    $user_id     User ID (unused; kept for backward compatibility).
 * @param string $customer_id ConvesioPay customer id.
 * @return array List of array( 'id' => string, 'last4' => string, 'brand' => string ).
 */
function peachpay_convesiopay_get_stored_cards_for_display( $user_id, $customer_id = '' ) {
	if ( '' === $customer_id || ! class_exists( 'PeachPay_ConvesioPay_Customer_Token_Store' ) ) {
		return array();
	}
	$stored = PeachPay_ConvesioPay_Customer_Token_Store::get_stored_payment_methods( $customer_id );
	if ( ! is_array( $stored ) || empty( $stored ) ) {
		return array();
	}
	$out = array();
	foreach ( $stored as $method ) {
		if ( ! is_array( $method ) || empty( $method['id'] ) ) {
			continue;
		}
		$out[] = array(
			'id'     => (string) $method['id'],
			'last4'  => isset( $method['lastFour'] ) ? (string) $method['lastFour'] : '',
			'brand'  => isset( $method['brand'] ) ? (string) $method['brand'] : '',
		);
	}
	return $out;
}

/**
 * Get currently selected token for a subscription.
 * Selection source: parent order meta _convesiopay_stored_payment_method_id.
 *
 * @param WC_Subscription $subscription Subscription object.
 * @return string Selected token id from parent order, even when not currently on file.
 */
function peachpay_convesiopay_get_subscription_card_id( $subscription ) {
	$selected = '';
	$parent_order_id = $subscription->get_parent_id();
	if ( $parent_order_id ) {
		$parent_order = wc_get_order( $parent_order_id );
		if ( $parent_order ) {
			$selected = (string) $parent_order->get_meta( '_convesiopay_stored_payment_method_id' );
		}
	}
	return $selected;
}

/**
 * Render "Card for renewals" selector on View Subscription (only ConvesioPay, only when user has stored cards).
 */
add_action( 'woocommerce_subscription_before_actions', 'peachpay_convesiopay_subscription_card_selector', 10, 1 );

function peachpay_convesiopay_subscription_card_selector( $subscription ) {
	if ( ! $subscription || ! function_exists( 'wcs_is_subscription' ) || ! wcs_is_subscription( $subscription ) ) {
		return;
	}
	if ( ! class_exists( 'PeachPay_ConvesioPay_Integration' ) || ! PeachPay_ConvesioPay_Integration::is_payment_gateway( $subscription->get_payment_method() ) ) {
		return;
	}
	$user_id     = $subscription->get_customer_id();
	$customer_id = peachpay_convesiopay_get_subscription_customer_id( $subscription );
	$cards       = peachpay_convesiopay_get_stored_cards_for_display( $user_id, $customer_id );
	if ( empty( $cards ) ) {
		peachpay_log( 'debug', 'Card for renewals: subscription_card_selector – subscription_id=' . $subscription->get_id() . ' user_id=' . $user_id . ' customer_id=' . $customer_id . ' no cards, hide selector' );
		return;
	}
	$current_id   = peachpay_convesiopay_get_subscription_card_id( $subscription );
	peachpay_log( 'info', 'Card for renewals: subscription_card_selector – subscription_id=' . $subscription->get_id() . ' user_id=' . $user_id . ' customer_id=' . $customer_id . ' cards_count=' . count( $cards ) . ' preselected_id=' . $current_id );
	$subscription_id = $subscription->get_id();
	$nonce = wp_create_nonce( 'peachpay_convesiopay_subscription_card_' . $subscription_id );
	$is_current_card_exists = false;

	// Resolve legacy ADN ref so the fallback row can show a contextual message.
	$is_migrated_sub = peachpay_convesiopay_is_legacy_cpay_migrated_subscription( $subscription );
	$legacy_adn_ref  = '';
	if ( $is_migrated_sub ) {
		$_parent_order_for_adn = wc_get_order( $subscription->get_parent_id() );
		if ( $_parent_order_for_adn ) {
			$legacy_adn_ref = trim( (string) $_parent_order_for_adn->get_meta( '_adn_recurringDetailReference' ) );
		}
		if ( '' === $legacy_adn_ref && is_callable( array( $subscription, 'get_meta' ) ) ) {
			$legacy_adn_ref = trim( (string) $subscription->get_meta( '_adn_recurringDetailReference' ) );
		}
	}
	?>
	<tr class="peachpay-convesiopay-subscription-card-row">
		<td><?php esc_html_e( 'Card for renewals', 'peachpay-for-woocommerce' ); ?></td>
		<td>
			<?php if ( '' === $current_id ) : ?>
				<p style="margin:0 0 8px;color:#b32d2e;font-size:0.9em;">
					<?php esc_html_e( 'No card selected for renewal. Please select a card below.', 'peachpay-for-woocommerce' ); ?>
				</p>
			<?php endif; ?>
			<ul class="peachpay-convesiopay-subscription-cards-list" style="list-style:none;margin:0;padding:0;">
				<?php foreach ( $cards as $card ) :
					$label = sprintf(
						/* translators: 1: card brand, 2: last 4 digits */
						__( '%1$s ending in %2$s', 'peachpay-for-woocommerce' ),
						esc_html( ucfirst( strtolower( $card['brand'] ) ) ?: _x( 'Card', 'payment method', 'peachpay-for-woocommerce' ) ),
						esc_html( $card['last4'] )
					);
					$checked = ( $current_id === $card['id'] ) ? ' checked="checked"' : '';
					if ( $current_id === $card['id'] ) {
						$is_current_card_exists = true;
					}
				?>
					<li style="margin-bottom:4px;">
						<label style="display:inline-flex;align-items:center;gap:6px;cursor:pointer;">
							<input
								type="radio"
								name="peachpay_convesiopay_subscription_card"
								value="<?php echo esc_attr( $card['id'] ); ?>"
								data-subscription-id="<?php echo esc_attr( (string) $subscription_id ); ?>"
								data-nonce="<?php echo esc_attr( $nonce ); ?>"
								<?php echo $checked; ?>
								class="peachpay-convesiopay-subscription-card-radio"
							/>
							<span><?php echo esc_html( $label ); ?></span>
						</label>
					</li>
				<?php endforeach; ?>
				<?php if ( ! $is_current_card_exists && $current_id !== '' ) :
					// The currently selected token is not in the stored methods list.
					// Two cases:
					// 1) Migrated sub whose selected token IS the legacy ADN ref — still valid for
					//    renewal via legacy path; show a reassuring label, not a warning.
					// 2) Any other token not on file — may fail; keep the existing warning.
					$is_legacy_adn_token = $is_migrated_sub && '' !== $legacy_adn_ref && $current_id === $legacy_adn_ref;
					if ( $is_legacy_adn_token ) {
						$fallback_label       = __( 'Original card (from previous subscription)', 'peachpay-for-woocommerce' );
						$fallback_helper_text = __( 'This is the card from before migration and will continue to be charged at renewal. Select a new card above to switch.', 'peachpay-for-woocommerce' );
					} else {
						$fallback_label       = __( 'Previously selected card (no longer on file)', 'peachpay-for-woocommerce' );
						$fallback_helper_text = __( 'This token is kept for now, but may fail at renewal. Choose one of the available cards to update your renewal card.', 'peachpay-for-woocommerce' );
					}
					$checked = ' checked="checked"';
					?>
					<li style="margin-bottom:4px;">
						<label style="display:inline-flex;align-items:center;gap:6px;cursor:pointer;">
							<input
								type="radio"
								name="peachpay_convesiopay_subscription_card"
								value="<?php echo esc_attr( $current_id ); ?>"
								data-subscription-id="<?php echo esc_attr( (string) $subscription_id ); ?>"
								data-nonce="<?php echo esc_attr( $nonce ); ?>"
								<?php echo $checked; ?>
								class="peachpay-convesiopay-subscription-card-radio"
							/>
							<span><?php echo esc_html( $fallback_label ); ?></span>
						</label>
						<small style="display:block;color:#666;margin-left:26px;">
							<?php echo esc_html( $fallback_helper_text ); ?>
						</small>
					</li>
				<?php endif; ?>
			</ul>
		</td>
	</tr>
	<?php
}

/**
 * AJAX: save selected card for subscription renewals.
 */
add_action( 'wp_ajax_peachpay_convesiopay_save_subscription_card', 'peachpay_convesiopay_save_subscription_card' );

function peachpay_convesiopay_save_subscription_card() {
	if ( ! is_user_logged_in() ) {
		wp_send_json_error( array( 'message' => __( 'You must be logged in.', 'peachpay-for-woocommerce' ) ) );
		return;
	}
	$nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
	$subscription_id = isset( $_POST['subscription_id'] ) ? absint( $_POST['subscription_id'] ) : 0;
	$card_token = isset( $_POST['card_token'] ) ? sanitize_text_field( wp_unslash( $_POST['card_token'] ) ) : '';
	if ( '' === $card_token && isset( $_POST['card_id'] ) ) {
		// Backward compatibility with earlier frontend payload.
		$card_token = sanitize_text_field( wp_unslash( $_POST['card_id'] ) );
	}
	if ( ! $subscription_id || ! wp_verify_nonce( $nonce, 'peachpay_convesiopay_subscription_card_' . $subscription_id ) ) {
		wp_send_json_error( array( 'message' => __( 'Security check failed.', 'peachpay-for-woocommerce' ) ) );
		return;
	}
	if ( ! function_exists( 'wcs_get_subscription' ) ) {
		wp_send_json_error( array( 'message' => __( 'Subscriptions not available.', 'peachpay-for-woocommerce' ) ) );
		return;
	}
	$subscription = wcs_get_subscription( $subscription_id );
	if ( ! $subscription || ! wcs_is_subscription( $subscription ) ) {
		wp_send_json_error( array( 'message' => __( 'Subscription not found.', 'peachpay-for-woocommerce' ) ) );
		return;
	}
	if ( (int) $subscription->get_customer_id() !== get_current_user_id() ) {
		wp_send_json_error( array( 'message' => __( 'You do not have permission to change this subscription.', 'peachpay-for-woocommerce' ) ) );
		return;
	}
	if ( ! class_exists( 'PeachPay_ConvesioPay_Integration' ) || ! PeachPay_ConvesioPay_Integration::is_payment_gateway( $subscription->get_payment_method() ) ) {
		wp_send_json_error( array( 'message' => __( 'This subscription does not use a supported payment method.', 'peachpay-for-woocommerce' ) ) );
		return;
	}
	$user_id     = $subscription->get_customer_id();
	$customer_id = peachpay_convesiopay_get_subscription_customer_id( $subscription );
	$cards       = peachpay_convesiopay_get_stored_cards_for_display( $user_id, $customer_id );
	$ids         = array_column( $cards, 'id' );

	$parent_order_id = $subscription->get_parent_id();
	$parent_order = $parent_order_id ? wc_get_order( $parent_order_id ) : null;
	if ( ! $parent_order ) {
		wp_send_json_error( array( 'message' => __( 'Parent order not found for this subscription.', 'peachpay-for-woocommerce' ) ) );
		return;
	}
	$current_parent_token = (string) $parent_order->get_meta( '_convesiopay_stored_payment_method_id' );

	peachpay_log( 'debug', 'Card for renewals: save_subscription_card – subscription_id=' . $subscription_id . ' user_id=' . $user_id . ' customer_id=' . $customer_id . ' card_token=' . $card_token . ' valid_ids=[' . implode( ', ', $ids ) . ']' );

	$is_on_file_token       = in_array( $card_token, $ids, true );
	$is_current_parent_token = ( '' !== $card_token && $card_token === $current_parent_token );

	// Allow either:
	// 1) a currently on-file token, or
	// 2) the already selected parent-order token (legacy/missing on-file edge case).
	if ( empty( $card_token ) || ( ! $is_on_file_token && ! $is_current_parent_token ) ) {
		peachpay_log( 'warning', 'Card for renewals: save_subscription_card – subscription_id=' . $subscription_id . ' card_token=' . $card_token . ' invalid token, rejected' );
		wp_send_json_error( array( 'message' => __( 'Selected card is not on file.', 'peachpay-for-woocommerce' ) ) );
		return;
	}

	$previous_id = (string) $parent_order->get_meta( '_convesiopay_stored_payment_method_id' );
	if ( $previous_id === $card_token ) {
		wp_send_json_success( array( 'message' => __( 'Card for renewals is already selected.', 'peachpay-for-woocommerce' ) ) );
		return;
	}
	$parent_order->update_meta_data( '_convesiopay_stored_payment_method_id', $card_token );

	// Mark that the user has explicitly chosen a native renewal card.
	// This flag gates the native-path logic in process_subscription_renewal() so that
	// migration-set tokens (which may differ from _adn_recurringDetailReference in format)
	// are never mistaken for user-selected native cards.
	$parent_order->update_meta_data( '_pp_cpay_user_renewal_card', '1' );

	// If customer_id was resolved via MD5 fallback (missing from parent order), persist it
	// now so the renewal does not need to re-derive it and future lookups find it directly.
	if ( '' !== $customer_id && '' === (string) $parent_order->get_meta( '_convesiopay_customer_id' ) ) {
		$parent_order->update_meta_data( '_convesiopay_customer_id', $customer_id );
	}

	$parent_order->save();
	peachpay_log( 'info', 'Card for renewals: save_subscription_card – subscription_id=' . $subscription_id . ' updated parent order card from ' . $previous_id . ' to ' . $card_token );

	// Add subscription note for admin (visible in subscription order notes)
	$card_label = '';
	if ( ! empty( $card_token ) ) {
		foreach ( $cards as $c ) {
			if ( isset( $c['id'] ) && $c['id'] === $card_token ) {
				$brand  = isset( $c['brand'] ) ? ucfirst( strtolower( $c['brand'] ) ) : _x( 'Card', 'payment method', 'peachpay-for-woocommerce' );
				$last4  = isset( $c['last4'] ) ? $c['last4'] : '';
				$card_label = $last4 ? sprintf( '%s ending in %s', $brand, $last4 ) : $brand;
				break;
			}
		}
	}
	if ( $card_label ) {
		$subscription->add_order_note(
			sprintf(
				/* translators: %s: card description e.g. "Visa ending in 1234" */
				__( 'Customer changed card for renewals to %s.', 'peachpay-for-woocommerce' ),
				$card_label
			)
		);
	} else {
		$subscription->add_order_note( __( 'Customer kept/selected a renewal token that is no longer on file.', 'peachpay-for-woocommerce' ) );
	}

	wp_send_json_success( array( 'message' => __( 'Card for renewals updated.', 'peachpay-for-woocommerce' ) ) );
}

/**
 * Register and enqueue ConvesioPay scripts
 */
add_action('wp_enqueue_scripts', 'peachpay_convesiopay_enqueue_scripts');

/**
 * Enqueue ConvesioPay admin scripts
 */
add_action('admin_enqueue_scripts', 'peachpay_convesiopay_enqueue_admin_scripts');

function peachpay_convesiopay_enqueue_scripts() {
    // DISABLED: Conflicting with unified gateway - individual checkout.js script disabled
    // The unified gateway (convesiopay-unified-classic.js) handles all ConvesioPay functionality

    // OLD CODE (commented out to prevent conflicts):
    // wp_register_script(
    //     'peachpay-convesiopay-checkout',
    //     plugins_url('assets/js/checkout.js', __FILE__),
    //     array('jquery', 'wp-util'),
    //     '1.2.0',
    //     true
    // );
    //
    // wp_enqueue_script('peachpay-convesiopay-checkout');

    // My Account → Subscriptions: "Update cards on file" (ConvesioPay Card Manager).
    if ( function_exists( 'is_account_page' ) && is_account_page()
        && function_exists( 'is_wc_endpoint_url' ) && ( is_wc_endpoint_url( 'subscriptions' ) || is_wc_endpoint_url( 'view-subscription' ) )
        && class_exists( 'PeachPay_ConvesioPay_Integration' ) && PeachPay_ConvesioPay_Integration::connected()
    ) {
        wp_enqueue_style(
            'peachpay-convesiopay-subscriptions-update-cards-on-file',
            plugins_url( 'assets/css/convesiopay-subscriptions-update-cards-on-file.css', __FILE__ ),
            array(),
            '1.0.5'
        );
        wp_enqueue_script(
            'peachpay-convesiopay-subscriptions-update-cards-on-file',
            plugins_url( 'assets/js/convesiopay-subscriptions-update-cards-on-file.js', __FILE__ ),
            array( 'jquery' ),
            '1.0.5',
            true
        );
        $card_manager_config = array(
            'ajaxUrl'    => admin_url( 'admin-ajax.php' ),
            'nonce'      => wp_create_nonce( 'peachpay_convesiopay_card_manager' ),
            'sendingText' => __( 'Sending…', 'peachpay-for-woocommerce' ),
            'saveCardAction' => 'peachpay_convesiopay_save_subscription_card',
            'savedText'  => __( 'Card for renewals updated.', 'peachpay-for-woocommerce' ),
            'successTitle' => __( 'Please Check your email', 'peachpay-for-woocommerce' ),
            'successIntro' => __( 'We sent a secure link to update your saved cards.', 'peachpay-for-woocommerce' ),
            'successSteps' => array(
                __( 'Open the email and follow the link to add or remove cards on file.', 'peachpay-for-woocommerce' ),
                __( 'The link expires in 15 minutes.', 'peachpay-for-woocommerce' ),
                __( 'If you do not see the email, check your spam or junk folder.', 'peachpay-for-woocommerce' ),
            ),
            'closeText'  => __( 'Got it', 'peachpay-for-woocommerce' ),
            'closeLabel' => __( 'Close', 'peachpay-for-woocommerce' ),
            'savedTitle' => __( 'Card updated', 'peachpay-for-woocommerce' ),
            'savedIntro' => __( 'Your renewal card has been updated. This card will be charged at your next renewal.', 'peachpay-for-woocommerce' ),
        );
        if ( function_exists( 'is_wc_endpoint_url' ) && is_wc_endpoint_url( 'view-subscription' ) && function_exists( 'get_query_var' ) ) {
            $view_sub_id = get_query_var( 'view-subscription' );
            if ( $view_sub_id ) {
                $card_manager_config['subscriptionId'] = (string) absint( $view_sub_id );
            }
        }
        wp_localize_script(
            'peachpay-convesiopay-subscriptions-update-cards-on-file',
            'peachpayConvesioPayCardManager',
            $card_manager_config
        );
    }
}

/**
 * Add nonce for AJAX security
 */
add_action('wp_enqueue_scripts', 'peachpay_convesiopay_add_nonce', 20); // Run after scripts are enqueued

function peachpay_convesiopay_add_nonce() {
    // Check if the checkout script is enqueued
    if (wp_script_is('peachpay-convesiopay-checkout', 'enqueued')) {
        $ajax_config = array(
            'ajax_url' => admin_url('admin-ajax.php'),
            'create_transaction_url' => WC_AJAX::get_endpoint('pp-create-transaction'),
            'nonce' => wp_create_nonce('peachpay_convesiopay_nonce')
        );
        
        wp_localize_script('peachpay-convesiopay-checkout', 'peachpayConvesioPayAjax', $ajax_config);
    }
    
    // Also add AJAX config globally for any script that might need it
    wp_localize_script('jquery', 'peachpayConvesiopayAjax', array(
        'ajax_url' => admin_url('admin-ajax.php'),
        'create_transaction_url' => WC_AJAX::get_endpoint('pp-create-transaction'),
        'nonce' => wp_create_nonce('peachpay_convesiopay_nonce')
    ));
}

/**
 * Enqueue ConvesioPay admin scripts for WooCommerce settings page
 */
function peachpay_convesiopay_enqueue_admin_scripts($hook) {
    // Only load on WooCommerce settings pages
    if ($hook !== 'woocommerce_page_wc-settings') {
        return;
    }
    
    // Check if we're on the payments tab
    $tab = $_GET['tab'] ?? '';
    if ($tab !== 'checkout') {
        return;
    }
    
    // Enqueue the admin payment methods script
    wp_enqueue_script(
        'peachpay-convesiopay-admin-payment-methods',
        plugins_url('assets/js/admin-payment-methods.js', __FILE__),
        array('jquery'),
        '1.9.0',
        true
    );
    
    // Add AJAX URL for admin scripts
    wp_localize_script('peachpay-convesiopay-admin-payment-methods', 'convesioPayAdmin', array(
        'ajaxUrl' => admin_url('admin-ajax.php'),
        'nonce' => wp_create_nonce('woocommerce-settings')
    ));
}



/**
 * Update ConvesioPay payment methods via API
 */
function peachpay_convesiopay_update_payment_methods() {
    // Security checks
    if (!current_user_can('manage_woocommerce')) {
        wp_send_json_error(array('message' => 'Insufficient permissions'));
        return;
    }
    
    // Verify nonce for security
    $nonce = $_POST['nonce'] ?? '';
    $nonce_verified = wp_verify_nonce($nonce, 'woocommerce-settings');
    
    if (!$nonce_verified) {
        wp_send_json_error(array('message' => 'Security check failed'));
        return;
    }
    
    // Get parameters from request
    $gateway_id = sanitize_text_field($_POST['gateway_id'] ?? '');
    $enabled = $_POST['enabled'] === 'true';
    
    if (empty($gateway_id)) {
        wp_send_json_error(array('message' => 'Gateway ID is required'));
        return;
    }
    
    try {
        // Get ConvesioPay configuration
        $config = PeachPay_ConvesioPay_Integration::config();
        $secret_key = $config['secret_key'] ?? '';
        
        if (empty($secret_key)) {
            wp_send_json_error(array('message' => 'ConvesioPay configuration error'));
            return;
        }
        
        // Map gateway IDs to API parameters
        $gateway_to_api_mapping = array(
            'peachpay_convesiopay_card' => 'card',
            'peachpay_convesiopay_applepay' => 'applePay',
			'peachpay_convesiopay_googlepay' => 'googlePay',
            'peachpay_convesiopay_btcpay' => 'btcPay'
        );
        
        if (!isset($gateway_to_api_mapping[$gateway_id])) {
            wp_send_json_error(array('message' => 'Unknown payment method'));
            return;
        }
        
        $api_param = $gateway_to_api_mapping[$gateway_id];
        
        // Determine API URL based on mode
        $api_url = peachpay_is_test_mode() ? 'https://api-qa.convesiopay.com' : 'https://api.convesiopay.com';
        $update_url = $api_url . '/v1/payment-methods';
        
        
        // Prepare request data - only update the specific method
        $update_data = array(
            $api_param => $enabled
        );
        
        
        // Make API request to ConvesioPay
        $response = wp_remote_request($update_url, array(
            'method' => 'PATCH',
            'timeout' => 30,
            'headers' => array(
                'Authorization' => $secret_key,
                'Content-Type' => 'application/json'
            ),
            'body' => json_encode($update_data)
        ));
        
        if (is_wp_error($response)) {
            wp_send_json_error(array('message' => 'Failed to update payment method: ' . $response->get_error_message()));
            return;
        }
        
        $response_code = wp_remote_retrieve_response_code($response);
        $response_body = wp_remote_retrieve_body($response);
        
        
        if ($response_code !== 200) {
            $error_data = json_decode($response_body, true);
            $error_message = $error_data['message'] ?? 'Unknown API error';
            wp_send_json_error(array('message' => 'Payment method update failed: ' . $error_message));
            return;
        }
        
        $api_response = json_decode($response_body, true);
        
        if (!$api_response || !isset($api_response['success']) || $api_response['success'] !== true) {
            wp_send_json_error(array('message' => 'Payment method update failed'));
            return;
        }
        
        
        // Now update the WooCommerce gateway setting
        $gateway_option_name = 'woocommerce_' . $gateway_id . '_settings';
        $gateway_settings = get_option($gateway_option_name, array());
        $gateway_settings['enabled'] = $enabled ? 'yes' : 'no';
        
        $settings_updated = update_option($gateway_option_name, $gateway_settings);
        
        wp_send_json_success(array(
            'message' => 'Payment method ' . ($enabled ? 'enabled' : 'disabled') . ' successfully',
            'gateway_id' => $gateway_id,
            'enabled' => $enabled
        ));
        
    } catch (Exception $e) {
        wp_send_json_error(array('message' => 'Failed to update payment method: ' . $e->getMessage()));
    }
}

/**
 * Create BTCPay session via ConvesioPay API
 */
function peachpay_convesiopay_create_btcpay_session() {
    
    // Verify nonce for security
    $nonce = $_POST['nonce'] ?? '';
    $nonce_verified = wp_verify_nonce($nonce, 'peachpay_convesiopay_nonce');
    
    
    if (!$nonce_verified) {
        wp_send_json_error(array('message' => 'Security check failed'));
        return;
    }

    // SERVER-SIDE SAFETY CHECK: if BTCPay is disabled in WooCommerce /
    // PeachPay settings, do not create sessions at all. Keep this before
    // request shaping or external API configuration so disabled BTCPay exits
    // as cheaply as possible.
    if ( ! PeachPay_ConvesioPay_Integration::is_btcpay_enabled() ) {
        wp_send_json_error( array( 'message' => 'BTCPay payment method is disabled' ) );
        return;
    }
    
    // Get request parameters
    $integration = sanitize_text_field($_POST['integration'] ?? '');
    $return_url = esc_url_raw($_POST['returnUrl'] ?? '');
    $order_number = sanitize_text_field($_POST['orderNumber'] ?? '');
    $amount = intval($_POST['amount'] ?? 0);
    $currency = sanitize_text_field($_POST['currency'] ?? 'USD');
    $email = sanitize_email($_POST['email'] ?? '');
    $name = sanitize_text_field($_POST['name'] ?? '');
    
    // For BTCPay blocks checkout, enhance order number with more context
    if (strpos($order_number, 'SESSION-BTCPAY-') === 0 || strpos($order_number, 'CART-') === 0) {
        // Try to get more context from WooCommerce session
        if (function_exists('WC') && WC()->session) {
            $session_id = WC()->session->get_customer_id();
            if ($session_id) {
                $order_number = 'WC-SESSION-' . $session_id . '-BTCPAY-' . time();
            }
        }
    }
    
    
    // Validate required parameters
    if (empty($integration) || empty($order_number) || $amount <= 0) {
        wp_send_json_error(array('message' => 'Missing required parameters'));
        return;
    }

    try {
        // Get ConvesioPay configuration
        $config = PeachPay_ConvesioPay_Integration::config();
        $secret_key = $config['secret_key'] ?? '';
        
        if (empty($secret_key)) {
            wp_send_json_error(array('message' => 'ConvesioPay configuration error'));
            return;
        }
        
        
        // Determine API URL based on mode
        $api_url = peachpay_is_test_mode() ? 'https://api-qa.convesiopay.com' : 'https://api.convesiopay.com';
        $create_session_url = $api_url . '/v1/create-session';
        
        
        // Prepare request data for ConvesioPay BTCPay session
        $session_data = array(
            'integration' => $integration,
            'paymentMethod' => 'btcPay',
            'amount' => $amount,
            'currency' => $currency,
            'orderNumber' => $order_number,
            'returnUrl' => $return_url,
            'customer' => array(
                'email' => $email,
                'name' => $name
            )
        );
        
        
        // Make API request to ConvesioPay
        $response = wp_remote_post($create_session_url, array(
            'method' => 'POST',
            'timeout' => 30,
            'headers' => array(
                'Authorization' => $secret_key,
                'Content-Type' => 'application/json'
            ),
            'body' => json_encode($session_data)
        ));
        if (is_wp_error($response)) {
            wp_send_json_error(array('message' => 'Failed to create BTCPay session: ' . $response->get_error_message()));
            return;
        }
        
        $response_code = wp_remote_retrieve_response_code($response);
        $response_body = wp_remote_retrieve_body($response);
        
        
        if ($response_code !== 200) {
            $error_data = json_decode($response_body, true);
            $error_message = $error_data['message'] ?? 'Unknown API error,(Check Test mode)';
            wp_send_json_error(array('message' => 'BTCPay session creation failed: ' . $error_message));
            return;
        }
        
        $api_response = json_decode($response_body, true);
        
        if (!$api_response || !isset($api_response['session'])) {
            wp_send_json_error(array('message' => 'BTCPay session creation failed'));
            return;
        }
        
        // Extract session ID from response (direct from response, not nested)
        $session_id = $api_response['session'];
        
        if (empty($session_id)) {
            wp_send_json_error(array('message' => 'Invalid session response'));
            return;
        }
        
        
        wp_send_json_success(array(
            'message' => 'BTCPay session created successfully',
            'session' => $session_id,
            'orderNumber' => $order_number,
            'amount' => $amount,
            'currency' => $currency
        ));
        
    } catch (Exception $e) {
        wp_send_json_error(array('message' => 'Failed to create BTCPay session: ' . $e->getMessage()));
    }
}

/**
 * Create BTCPay intent using existing session
 */
function peachpay_convesiopay_create_btcpay_intent() {
    
    // Verify nonce for security
    $nonce = $_POST['nonce'] ?? '';
    $nonce_verified = wp_verify_nonce($nonce, 'peachpay_convesiopay_nonce');
    
    
    if (!$nonce_verified) {
        wp_send_json_error(array('message' => 'Security check failed'));
        return;
    }
    
    // Get request parameters
    $session_id = sanitize_text_field($_POST['sessionId'] ?? '');
    
    
    // Validate required parameters
    if (empty($session_id)) {
        wp_send_json_error(array('message' => 'Session ID is required'));
        return;
    }

    // SERVER-SIDE SAFETY CHECK: if BTCPay is disabled, do not attempt to
    // create new intents.
    if ( ! PeachPay_ConvesioPay_Integration::is_btcpay_enabled() ) {
        wp_send_json_error( array( 'message' => 'BTCPay payment method is disabled' ) );
        return;
    }
    
    try {
        // Get ConvesioPay configuration
        $config = PeachPay_ConvesioPay_Integration::config();
        $secret_key = $config['secret_key'] ?? '';
        
        if (empty($secret_key)) {
            wp_send_json_error(array('message' => 'ConvesioPay configuration error'));
            return;
        }
        
        // Determine API URL based on mode
        $api_url = peachpay_is_test_mode() ? 'https://api-qa.convesiopay.com' : 'https://api.convesiopay.com';
        $create_intent_url = $api_url . '/v1/create-intent';
        
        
        // Prepare request data for ConvesioPay BTCPay intent
        $intent_data = array(
            'sessionId' => $session_id,
            'type' => 'btcPay'
        );
        
        
        // Make API request to ConvesioPay
        $response = wp_remote_post($create_intent_url, array(
            'method' => 'POST',
            'timeout' => 30,
            'headers' => array(
                'Authorization' => $secret_key,
                'Content-Type' => 'application/json'
            ),
            'body' => json_encode($intent_data)
        ));
        
        if (is_wp_error($response)) {
            wp_send_json_error(array('message' => 'Failed to create BTCPay intent: ' . $response->get_error_message()));
            return;
        }
        
        $response_code = wp_remote_retrieve_response_code($response);
        $response_body = wp_remote_retrieve_body($response);
        
        
        if ($response_code !== 200) {
            $error_data = json_decode($response_body, true);
            $error_message = $error_data['message'] ?? 'Unknown API error';
            wp_send_json_error(array('message' => 'BTCPay intent creation failed: ' . $error_message));
            return;
        }
        
        $api_response = json_decode($response_body, true);
        
        if (!$api_response || !isset($api_response['success']) || $api_response['success'] !== true) {
            wp_send_json_error(array('message' => 'BTCPay intent creation failed'));
            return;
        }
        
        // Extract intent data from response
        $intent_data = $api_response['data'] ?? array();
        $qr_code_data = $intent_data['qrCodeData'] ?? null;
        $payment_uri = $intent_data['paymentUri'] ?? null;
        $intent_id = $intent_data['intentId'] ?? null;
        
        
        wp_send_json_success(array(
            'message' => 'BTCPay intent created successfully',
            'intentId' => $intent_id,
            'qrCodeData' => $qr_code_data,
            'paymentUri' => $payment_uri,
            'sessionId' => $session_id
        ));
        
    } catch (Exception $e) {
        wp_send_json_error(array('message' => 'Failed to create BTCPay intent: ' . $e->getMessage()));
    }
}

/**
 * Check BTCPay payment status for auto-redirect
 */
function peachpay_convesiopay_check_btcpay_status() {
	
	// Get order ID from request
	$order_id = sanitize_text_field($_POST['order_id'] ?? '');
	
	if (empty($order_id) || !is_numeric($order_id)) {
		wp_send_json_error(array('message' => 'Invalid order ID'));
		return;
	}
	
	try {
		// Get WooCommerce order
		$order = wc_get_order($order_id);
		
		if (!$order) {
			wp_send_json_error(array('message' => 'Order not found'));
			return;
		}
		
		// Check if BTCPay payment is completed
		$is_completed = get_transient('convesiopay_btcpay_completed_' . $order_id);
		$order_status = $order->get_status();
		$btcpay_completed = $order->get_meta('_convesiopay_btcpay_completed');
		
		if ($is_completed === 'yes' || $btcpay_completed === 'yes' || in_array($order_status, array('processing', 'completed'))) {
			// Payment is completed, return success with redirect URL
			wp_send_json_success(array(
				'completed' => true,
				'redirect_url' => $order->get_checkout_order_received_url(),
				'order_status' => $order_status,
				'message' => 'Payment completed successfully'
			));
		} else {
			// Payment still pending
			wp_send_json_success(array(
				'completed' => false,
				'order_status' => $order_status,
				'message' => 'Payment pending'
			));
		}
		
	} catch (Exception $e) {
		wp_send_json_error(array('message' => 'Status check failed: ' . $e->getMessage()));
	}
}

/**
 * Update ConvesioPay checkout theme setting
 */
function peachpay_convesiopay_update_theme() {
	// Security checks
	if (!current_user_can('manage_woocommerce')) {
		wp_send_json_error(array('message' => 'Insufficient permissions'));
		return;
	}

	// Verify nonce for security
	$nonce = $_POST['nonce'] ?? '';
	if (!wp_verify_nonce($nonce, 'peachpay_convesiopay_update_theme')) {
		wp_send_json_error(array('message' => 'Security check failed'));
		return;
	}

	// Get theme parameter
	$theme = sanitize_text_field($_POST['theme'] ?? '');

	// Validate theme value
	if (empty($theme) || !in_array($theme, array('light', 'dark'))) {
		wp_send_json_error(array('message' => 'Invalid theme value'));
		return;
	}

	// Store theme in a separate option to avoid WooCommerce gateway settings sanitization
	// WooCommerce gateways only save keys defined in form_fields, and checkout_theme is commented out
	$theme_option_name = 'peachpay_convesiopay_checkout_theme';

	update_option($theme_option_name, $theme);

	// Clear any WooCommerce caches
	wp_cache_delete($theme_option_name, 'options');

	// Verify the setting was saved by reading it back
	$saved_theme = get_option($theme_option_name, 'light');

	// Check if update was successful
	if ($saved_theme === $theme) {
		wp_send_json_success(array(
			'message' => 'Checkout theme updated successfully',
			'theme' => $theme
		));
	} else {
		wp_send_json_error(array('message' => 'Failed to update checkout theme'));
	}
}

/**
 * Update ConvesioPay unified gateway label setting
 */
function peachpay_convesiopay_update_unified_label() {
	// Security checks
	if (!current_user_can('manage_woocommerce')) {
		wp_send_json_error(array('message' => 'Insufficient permissions'));
		return;
	}

	// Verify nonce for security
	$nonce = $_POST['nonce'] ?? '';
	if (!wp_verify_nonce($nonce, 'peachpay_convesiopay_update_unified_label')) {
		wp_send_json_error(array('message' => 'Security check failed'));
		return;
	}

	// Get label parameter
	$label = sanitize_text_field($_POST['label'] ?? '');

	// Validate label value - must not be empty
	if (empty($label)) {
		wp_send_json_error(array('message' => 'Label cannot be empty'));
		return;
	}

	// Limit label length to prevent abuse
	if (strlen($label) > 100) {
		wp_send_json_error(array('message' => 'Label is too long (max 100 characters)'));
		return;
	}

	// Store label in a separate option to avoid WooCommerce gateway settings sanitization
	$label_option_name = 'peachpay_convesiopay_unified_gateway_label';

	update_option($label_option_name, $label);

	// Clear any WooCommerce caches
	wp_cache_delete($label_option_name, 'options');

	// Verify the setting was saved by reading it back
	$saved_label = get_option($label_option_name, 'Credit Card');

	// Check if update was successful
	if ($saved_label === $label) {
		wp_send_json_success(array(
			'message' => 'Unified gateway label updated successfully',
			'label' => $label
		));
	} else {
		wp_send_json_error(array('message' => 'Failed to update unified gateway label'));
	}
}

/**
 * Update ConvesioPay card icons display setting
 */
function peachpay_convesiopay_update_card_icons() {
	// Security checks
	if (!current_user_can('manage_woocommerce')) {
		wp_send_json_error(array('message' => 'Insufficient permissions'));
		return;
	}

	// Verify nonce for security
	$nonce = $_POST['nonce'] ?? '';
	if (!wp_verify_nonce($nonce, 'peachpay_convesiopay_update_card_icons')) {
		wp_send_json_error(array('message' => 'Security check failed'));
		return;
	}

	// Get card_icons parameter (JSON string with individual card settings)
	$card_icons_json = isset($_POST['card_icons']) ? wp_unslash($_POST['card_icons']) : '';
	
	if (empty($card_icons_json)) {
		wp_send_json_error(array('message' => 'No card icons data provided'));
		return;
	}

	$card_icons = json_decode($card_icons_json, true);
	
	if (!is_array($card_icons)) {
		wp_send_json_error(array('message' => 'Invalid card icons data'));
		return;
	}

	// Sanitize and validate each card icon setting
	$valid_cards = array('visa', 'mastercard', 'amex', 'discover');
	$sanitized_icons = array();
	
	foreach ($valid_cards as $card) {
		$value = isset($card_icons[$card]) ? sanitize_text_field($card_icons[$card]) : 'no';
		// Ensure value is 'yes' or 'no'
		$sanitized_icons[$card] = ($value === 'yes') ? 'yes' : 'no';
	}

	// Store settings in option
	$option_name = 'peachpay_convesiopay_card_icons';
	update_option($option_name, $sanitized_icons);

	// Also update the legacy show_card_icons option for backward compatibility
	// Set to 'yes' if any card is enabled, 'no' if all disabled
	$any_enabled = in_array('yes', $sanitized_icons, true);
	update_option('peachpay_convesiopay_show_card_icons', $any_enabled ? 'yes' : 'no');

	// Clear any WooCommerce caches
	wp_cache_delete($option_name, 'options');
	wp_cache_delete('peachpay_convesiopay_show_card_icons', 'options');

	// Verify the setting was saved by reading it back
	$saved_value = get_option($option_name, array());

	// Check if update was successful
	if ($saved_value === $sanitized_icons) {
		wp_send_json_success(array(
			'message' => 'Card icons updated successfully',
			'card_icons' => $sanitized_icons
		));
	} else {
		wp_send_json_error(array('message' => 'Failed to update card icons setting'));
	}
}

/**
 * Update ConvesioPay order list logo visibility (show/hide logo next to customer name in order list).
 */
function peachpay_convesiopay_update_order_list_logo() {
	if ( ! current_user_can( 'manage_woocommerce' ) ) {
		wp_send_json_error( array( 'message' => __( 'Insufficient permissions', 'peachpay-for-woocommerce' ) ) );
		return;
	}

	$nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
	if ( ! wp_verify_nonce( $nonce, 'peachpay_convesiopay_update_order_list_logo' ) ) {
		wp_send_json_error( array( 'message' => __( 'Security check failed', 'peachpay-for-woocommerce' ) ) );
		return;
	}

	$show = isset( $_POST['show'] ) ? sanitize_text_field( wp_unslash( $_POST['show'] ) ) : '';
	$value = ( $show === 'yes' ) ? 'yes' : 'no';

	$option_name = 'peachpay_convesiopay_show_order_list_logo';
	update_option( $option_name, $value );
	wp_cache_delete( $option_name, 'options' );

	$saved = get_option( $option_name, 'yes' );
	if ( $saved === $value ) {
		wp_send_json_success( array(
			'message' => __( 'Order list logo setting updated.', 'peachpay-for-woocommerce' ),
			'show'    => $value,
		) );
	} else {
		wp_send_json_error( array( 'message' => __( 'Failed to update setting.', 'peachpay-for-woocommerce' ) ) );
	}
}

/**
 * Update ConvesioPay accelerated checkout settings.
 */
function peachpay_convesiopay_update_accelerated_checkout_settings() {
	if ( ! current_user_can( 'manage_woocommerce' ) ) {
		wp_send_json_error( array( 'message' => __( 'Insufficient permissions', 'peachpay-for-woocommerce' ) ) );
		return;
	}

	$nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
	if ( ! wp_verify_nonce( $nonce, 'peachpay_convesiopay_update_accelerated_checkout_settings' ) ) {
		wp_send_json_error( array( 'message' => __( 'Security check failed', 'peachpay-for-woocommerce' ) ) );
		return;
	}

	$default_settings = array(
		'applepay_enabled' => 'yes',
		'googlepay_enabled' => 'yes',
		'checkout_enabled' => 'yes',
		'cart_enabled'    => 'no',
		'product_enabled' => 'no',
	);

	$raw_settings = isset( $_POST['settings'] ) ? wp_unslash( $_POST['settings'] ) : '';
	if ( empty( $raw_settings ) ) {
		wp_send_json_error( array( 'message' => __( 'No settings payload provided', 'peachpay-for-woocommerce' ) ) );
		return;
	}

	$decoded_settings = json_decode( $raw_settings, true );
	if ( ! is_array( $decoded_settings ) ) {
		wp_send_json_error( array( 'message' => __( 'Invalid settings payload', 'peachpay-for-woocommerce' ) ) );
		return;
	}

	$yes_no_keys = array(
		'applepay_enabled',
		'googlepay_enabled',
		'checkout_enabled',
		'cart_enabled',
		'product_enabled',
	);

	$sanitized_settings = $default_settings;
	foreach ( $yes_no_keys as $key ) {
		$value = isset( $decoded_settings[ $key ] ) ? sanitize_text_field( (string) $decoded_settings[ $key ] ) : $default_settings[ $key ];
		$sanitized_settings[ $key ] = ( 'yes' === $value ) ? 'yes' : 'no';
	}

	$option_name = 'peachpay_convesiopay_accelerated_checkout_settings';
	update_option( $option_name, $sanitized_settings );
	wp_cache_delete( $option_name, 'options' );

	$saved_settings = get_option( $option_name, array() );
	if ( $saved_settings === $sanitized_settings ) {
		wp_send_json_success(
			array(
				'message'  => __( 'Accelerated checkout settings updated.', 'peachpay-for-woocommerce' ),
				'settings' => $saved_settings,
			)
		);
		return;
	}

	wp_send_json_error( array( 'message' => __( 'Failed to update settings.', 'peachpay-for-woocommerce' ) ) );
}
