<?php
/**
 * Authorize.net Gateway Tokenization Credit Card Class
 *
 * Handles Credit Card Tokenization API payments through Authorize.net gateway for WooCommerce.
 *
 * @package    Authorize_Net_Payments_For_Woocommerce
 * @subpackage Authorize_Net_Payments_For_Woocommerce/includes
 * @since      1.0.0
 */
 
if (! defined('ABSPATH')) {
    exit;
}

use net\authorize\api\contract\v1 as AnetAPI;
use net\authorize\api\controller as AnetController;

require_once plugin_dir_path(__FILE__) . '../../trait-anet-customer-profile.php';
require_once plugin_dir_path(__FILE__) . '../../trait-anet-order-meta.php';
/**
 * Authorize.net Credit Card Tokenization Class
 *
 * Handles customer profile and payment profile creation, management, and tokenization
 * for credit card payments through the Authorize.net API. This class provides
 * functionality for storing and managing customer payment methods securely.
 *
 * @since 1.0.0
 * @package AuthorizeNetGateway
 */
class Anet_Credit_Card_Tokenization
{
    use Anet_Customer_Profile;
    use Anet_Order_Meta;
    /**
     * Meta key for storing Authorize.net customer profile ID
     *
     * @var mixed
     */
    private $meta_key;
    /**
     * Helper for API request 
     *
     * @var mixed
     */
    private $helper;
    /**
     * Initialize the tokenization class.
     *
     * Sets up the meta key for storing customer profile information.
     * Sets up the helper for request.
     * 
     * @since 1.0.0
     */
    public function __construct()
    {
        $this->meta_key = $this->get_customer_profile_meta_key(false);
        $this->helper = new Anet_Api_Helper(ANET_PAYMENT_TYPE_CREDIT_CARD);
    }
    /**
     * Create a customer profile for My Account Section.
     *
     * @since 1.0.0
     * 
     * @param int   $user_id User ID.
     * @param array $payment_args Payment arguments.
     * 
     * @return array Result array with status and details.
     */
    public function create_customer_profile($user_id, $payment_args)
    {
        try {
            $customer_profile_id = get_user_meta($user_id, $this->meta_key, true);
            if ($customer_profile_id) {
                // Customer profile exists, just create payment profile.
                return $this->create_customer_payment_profile($customer_profile_id, $user_id, $payment_args);
            }
            $merchant_auth = $this->helper->merchant_authentication_request();
            $customer_profile = $this->helper->create_customer_profile_request($user_id, $payment_args);
            $validation_mode = $this->helper->validation_mode();
            $request = new AnetAPI\CreateCustomerProfileRequest();
            $request->setMerchantAuthentication($merchant_auth);
            $request->setProfile($customer_profile);
            $request->setValidationMode($validation_mode);
            $sanitized_request = Anet_Api_Helper::mask_tokenization_request($request); // Call the mask_tokenization_request function.
            Anet_Setting_Helper::log("\ncreateCustomerProfileRequest:\n" . $sanitized_request, ANET_PAYMENT_TYPE_CREDIT_CARD, 'debug');
            $controller = new AnetController\CreateCustomerProfileController($request);
            $response = $controller->executeWithApiResponse($this->helper->controller_response());
            $customer_profile_id = $response->getCustomerProfileId();
            $payment_profile_id_list = $response->getCustomerPaymentProfileIdList();
            $validation_direct_response_list = $response->getValidationDirectResponseList();
            Anet_Setting_Helper::log(
                "\ncreateCustomerProfileResponse:\n" .
                    wp_json_encode([
                        'customerProfileId' => $customer_profile_id,
                        'customerPaymentProfileIdList' => $payment_profile_id_list,
                        'validationDirectResponseList' => $validation_direct_response_list,
                        'messages' => $response->getMessages(),
                    ], JSON_PRETTY_PRINT),
                ANET_PAYMENT_TYPE_CREDIT_CARD, 'debug'
            );
            if (ANET_SANDBOX_STATUS_AUTHORIZED === $response->getMessages()->getResultCode() && null !== $response) {
                $customer_profile_id = $response->getCustomerProfileId();
                $payment_profile_id = $response->getCustomerPaymentProfileIdList()[0];
                update_user_meta($user_id, $this->meta_key, $customer_profile_id);
                $payment_profile_result = $this->get_customer_payment_profile($user_id, $payment_profile_id, true);
                if ($payment_profile_result['result']) {
                    return [
                        'result' => true,
                        'customerProfileId' => $customer_profile_id,
                        'customerPaymentProfileId' => $payment_profile_id
                    ];
                }
            }
            return [
                'result' => false,
            ];
        } catch (Throwable $e) {
            Anet_Setting_Helper::log("\nException:\n" . $e->getMessage(), ANET_PAYMENT_TYPE_CREDIT_CARD, 'error');
            return [
                'result' => false,
            ];
        }
    }
    /**
     * Create a customer payment profile for My Account Section.
     *
     * @since 1.0.0
     * 
     * @param string $customer_profile_id Customer profile ID.
     * @param int    $user_id User ID.
     * @param array  $payment_args Payment arguments.
     * 
     * @return array Result array with status and details.
     */
    public function create_customer_payment_profile($customer_profile_id, $user_id, $payment_args)
    {
        try {
            $merchant_auth = $this->helper->merchant_authentication_request();
            $payment_profile = $this->helper->create_customer_payment_profile_request($payment_args);
            $validation_mode = $this->helper->validation_mode();
            $request = new AnetAPI\CreateCustomerPaymentProfileRequest();
            $request->setMerchantAuthentication($merchant_auth);
            $request->setCustomerProfileId($customer_profile_id);
            $request->setPaymentProfile($payment_profile);
            $request->setValidationMode($validation_mode);
            $sanitized_request = Anet_Api_Helper::mask_tokenization_request($request); // Call the mask_tokenization_request function.
            Anet_Setting_Helper::log("\ncreateCustomerPaymentProfileRequest:\n" . $sanitized_request, ANET_PAYMENT_TYPE_CREDIT_CARD, 'debug');
            $controller = new AnetController\CreateCustomerPaymentProfileController($request);
            $response = $controller->executeWithApiResponse($this->helper->controller_response());
            $customer_profile_id = $response->getCustomerProfileId();
            $customer_payment_profile_id = $response->getCustomerPaymentProfileId();
            $validation_direct_response = $response->getValidationDirectResponse();
            Anet_Setting_Helper::log(
                "\ncreateCustomerPaymentProfileResponse:\n" .
                    wp_json_encode([
                        'customerProfileId' => $customer_profile_id,
                        'customerPaymentProfileId' => $customer_payment_profile_id,
                        'validationDirectResponse' => $validation_direct_response,
                        'messages' => $response->getMessages(),
                    ], JSON_PRETTY_PRINT),
                ANET_PAYMENT_TYPE_CREDIT_CARD, 'debug'
            );
            if (ANET_SANDBOX_STATUS_AUTHORIZED === $response->getMessages()->getResultCode() && null !== $response) {
                $payment_profile_id = $response->getCustomerPaymentProfileId();
                $payment_profile_result = $this->get_customer_payment_profile($user_id, $payment_profile_id, true);
                // If more than one token, do NOT change default.
                if ($payment_profile_result['result']) {
                    return [
                        'result' => true,
                        'customerProfileId' => $customer_profile_id,
                        'customerPaymentProfileId' => $payment_profile_id
                    ];
                }
            }
            return [
                'result' => false,
            ];
        } catch (Throwable $e) {
            Anet_Setting_Helper::log("\nException:\n" . $e->getMessage(), ANET_PAYMENT_TYPE_CREDIT_CARD, 'error');
            return [
                'result' => false,
            ];
        }
    }
    /**
     * Get customer payment profile information.
     *
     * @since 1.0.0
     *
     * @param int    $user_id User ID.
     * @param string $customer_payment_profile_id Customer payment profile ID.
     * @param bool   $store_card_details Whether to store card details. Default false.
     * 
     * @return array Payment profile data or empty array if not found.
     */
    public function get_customer_payment_profile($user_id, $customer_payment_profile_id, $store_card_details = false)
    {
        try {
            $customer_profile_id = get_user_meta($user_id, $this->meta_key, true);
            if (!$customer_profile_id) {
                return [];
            }
            $merchant_auth = $this->helper->merchant_authentication_request();
            $request = new AnetAPI\GetCustomerPaymentProfileRequest();
            $request->setMerchantAuthentication($merchant_auth);
            $request->setCustomerProfileId($customer_profile_id);
            $request->setCustomerPaymentProfileId($customer_payment_profile_id);
            // Only set if your SDK version supports it.
            if (method_exists($request, 'setIncludeIssuerInfo')) {
                $request->setIncludeIssuerInfo(true);
            }
            $controller = new AnetController\GetCustomerPaymentProfileController($request);
            $response = $controller->executeWithApiResponse($this->helper->controller_response());
            if (ANET_SANDBOX_STATUS_AUTHORIZED === $response->getMessages()->getResultCode() && null !== $response) {
                $payment_profile = $response->getPaymentProfile();
                $credit_card = $payment_profile->getPayment()->getCreditCard();
                if ($store_card_details) {
                    $this->store_card_details($user_id, $customer_payment_profile_id,  $response->getPaymentProfile());
                }
                $issuer_info = method_exists($response, 'getIssuerInfo') ? $response->getIssuerInfo() : null;
                return [
                    'result' => true,
                    'card_number' => $credit_card->getCardNumber(),
                    'expiration_date' => $credit_card->getExpirationDate(),
                    'card_type' => $credit_card->getCardType(),
                ];
            }
            return [
                'result' => false,
            ];
        } catch (Throwable $e) {
            Anet_Setting_Helper::log("\nException:\n" . $e->getMessage(), ANET_PAYMENT_TYPE_CREDIT_CARD, 'error');
            return [
                'result' => false,
            ];
        }
    }
    /**
     * Storing a card through checkout page.
     *
     * @since 1.0.0
     * 
     * @param string   $customer_profile_id Customer profile ID.
     * @param string   $transaction_id Transaction ID.
     * @param int|null $user_id User ID (optional).
     * 
     * @return array Result array with status and details.
     */
    public function create_customer_payment_profile_from_transaction($customer_profile_id, $transaction_id, $user_id = null)
    {
        try {
            $merchant_auth = $this->helper->merchant_authentication_request();
            $request = new AnetAPI\CreateCustomerProfileFromTransactionRequest();
            $request->setMerchantAuthentication($merchant_auth);
            if ($customer_profile_id) {
                $request->setCustomerProfileId($customer_profile_id);
            }
            $request->setTransId($transaction_id);
            $sanitized_request = Anet_Api_Helper::mask_tokenization_request($request); // Call the mask_tokenization_request function.
            Anet_Setting_Helper::log("\ncreateCustomerProfileFromTransactionRequest:\n" . $sanitized_request, ANET_PAYMENT_TYPE_CREDIT_CARD, 'debug');
            $controller = new AnetController\CreateCustomerProfileFromTransactionController($request);
            $response = $controller->executeWithApiResponse($this->helper->controller_response());
            // Log the response.
            Anet_Setting_Helper::log(
                "\ncreateCustomerProfileFromTransactionResponse:\n" .
                    wp_json_encode([
                        'customerProfileId' => $response->getCustomerProfileId(),
                        'customerPaymentProfileIdList' => $response->getCustomerPaymentProfileIdList(),
                        'customerShippingAddressIdList' => $response->getCustomerShippingAddressIdList(),
                        'validationDirectResponseList' => $response->getValidationDirectResponseList(),
                        'messages' => $response->getMessages(),
                    ], JSON_PRETTY_PRINT),
                ANET_PAYMENT_TYPE_CREDIT_CARD, 'debug'
            );
            if (ANET_SANDBOX_STATUS_AUTHORIZED === $response->getMessages()->getResultCode() && null !== $response) {
                $customer_profile_id = $response->getCustomerProfileId();
                $payment_profile_id_list = $response->getCustomerPaymentProfileIdList();
                update_user_meta($user_id, $this->meta_key, $customer_profile_id);
                $payment_profile_result = $this->get_customer_payment_profile($user_id, end($payment_profile_id_list), true);
                if ($payment_profile_result['result']) {
                    return [
                        'result' => true,
                        'customerProfileId' => $customer_profile_id,
                        'customerPaymentProfileId' => end($payment_profile_id_list)
                    ];
                }
            }
            return [
                'result' => false,
            ];
        } catch (Throwable $e) {
            Anet_Setting_Helper::log("\nException:\n" . $e->getMessage(), ANET_PAYMENT_TYPE_CREDIT_CARD, 'error');
            return [
                'result' => false,
            ];
        }
    }
    /**
     * Process a stored card transaction.
     *
     * @since 1.0.0
     *
     * @param WC_Order $wc_order WooCommerce order object.
     * @param array    $payment_args Payment arguments.
     * @param bool     $merchant_initiated Whether transaction is merchant initiated. Default false.
     * 
     * @return array Transaction result array.
     */
    public function stored_card($wc_order, $payment_args = array(), $merchant_initiated = false)
    {
        try {
            // Set up merchant authentication.
            $merchant_auth = $this->helper->merchant_authentication_request();
            $transaction_request = $this->helper->stored_card_request($payment_args);
            $processing_options = new AnetAPI\ProcessingOptionsType();
            $anet_subscription = new Anet_Subscriptions();
            if ($anet_subscription->is_subscription_active) {
                if ((wcs_order_contains_subscription($wc_order) || wcs_order_contains_renewal($wc_order)) &&  empty($this->get_order_meta($wc_order, 'anet_subscription_token')) && !$merchant_initiated) { // CIT.
                    // Subscription is first recurring payment.
                    $processing_options->setIsFirstRecurringPayment(true);
                    $transaction_request->setProcessingOptions($processing_options);
                } else if ((wcs_order_contains_renewal($wc_order) || wcs_order_contains_early_renewal($wc_order)) &&  !empty($this->get_order_meta($wc_order, 'anet_subscription_token'))) { // MIT or early renewal.
                    $processing_options->setIsSubsequentAuth(true);
                    $transaction_request->setProcessingOptions($processing_options);
                }
                if ((wcs_order_contains_subscription($wc_order) || wcs_order_contains_renewal($wc_order) || wcs_order_contains_early_renewal($wc_order)) && !$merchant_initiated) { // CIT.
                    $processing_options->setIsStoredCredentials(true);
                    $transaction_request->setProcessingOptions($processing_options);
                }
            }
            // Create the transaction request.
            $request = new AnetAPI\CreateTransactionRequest();
            $request->setMerchantAuthentication($merchant_auth);
            $request->setTransactionRequest($transaction_request);
            // Set the refId.
            if (isset($payment_args['refId'])) {
                $request->setRefId($payment_args['refId']);
            }
            // Log the request with masked data.
            $sanitized_request = Anet_Api_Helper::mask_sensitive_data($request); // Call the mask_sensitive_data function.
            Anet_Setting_Helper::log("\ncreateTransactionRequest:\n" . $sanitized_request, ANET_PAYMENT_TYPE_CREDIT_CARD, 'debug');
            // Execute the request.
            $controller = new AnetController\CreateTransactionController($request);
            $response = $controller->executeWithApiResponse($this->helper->controller_response());
            return Anet_Credit_Card_Api::process_response($response);
        } catch (Throwable $e) {
            Anet_Setting_Helper::log("\nException:\n" . $e->getMessage(), ANET_PAYMENT_TYPE_CREDIT_CARD, 'error');
            return array("success" => false);
        }
    }
    /**
     * Update customer payment profile with new card details.
     *
     * @since 1.0.0
     *
     * @param int    $user_id User ID.
     * @param string $customer_profile_id Customer profile ID.
     * @param string $customer_payment_profile_id Customer payment profile ID.
     * @param string $new_expiry_month New expiry month.
     * @param string $new_expiry_year New expiry year.
     * @param string $new_card_number New card number.
     * 
     * @return array Result array with success status and details.
     */
    public function update_customer_payment_profile($user_id, $customer_profile_id, $customer_payment_profile_id, $new_expiry_month, $new_expiry_year, $new_card_number)
    {
        try {
            // Validate expiry input.
            $new_expiry_month = str_pad(preg_replace('/\D/', '', $new_expiry_month), 2, '0', STR_PAD_LEFT);
            $new_expiry_year = preg_replace('/\D/', '', $new_expiry_year);
            // If $card_number is not passed as an argument, try to get it from $_POST (for backward compatibility).
            if (empty($card_number) && !empty($_POST['card_number'])) {
                // Verify nonce before accessing $_POST data.
                if (isset($_POST['anet_edit_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['anet_edit_nonce'])), 'anet_edit_nonce')) {
                    $new_card_number = sanitize_text_field(wp_unslash($_POST['card_number']));
                } else {
                    return array('result' => false, 'message' => __('Security verification failed.', 'authorize-net-payments-for-woocommerce'));
                }
            }
            // 1. Fetch the current payment profile.
            $merchant_auth = $this->helper->merchant_authentication_request();
            $get_request = new AnetAPI\GetCustomerPaymentProfileRequest();
            $get_request->setMerchantAuthentication($merchant_auth);
            $get_request->setCustomerProfileId($customer_profile_id);
            $get_request->setCustomerPaymentProfileId($customer_payment_profile_id);
            $get_controller = new AnetController\GetCustomerPaymentProfileController($get_request);
            $get_response = $get_controller->executeWithApiResponse($this->helper->controller_response());
            if (ANET_SANDBOX_STATUS_AUTHORIZED !== $get_response->getMessages()->getResultCode() || !$get_response) {
                return [
                    'result' => false,
                    'message' => __('Could not fetch current payment profile.', 'authorize-net-payments-for-woocommerce')
                ];
            }
            $current_profile = $get_response->getPaymentProfile();
            // 2. Update only the expiry date in the credit card info.
            $credit_card = new AnetAPI\CreditCardType();
            if ($new_card_number) {
                $credit_card->setCardNumber($new_card_number);
            } else {
                // Handle error: card number is required for update.
                return [
                    'result' => false,
                    'message' => __('Card number is required to update the payment profile.', 'authorize-net-payments-for-woocommerce')
                ];
            }
            $expiration_date = $new_expiry_year . ANET_HYPHEN . str_pad($new_expiry_month, 2, '0', STR_PAD_LEFT);
            $credit_card->setExpirationDate($expiration_date);
            $payment = new AnetAPI\PaymentType();
            $payment->setCreditCard($credit_card);
            // 3. Build the updated payment profile object.
            $updated_profile = new AnetAPI\CustomerPaymentProfileExType();
            $updated_profile->setCustomerPaymentProfileId($customer_payment_profile_id);
            $updated_profile->setPayment($payment);
            // Copy billing address if present.
            if ($current_profile->getBillTo()) {
                $updated_profile->setBillTo($current_profile->getBillTo());
            }
            $validation_mode = $this->helper->validation_mode();
            // 4. Send the update request.
            $request = new AnetAPI\UpdateCustomerPaymentProfileRequest();
            $request->setMerchantAuthentication($merchant_auth);
            $request->setCustomerProfileId($customer_profile_id);
            $request->setPaymentProfile($updated_profile);
            $request->setValidationMode($validation_mode);
            $sanitized_request = Anet_Api_Helper::mask_tokenization_request($request); // Call the mask_tokenization_request function.
            Anet_Setting_Helper::log("\nupdateCustomerPaymentProfileRequest:\n" . $sanitized_request, ANET_PAYMENT_TYPE_CREDIT_CARD, 'debug');
            $controller = new AnetController\UpdateCustomerPaymentProfileController($request);
            $response = $controller->executeWithApiResponse($this->helper->controller_response());
            // Log the response.
            Anet_Setting_Helper::log(
                "\nupdateCustomerPaymentProfileResponse:\n" .
                    wp_json_encode([
                        'validationDirectResponse' => $response->getValidationDirectResponse(),
                        'messages' => $response->getMessages(),
                    ], JSON_PRETTY_PRINT),
                ANET_PAYMENT_TYPE_CREDIT_CARD, 'debug'
            );
            $validation_mode_string = $this->helper->validation_mode();
            if (ANET_SANDBOX_STATUS_AUTHORIZED === $response->getMessages()->getResultCode() && $response) {
                // Optionally validate the updated profile.
                $validate_request = new AnetAPI\ValidateCustomerPaymentProfileRequest();
                $validate_request->setMerchantAuthentication($merchant_auth);
                $validate_request->setCustomerProfileId($customer_profile_id);
                $validate_request->setCustomerPaymentProfileId($customer_payment_profile_id);
                $validate_request->setValidationMode($validation_mode_string);
                $validate_controller = new AnetController\ValidateCustomerPaymentProfileController($validate_request);
                $validate_response = $validate_controller->executeWithApiResponse($this->helper->controller_response());
                if (ANET_SANDBOX_STATUS_AUTHORIZED === $validate_response->getMessages()->getResultCode() && $validate_response) {
                    return [
                        'result' => true,
                        'message' => __('Payment method successfully updated.', 'authorize-net-payments-for-woocommerce')
                    ];
                }
            }
            return [
                'result' => false,
                'message' => __('Payment method update failed. Please try again.', 'authorize-net-payments-for-woocommerce') . $response->getMessages()->getMessage()[0]->getText()
            ];
        } catch (Throwable $e) {
            Anet_Setting_Helper::log("\nException:\n" . $e->getMessage(), ANET_PAYMENT_TYPE_CREDIT_CARD, 'error');
            return [
                'result' => false,
                'message' => __('Payment method update failed. Please try again.', 'authorize-net-payments-for-woocommerce') . $response->getMessages()->getMessage()[0]->getText()
            ];
        }
    }
    /**
     * Set a payment profile as the default for a customer.
     *
     * @since 1.0.0
     *
     * @param int         $user_id User ID.
     * @param string      $customer_profile_id Customer profile ID.
     * @param string      $customer_payment_profile_id Customer payment profile ID.
     * @param string|null $card_number Card number. Optional.
     * @param string|null $expiration_date Expiration date. Optional.
     * 
     * @return array|bool Result of setting default payment profile.
     */
    public function set_default_payment_profile($user_id, $customer_profile_id, $customer_payment_profile_id, $card_number = null, $expiration_date = null)
    {
        try {
            $merchant_auth = $this->helper->merchant_authentication_request();
            $payment_profile = new AnetAPI\CustomerPaymentProfileExType();
            $payment_profile->setCustomerPaymentProfileId($customer_payment_profile_id);
            $payment_profile->setDefaultPaymentProfile(true);
            if ($card_number && $expiration_date) {
                $credit_card = new AnetAPI\CreditCardType();
                $credit_card->setCardNumber($card_number);
                $credit_card->setExpirationDate($expiration_date);
                $payment = new AnetAPI\PaymentType();
                $payment->setCreditCard($credit_card);
                $payment_profile->setPayment($payment);
            }
            $validation_mode = $this->helper->validation_mode();
            $request = new AnetAPI\UpdateCustomerPaymentProfileRequest();
            $request->setMerchantAuthentication($merchant_auth);
            $request->setCustomerProfileId($customer_profile_id);
            $request->setPaymentProfile($payment_profile);
            $request->setValidationMode($validation_mode);
            $sanitized_request = Anet_Api_Helper::mask_tokenization_request($request); // Call the mask_tokenization_request function.
            Anet_Setting_Helper::log("\nsetDefaultPaymentProfileRequest:\n" . $sanitized_request, ANET_PAYMENT_TYPE_CREDIT_CARD, 'debug');
            $controller = new AnetController\UpdateCustomerPaymentProfileController($request);
            $response = $controller->executeWithApiResponse($this->helper->controller_response());
            // Log the response.
            Anet_Setting_Helper::log(
                "\nsetDefaultPaymentProfileResponse:\n" .
                    wp_json_encode([
                        'validationDirectResponse' => $response->getValidationDirectResponse(),
                        'messages' => $response->getMessages(),
                    ], JSON_PRETTY_PRINT),
                ANET_PAYMENT_TYPE_CREDIT_CARD, 'debug'
            );
            if (ANET_SANDBOX_STATUS_AUTHORIZED === $response->getMessages()->getResultCode() && $response) {
                return [
                    'result' => true,
                ];
            }
            return [
                'result' => false,
            ];
        } catch (Throwable $e) {
            Anet_Setting_Helper::log("\nException:\n" . $e->getMessage(), ANET_PAYMENT_TYPE_CREDIT_CARD, 'error');
            return [
                'result' => false,
            ];
        }
    }
    /**
     * Delete a customer profile from Authorize.net.
     *
     * @since 1.0.0
     *
     * @param int    $user_id User ID.
     * @param string $customer_profile_id Customer profile ID.
     * 
     * @return bool True on success, false on failure.
     */
    public function delete_customer_profile($user_id, $customer_profile_id)
    {
        if (!$customer_profile_id) {
            return false;
        }
        try {
            $merchant_auth = $this->helper->merchant_authentication_request();
            $request = new AnetAPI\DeleteCustomerProfileRequest();
            $request->setMerchantAuthentication($merchant_auth);
            $request->setCustomerProfileId($customer_profile_id);
            $sanitized_request = Anet_Api_Helper::mask_tokenization_request($request); // Call the mask_tokenization_request function.
            Anet_Setting_Helper::log("\ndeleteCustomerProfileRequest:\n" . $sanitized_request, ANET_PAYMENT_TYPE_CREDIT_CARD, 'debug');
            $controller = new AnetController\DeleteCustomerProfileController($request);
            $response = $controller->executeWithApiResponse($this->helper->controller_response());
            Anet_Setting_Helper::log("\ndeleteCustomerProfileResponse:\n" . wp_json_encode($response, JSON_PRETTY_PRINT), ANET_PAYMENT_TYPE_CREDIT_CARD, 'debug');
            if (ANET_SANDBOX_STATUS_AUTHORIZED === $response->getMessages()->getResultCode() && null !== $response) {
                delete_user_meta($user_id, $this->meta_key);
                return true;
            }
            return false;
        } catch (Throwable $e) {
            Anet_Setting_Helper::log("\nException:\n" . $e->getMessage(), ANET_PAYMENT_TYPE_CREDIT_CARD, 'error');
            return false;
        }
    }
    /**
     * Delete a customer payment profile from Authorize.net.
     *
     * @since 1.0.0
     *
     * @param int    $user_id User ID.
     * @param string $customer_profile_id Customer profile ID.
     * @param string $customer_payment_profile_id Customer payment profile ID.
     * 
     * @return bool True on success, false on failure.
     */
    public function delete_customer_payment_profile($user_id, $customer_profile_id, $customer_payment_profile_id)
    {
        if (!$customer_profile_id || !$customer_payment_profile_id) {
            return false;
        }
        try {
            $merchant_auth = $this->helper->merchant_authentication_request();
            $request = new AnetAPI\DeleteCustomerPaymentProfileRequest();
            $request->setMerchantAuthentication($merchant_auth);
            $request->setCustomerProfileId($customer_profile_id);
            $request->setCustomerPaymentProfileId($customer_payment_profile_id);
            $sanitized_request = Anet_Api_Helper::mask_tokenization_request($request); // Call the mask_tokenization_request function.
            Anet_Setting_Helper::log("\ndeleteCustomerPaymentProfileRequest:\n" . $sanitized_request, ANET_PAYMENT_TYPE_CREDIT_CARD, 'debug');
            $controller = new AnetController\DeleteCustomerPaymentProfileController($request);
            $response = $controller->executeWithApiResponse($this->helper->controller_response());
            Anet_Setting_Helper::log("\ndeleteCustomerPaymentProfileResponse:\n" . wp_json_encode($response, JSON_PRETTY_PRINT), ANET_PAYMENT_TYPE_CREDIT_CARD, 'debug');
            if (ANET_SANDBOX_STATUS_AUTHORIZED === $response->getMessages()->getResultCode() && null !== $response) {
                // Optionally, delete the WooCommerce payment token for this card.
                $tokens = WC_Payment_Tokens::get_customer_tokens($user_id, ANET_CREDIT_CARD_GATEWAY_ID);
                foreach ($tokens as $token) {
                    $token_data = $token->get_meta('token_information');
                    if (!empty($token_data['payment_profile_id']) && $token_data['payment_profile_id'] === $customer_payment_profile_id) {
                        return true;
                    }
                }
            }
            return false;
        } catch (Throwable $e) {
            Anet_Setting_Helper::log("\nException:\n" . $e->getMessage(), ANET_PAYMENT_TYPE_CREDIT_CARD, 'error');
            return false;
        }
    }
    /**
     * Delete customer profile or payment profile.
     *
     * @since 1.0.0
     *
     * @param int         $user_id User ID.
     * @param string      $customer_profile_id Customer profile ID.
     * @param string|null $customer_payment_profile_id Customer payment profile ID. Optional.
     * 
     * @return bool|array Result of deletion operation.
     */
    public function delete_profile($user_id, $customer_profile_id, $customer_payment_profile_id = null)
    {
        $customer_tokens = "_anet_customer_profile_id_creditcard" === $this->meta_key ? WC_Payment_Tokens::get_tokens(['user_id' => $user_id, 'gateway_id' => "anet"]) : array_merge(WC_Payment_Tokens::get_tokens(['user_id' => $user_id, 'gateway_id' => "anet"]), WC_Payment_Tokens::get_tokens(['user_id' => $user_id, 'gateway_id' => "anet_echeck"]));
        if (count($customer_tokens) <= 1 || !$customer_payment_profile_id) {
            return $this->delete_customer_profile($user_id, $customer_profile_id);
        } else {
            // Delete only the specified payment profile.
            return $this->delete_customer_payment_profile($user_id, $customer_profile_id, $customer_payment_profile_id);
        }
    }
    /**
     * Store card details for a customer.
     *
     * @since 1.0.0
     *
     * @param int    $user_id User ID.
     * @param string $payment_profile_id Payment profile ID.
     * @param mixed  $card_data Card data.
     * 
     * @return void
     */
    public function store_card_details($user_id, $payment_profile_id, $card_data)
    {
        // Try to find an existing token for this user and payment profile.
        $existing_tokens = WC_Payment_Tokens::get_customer_tokens($user_id, ANET_CREDIT_CARD_GATEWAY_ID);
        $token_obj = null;
        foreach ($existing_tokens as $token) {
            $token_info = $token->get_meta('token_information');
            if (
                !empty($token_info['payment_profile_id']) &&
                $token_info['payment_profile_id'] === $payment_profile_id
            ) {
                $token_obj = $token;
                break;
            }
        }
        // If not found, create a new token.
        if (!$token_obj) {
            $token_obj = new \WC_Payment_Token_CC();
            $token_obj->set_token($payment_profile_id);
            $token_obj->set_user_id($user_id);
            $token_obj->set_gateway_id(ANET_CREDIT_CARD_GATEWAY_ID);
            $token_obj->set_type('CC');
        }
        $data          = $this->get_data_to_save($card_data, $user_id);
        $props         = $this->get_props();
        $return_result = $this->save_token_to_database($token_obj, $data, $props);
    }
    /**
     * Get formatted data to save for payment token.
     *
     * @since 1.0.0
     *
     * @param mixed $card_data Card data from API response.
     * @param int   $user_id User ID.
     * 
     * @return array Formatted data array.
     */
    public function get_data_to_save($card_data, $user_id)
    {
        $setting = Anet_Setting_Helper::get_cc_settings();
        $card_type_map = array(
            'AmericanExpress' => 'American Express',
            'MasterCard'      => 'MasterCard',
            'Visa'            => 'Visa',
            'Discover'        => 'Discover',
            'JCB'             => 'JCB',
            'DinersClub'      => 'Diners Club',
        );
        $card_data = json_decode(wp_json_encode($card_data), true);
        $data = array();
        $token_identifier['customer_profile_id'] = $card_data['customerProfileId'];
        $token_identifier['payment_profile_id'] = $card_data['customerPaymentProfileId'];
        $token_identifier['state'] = 'ACTIVE';
        $token_identifier['new'] = true;
        $data['first_six']         = $card_data['payment']['creditCard']['issuerNumber'];
        $data['last_four']         = $card_data['payment']['creditCard']['cardNumber'];
        $data['token_information'] = $token_identifier;
        $raw_type = $card_data['payment']['creditCard']['cardType'];
        $data['card_type'] = isset($card_type_map[$raw_type]) ? $card_type_map[$raw_type] : $raw_type;
        $data['expiry_year']       = substr($card_data['payment']['creditCard']['expirationDate'], 0, 4);
        $data['expiry_month']      = substr($card_data['payment']['creditCard']['expirationDate'], 0, 2);
        $data['gateway_id']        = ANET_CREDIT_CARD_GATEWAY_ID;
        $data['user_id']           = $user_id;
        $data['environment']       = $setting['testmode'] ? ANET_ENVIRONMENT_TEST : ANET_ENVIRONMENT_PRODUCTION;
        return $data;
    }
    /**
     * Get property mapping for token data.
     *
     * @since 1.0.0
     * 
     * @return array Array mapping of property names.
     */
    public function get_props()
    {
        $response = [
            'gateway_id'   => 'gateway_id',
            'user_id'      => 'user_id',
            'is_default' => 'default',
            'last4'        => 'last_four',
            'expiry_year'  => 'expiry_year',
            'expiry_month'  => 'expiry_month',
            'card_type'    => 'card_type',
        ];
        return $response;
    }
    /**
     * Save payment token to database.
     *
     * @since 1.0.0
     *
     * @param WC_Payment_Token $token_obj Payment token object.
     * @param array            $data Token data to save.
     * @param array            $props Property mappings.
     * 
     * @return array Result array with status and message.
     */
    public function save_token_to_database($token_obj, $data, $props)
    {
        foreach ($data as $key => $value) {
            $core_key = array_search($key, $props, true);
            /** \WC_Payment_Token does not define a set_is_default method */
            if ('is_default' === $core_key) {
                $token_obj->set_default($value);
            } elseif ($core_key) {
                $token_obj->set_props(array($core_key => $value));
            } else {
                $token_obj->update_meta_data($key, $value, true);
            }
        }
        try {
            $saved_token = $token_obj->save();
            if ($saved_token) {
                $return_result['message'] = __('Card Saved Succesfully.', 'authorize-net-payments-for-woocommerce');
                $return_result['status']  = true;
                $return_result['token']  = $token_obj->get_token();
                // Redirect to payment methods page after saving.
            }
        } catch (Throwable $e) {
            Anet_Setting_Helper::log("\nException:\n" . $e->getMessage(), ANET_PAYMENT_TYPE_CREDIT_CARD, 'error');
            $return_result['message'] = __('Unable to store card information. Please try again later.', 'authorize-net-payments-for-woocommerce');
            $return_result['status']  = false;
        }
        return $return_result;
    }
    /**
     * Add the payment method title to the account page.
     *
     * @since 1.0.0
     * 
     * @param array $columns Existing columns array.
     * 
     * @return array Modified columns array.
     */
    public function account_payment_methods_columns($columns = array())
    {
        $title_column = array('title' => __('Title', 'authorize-net-payments-for-woocommerce'));
        $columns      = $this->array_insert_after($columns, 'method', $title_column);
        $details_column = array('details' => __('Details', 'authorize-net-payments-for-woocommerce'));
        $columns        = $this->array_insert_after($columns, 'title', $details_column);
        $default_column = array('default' => __('Default', 'authorize-net-payments-for-woocommerce'));
        $columns        = $this->array_insert_after($columns, 'expires', $default_column);
        $anet_subscription = new Anet_Subscriptions();
        $anet_subscription_active = $anet_subscription->is_subscription_active;
        if ($anet_subscription_active) {
            if (!isset($columns['subscriptions'])) {
                $default_column = array('subscriptions' => __('Subscriptions', 'authorize-net-payments-for-woocommerce'));
                $columns        = $this->array_insert_after($columns, 'default', $default_column);
            }
        }
        return $columns;
    }
    /**
     * Insert an element into an array after a specific key.
     *
     * @since 1.0.0
     *
     * @param array  $main_array The main array to insert into.
     * @param string $insert_key The key after which to insert the element.
     * @param array  $element The element to insert.
     * 
     * @return array The modified array.
     */
    public static function array_insert_after(array $main_array, $insert_key, array $element)
    {
        $new_array = array();
        foreach ($main_array as $key => $value) {
            $new_array[$key] = $value;
            if ($key === $insert_key) {
                foreach ($element as $k => $v) {
                    $new_array[$k] = $v;
                }
            }
        }
        return $new_array;
    }
    /**
     * Add the payment method title value to the account page.
     *
     * @since 1.0.0
     * 
     * @param array $method Payment method data.
     * 
     * @return void
     */
    public function add_payment_method_title($method)
    {
        $gateway_title = null;
        $settings = get_option('woocommerce_anet_settings', []);
        if (ANET_CREDIT_CARD_GATEWAY_ID === $method['method']['gateway']) {
            $gateway_title = isset($settings['title']) ? $settings['title'] : null;
        }
        if ($gateway_title) {
            echo '<div class="method title"> ' . esc_html($gateway_title) . ' </div>';
        }
    }
    /**
     * This method provides the Card used for Payment.
     *
     * @param mixed $method Payment Method.
     */
    public function add_payment_method_details($method)
    {
        $last_four = null;
        if (ANET_CREDIT_CARD_GATEWAY_ID === $method['method']['gateway']) {
            $last_four = $method['method']['last4'];
        }
        if ($last_four) {
            echo '<span class="anet-card-display">' . esc_html($last_four) . '</span>';
        }
    }
    /**
     * Add default payment method marker to the account page.
     *
     * @since 1.0.0
     *
     * @param array $method Payment method data.
     * 
     * @return void
     */
    public function add_payment_method_default($method)
    {
        if (
            $method['is_default'] &&
            (isset($method['method']['gateway']) &&
                (ANET_CREDIT_CARD_GATEWAY_ID === $method['method']['gateway'] || ANET_ECHECK_GATEWAY_ID === $method['method']['gateway']))
        ) {
            echo '<mark class="default">' . esc_html__('Default', 'authorize-net-payments-for-woocommerce') . '</mark>';
        }
    }
    /**
     * Marks default card as default and remaining non default in db.
     *
     * @since 1.0.0
     *
     * @param int    $user_id User ID.
     * 
     * @return void
     */
    public function set_token_default($user_id)
    {
        $data_store                = WC_Data_Store::load('payment-token');
        $core_tokens               = array_merge(\WC_Payment_Tokens::get_customer_tokens($user_id, ANET_CREDIT_CARD_GATEWAY_ID), \WC_Payment_Tokens::get_customer_tokens($user_id, ANET_ECHECK_GATEWAY_ID));
        $default_payment_method_id = WC()->session->get("wc_anet_default_card_id", '');
        foreach ($core_tokens as $token) {
            if ($token->get_id() === (int) $default_payment_method_id) {
                $data_store->set_default_status($token->get_id(), true);
            } else {
                $data_store->set_default_status($token->get_id(), false);
            }
        }
    }
    /**
     * Handle setting a token as default.
     *
     * @since 1.0.0
     *
     * @param int                 $token_id Token ID.
     * @param WC_Payment_Token    $token Payment token object.
     * 
     * @return void
     */
    public function handle_set_default_token($token_id, $token)
    {
        $gateway_id = $token->get_gateway_id();
        $user_id = $token->get_user_id();
        $core_tokens = array_merge(\WC_Payment_Tokens::get_customer_tokens($user_id, ANET_CREDIT_CARD_GATEWAY_ID), \WC_Payment_Tokens::get_customer_tokens($user_id, ANET_ECHECK_GATEWAY_ID));
        $default_token = wc()->session->get("wc_anet_default_card_id", null);
        $is_edit_page = null;
        $is_edit_page = get_query_var('edit-credit-card') ?? get_query_var('edit-echeck');
        if ((ANET_CREDIT_CARD_GATEWAY_ID === $gateway_id || ANET_ECHECK_GATEWAY_ID === $gateway_id) && !is_checkout() && !is_add_payment_method_page() && $token instanceof \WC_Payment_Token && !isset($is_edit_page)) {
            if (1 < count($core_tokens) && (int)$default_token !== $token_id) {
                try {
                    $default_response = ['result' => false];
                    $token_info = $token->get_meta('token_information');
                    $customer_profile_id = !empty($token_info['customer_profile_id']) ? $token_info['customer_profile_id'] : null;
                    $customer_payment_profile_id = !empty($token_info['payment_profile_id']) ? $token_info['payment_profile_id'] : null;
                    if (ANET_CREDIT_CARD_GATEWAY_ID === $gateway_id) {
                        $tokenization = new Anet_Credit_Card_Tokenization();
                        $profile_response = $tokenization->get_customer_payment_profile($user_id, $customer_payment_profile_id);
                        if ($profile_response['result']) {
                            $card_number = $profile_response['card_number'] ?? null;
                            $expiration_date = $profile_response['expiration_date'] ?? null;
                            $default_response = $tokenization->set_default_payment_profile(
                                $user_id,
                                $customer_profile_id,
                                $customer_payment_profile_id,
                                $card_number,
                                $expiration_date
                            );
                        }
                    } elseif (ANET_ECHECK_GATEWAY_ID === $gateway_id) {
                        $tokenization = new Anet_ECheck_Tokenization();
                        $profile_response = $tokenization->get_customer_payment_profile($user_id, $customer_payment_profile_id);
                        if ($profile_response['result']) {
                            $account_number = $profile_response['account_number'] ?? null;
                            $routing_number = $profile_response['routing_number'] ?? null;
                            $account_type = $profile_response['account_type'] ?? null;
                            $name_on_account = $profile_response['name_on_account'] ?? null;
                            $default_response = $tokenization->set_default_payment_profile(
                                $user_id,
                                $customer_profile_id,
                                $customer_payment_profile_id,
                                $account_number,
                                $routing_number,
                                $account_type,
                                $name_on_account
                            );
                        }
                    }
                    if ($default_response['result']) {
                        return;
                    } else {
                        $this->set_token_default($user_id, $gateway_id);
                        wc_clear_notices();
                        wc_add_notice(esc_html__("Failed to update as default payment method. Please try again.", 'authorize-net-payments-for-woocommerce'), 'error');
                        wp_safe_redirect(wc_get_account_endpoint_url(ANET_PAYMENT_METHODS));
                        exit();
                    }
                } catch (Throwable $e) {
                    Anet_Setting_Helper::log("\nException:\n" . $e->getMessage(), ANET_PAYMENT_TYPE_CREDIT_CARD, 'error');
                    wc_clear_notices();
                    $this->set_token_default($user_id, $gateway_id);
                    wc_add_notice(esc_html__("Failed to update as default payment method. Please try again.", 'authorize-net-payments-for-woocommerce'), 'error');
                    wp_safe_redirect(wc_get_account_endpoint_url(ANET_PAYMENT_METHODS));
                    exit();
                }
            } else {
                wc_clear_notices();
                $this->set_token_default($user_id, $gateway_id);
                wc_add_notice(esc_html__("Failed to update as default payment method. Please try again.", 'authorize-net-payments-for-woocommerce'), 'error');
                wp_safe_redirect(wc_get_account_endpoint_url(ANET_PAYMENT_METHODS));
                exit();
            }
        }
    }
    /**
     * Add edit functionality to payment methods list items.
     *
     * @since 1.0.0
     *
     * @param array            $item Payment method item data.
     * @param WC_Payment_Token $payment_token Payment token object.
     * 
     * @return array Modified item data.
     */
    public function add_payment_methods_list_item_edit($item, $payment_token)
    {
        if (ANET_CREDIT_CARD_GATEWAY_ID === $payment_token->get_gateway_id()) {
            if ($payment_token->get_is_default()) {
                WC()->session->set('wc_anet_default_card_id', wc_clean($payment_token->get_id()));
            }
            $token_info = $payment_token->get_meta('token_information');
            $item['method']['token_id'] = $payment_token->get_id();
            if (!empty($token_info['payment_profile_id'])) {
                $item['method']['payment_profile_id'] = $token_info['payment_profile_id'];
            }
            if (!empty($token_info['customer_profile_id'])) {
                $item['method']['customer_profile_id'] = $token_info['customer_profile_id'];
            }
            $item['row_class'] = (isset($item['row_class']) ? $item['row_class'] . ' ' : '') . 'anet-method-row';
            $token_id = $payment_token->get_id();
            // Add Edit action.
            $item['actions']['edit'] = array(
                'url'  => wc_get_account_endpoint_url('edit-credit-card') . $token_id . ANET_SLASH,
                'name' => __('Edit', 'authorize-net-payments-for-woocommerce'),
            );
        }
        return $item;
    }
    /**
     * Enqueue scripts for My Account credit card section.
     *
     * @since 1.0.0
     * 
     * @return void
     */
    public function enqueue_myaccount_credit_card()
    {
        if (is_account_page() && !is_add_payment_method_page()) {
            wp_enqueue_script(
                'anet-inline-edit',
                plugins_url('../../../assets/js/frontend/anet-credit-card-update-payment-method.js', __FILE__),
                ['jquery'],
                ANET_PLUGIN_VERSION,
                true
            );
            wp_localize_script('anet-inline-edit', 'anetEdit', [
                'ajax_url' => admin_url('admin-ajax.php'),
                'nonce'    => wp_create_nonce('anet_edit_nonce'),
            ]);
        }
    }
    /**
     * Add custom query variables for credit card editing.
     *
     * @since 1.0.0
     *
     * @param array $vars Existing query variables.
     * 
     * @return array Modified query variables.
     */
    public function add_custom_query_vars_credit_card($vars)
    {
        $vars[] = 'edit-credit-card';
        return $vars;
    }
    /**
     * Render the edit credit card form.
     *
     * @since 1.0.0
     * 
     * @return void
     */
    public function render_edit_credit_card()
    {
        try {
            $redirect_url = isset($_SERVER['REQUEST_URI']) ? esc_url_raw(wp_unslash($_SERVER['REQUEST_URI'])) : '';
            $notice_type = 'error';
            $user_id = get_current_user_id();
            $token_id = get_query_var('edit-credit-card');
            $result = array('result' => false);
            if (!$token_id) {
                echo '<p>' . esc_html__('Invalid card.', 'authorize-net-payments-for-woocommerce') . '</p>';
                return;
            }
            $payment_token = WC_Payment_Tokens::get($token_id);
            if (!$payment_token || $payment_token->get_user_id() !== $user_id) {
                echo '<p>' . esc_html__('Invalid card.', 'authorize-net-payments-for-woocommerce') . '</p>';
                return;
            }
            $token_info = $payment_token->get_meta('token_information');
            $payment_profile_id = !empty($token_info['payment_profile_id']) ? $token_info['payment_profile_id'] : '';
            $customer_profile_id = !empty($token_info['customer_profile_id']) ? $token_info['customer_profile_id'] : '';
            $tokenization = new Anet_Credit_Card_Tokenization();
            $profile = $tokenization->get_customer_payment_profile($user_id, $payment_profile_id);
            if (empty($profile['card_number'])) {
                echo '<p>' . esc_html__('Unable to fetch card details.', 'authorize-net-payments-for-woocommerce') . '</p>';
                return;
            }
            // Handle form submission.
            if (isset($_SERVER['REQUEST_METHOD']) && 'POST' === $_SERVER['REQUEST_METHOD'] && isset($_POST['anet_edit_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['anet_edit_nonce'])), 'anet_edit_nonce')) {
                $new_card_number = isset($_POST['card_number']) ? sanitize_text_field(wp_unslash($_POST['card_number'])) : '';
                $new_expiry_month = isset($_POST['expiry_month']) ? sanitize_text_field(wp_unslash($_POST['expiry_month'])) : '';
                $new_expiry_year = isset($_POST['expiry_year']) ? sanitize_text_field(wp_unslash($_POST['expiry_year'])) : '';
                if (
                    empty($new_expiry_month) || empty($new_expiry_year) ||
                    !preg_match('/^(0[1-9]|1[0-2])$/', $new_expiry_month) ||
                    !preg_match('/^\d{4}$/', $new_expiry_year)
                ) {
                    wc_add_notice(__('Please select a valid expiry month and year.', 'authorize-net-payments-for-woocommerce'), 'error');
                } else {
                    $result = $tokenization->update_customer_payment_profile(
                        $user_id,
                        $customer_profile_id,
                        $payment_profile_id,
                        $new_expiry_month,
                        $new_expiry_year,
                        $new_card_number
                    );
                    if ($result['result']) {
                        $profile = $tokenization->get_customer_payment_profile($user_id, $payment_profile_id, true);
                        if ($profile['result']) {
                            $notice_type = 'success';
                            $redirect_url = wc_get_endpoint_url(ANET_PAYMENT_METHODS);
                        }
                    }
                    wc_add_notice($result['message'], $notice_type);
                }
            }
            // Load a template that ONLY shows the edit form.
            $template_path = plugin_dir_path(__FILE__) . '../../../templates/myaccount/anet-credit-card-edit.php';
            if (file_exists($template_path)) {
                include $template_path;
            } else {
                echo '<p>' . esc_html__('Edit template not found.', 'authorize-net-payments-for-woocommerce') . '</p>';
                return;
            }
        } catch (Throwable $e) {
            Anet_Setting_Helper::log("\nException:\n" . $e->getMessage(), ANET_PAYMENT_TYPE_CREDIT_CARD, 'error');
            wc_add_notice($result['message'], 'error');
            $redirect_url = isset($_SERVER['REQUEST_URI']) ? esc_url_raw(wp_unslash($_SERVER['REQUEST_URI'])) : '';
            wp_safe_redirect($redirect_url);
            exit();
        }
    }
   
}
// Register the custom endpoint for /my-account/edit-card/.
add_action('init', function () {
    add_rewrite_endpoint('edit-credit-card', EP_ROOT | EP_PAGES);
});
