<?php

/**
 * Plugin Name: Ghostonix Connector for FIB Payments
 * Description: WooCommerce connector for accepting FIB payments. Ghostonix is the independent plugin developer only; not a bank, payment processor, gateway provider, or FIB affiliate.
 * Version: 1.0.10
 * Requires at least: 6.5
 * Requires PHP: 7.4
 * Author: Ghostonix
 * Author URI: https://www.ghostonix.com
 * Text Domain: ghostonix-connector-for-fib-payments
 * License: GPLv2 or later
 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
 * WC requires at least: 7.0
 * WC tested up to: 10.0
 * Requires Plugins: woocommerce
 */
if ( !defined( 'ABSPATH' ) ) {
    exit;
}
if ( function_exists( 'ghostonix_fib_fs' ) ) {
    ghostonix_fib_fs()->set_basename( false, __FILE__ );
} else {
    if ( !function_exists( 'ghostonix_fib_fs' ) ) {
        function ghostonix_fib_fs() {
            global $ghostonix_fib_fs;
            if ( !isset( $ghostonix_fib_fs ) ) {
                require_once dirname( __FILE__ ) . '/vendor/freemius/start.php';
                $ghostonix_fib_fs = fs_dynamic_init( array(
                    'id'               => '32341',
                    'slug'             => 'ghostonix-connector-for-fib-payments',
                    'type'             => 'plugin',
                    'public_key'       => 'pk_785d188d843477b8658ff6600a259',
                    'is_premium'       => false,
                    'premium_slug'     => 'ghostonix-connector-for-fib-payments-premium',
                    'premium_suffix'   => 'Pro',
                    'has_addons'       => false,
                    'has_paid_plans'   => true,
                    'is_org_compliant' => true,
                    'menu'             => array(
                        'slug'       => 'ghostonix-fib-gateway',
                        'first-path' => 'admin.php?page=wc-settings&tab=checkout&section=ghostonix_fib',
                        'support'    => false,
                    ),
                    'is_live'          => true,
                ) );
            }
            return $ghostonix_fib_fs;
        }

        ghostonix_fib_fs();
        do_action( 'ghostonix_fib_fs_loaded' );
    }
    define( 'GHOSTONIX_FIB_VERSION', '1.0.10' );
    define( 'GHOSTONIX_FIB_FILE', __FILE__ );
    define( 'GHOSTONIX_FIB_DIR', plugin_dir_path( __FILE__ ) );
    define( 'GHOSTONIX_FIB_URL', plugin_dir_url( __FILE__ ) );
    if ( function_exists( 'ghostonix_fib_fs' ) && method_exists( ghostonix_fib_fs(), 'add_filter' ) ) {
        ghostonix_fib_fs()->add_filter( 'plugin_icon', function () {
            return GHOSTONIX_FIB_DIR . 'assets/img/ghostonix-fib-icon.png';
        } );
    }
    if ( !function_exists( 'ghostonix_fib_has_premium_code' ) ) {
        function ghostonix_fib_has_premium_code() {
            $is_premium_build = false;
            if ( function_exists( 'ghostonix_fib_fs' ) && method_exists( ghostonix_fib_fs(), 'is__premium_only' ) ) {
            }
            return $is_premium_build;
        }

    }
    if ( !function_exists( 'ghostonix_fib_is_pro' ) ) {
        function ghostonix_fib_is_pro() {
            if ( !ghostonix_fib_has_premium_code() ) {
                return false;
            }
            return false;
        }

    }
    if ( !function_exists( 'ghostonix_fib_upgrade_url' ) ) {
        function ghostonix_fib_upgrade_url() {
            return add_query_arg( array(
                'page'          => 'ghostonix-fib-gateway-pricing',
                'billing_cycle' => 'annual',
            ), admin_url( 'admin.php' ) );
        }

    }
    if ( !function_exists( 'ghostonix_fib_defaults' ) ) {
        function ghostonix_fib_defaults() {
            $defaults = array(
                'enabled'            => 'no',
                'title'              => 'Pay with FIB',
                'description'        => 'Pay securely using your FIB app.',
                'testmode'           => 'yes',
                'test_api_base'      => 'https://fib.stage.fib.iq',
                'live_api_base'      => 'https://fib.prod.fib.iq',
                'test_client_id'     => '',
                'test_client_secret' => '',
                'live_client_id'     => '',
                'live_client_secret' => '',
                'callback_token'     => '',
                'debug'              => 'no',
            );
            return $defaults;
        }

    }
    if ( !function_exists( 'ghostonix_fib_generate_callback_token' ) ) {
        function ghostonix_fib_generate_callback_token() {
            if ( function_exists( 'wp_generate_password' ) ) {
                return wp_generate_password( 40, false, false );
            }
            try {
                return bin2hex( random_bytes( 20 ) );
            } catch ( Exception $e ) {
                return substr( sha1( microtime( true ) . wp_rand() ), 0, 40 );
            }
        }

    }
    if ( !function_exists( 'ghostonix_fib_money' ) ) {
        function ghostonix_fib_money(  $amount  ) {
            return number_format(
                (float) $amount,
                2,
                '.',
                ''
            );
        }

    }
    if ( !function_exists( 'ghostonix_fib_trim_base' ) ) {
        function ghostonix_fib_trim_base(  $url, $fallback  ) {
            $url = trim( (string) $url );
            return ( '' !== $url ? rtrim( esc_url_raw( $url ), '/' ) : $fallback );
        }

    }
    if ( !function_exists( 'ghostonix_fib_amount_equal' ) ) {
        function ghostonix_fib_amount_equal(  $a, $b  ) {
            return abs( (float) $a - (float) $b ) < 0.01;
        }

    }
    if ( !function_exists( 'ghostonix_fib_query_arg' ) ) {
        /**
         * Read a sanitized query argument.
         *
         * State-changing frontend actions must pass a nonce action so the input
         * origin is verified before the value is used. Public gateway returns are
         * additionally protected by the WooCommerce order key.
         *
         * @param string $key          Query argument key.
         * @param string $nonce_action Optional nonce action required for action links.
         * @param string $nonce_key    Query argument key containing the nonce.
         * @return string
         */
        function ghostonix_fib_query_arg(  $key, $nonce_action = '', $nonce_key = '_wpnonce'  ) {
            if ( '' !== (string) $nonce_action ) {
                $nonce_value = filter_input( INPUT_GET, (string) $nonce_key, FILTER_UNSAFE_RAW );
                if ( null === $nonce_value || false === $nonce_value || is_array( $nonce_value ) ) {
                    return '';
                }
                $nonce_value = sanitize_text_field( wp_unslash( (string) $nonce_value ) );
                if ( !wp_verify_nonce( $nonce_value, (string) $nonce_action ) ) {
                    return '';
                }
            }
            $value = filter_input( INPUT_GET, (string) $key, FILTER_UNSAFE_RAW );
            if ( null === $value || false === $value || is_array( $value ) ) {
                return '';
            }
            return sanitize_text_field( wp_unslash( (string) $value ) );
        }

    }
    add_action( 'before_woocommerce_init', function () {
        if ( class_exists( '\\Automattic\\WooCommerce\\Utilities\\FeaturesUtil' ) ) {
            \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true );
        }
    } );
    add_action( 'admin_notices', function () {
        if ( !current_user_can( 'activate_plugins' ) ) {
            return;
        }
        if ( !class_exists( 'WooCommerce' ) ) {
            echo '<div class="notice notice-warning"><p>' . esc_html__( 'Ghostonix Connector for FIB Payments requires WooCommerce to be installed and active.', 'ghostonix-connector-for-fib-payments' ) . '</p></div>';
        }
    } );
    add_action( 'plugins_loaded', function () {
        if ( !class_exists( 'WC_Payment_Gateway' ) ) {
            return;
        }
        class WC_Gateway_Ghostonix_FIB extends WC_Payment_Gateway {
            const META_PAYMENT_ID = '_ghostonix_fib_payment_id';

            const META_STATUS = '_ghostonix_fib_status';

            const META_RAW = '_ghostonix_fib_raw';

            const META_ERROR = '_ghostonix_fib_error';

            const META_VALID_UNTIL = '_ghostonix_fib_valid_until';

            const META_QR = '_ghostonix_fib_qr';

            const META_CODE = '_ghostonix_fib_code';

            const META_PERSONAL_LINK = '_ghostonix_fib_personal_link';

            const META_BUSINESS_LINK = '_ghostonix_fib_business_link';

            const META_CORPORATE_LINK = '_ghostonix_fib_corporate_link';

            const META_BASE_AMOUNT = '_ghostonix_fib_base_amount';

            const META_BASE_CURRENCY = '_ghostonix_fib_base_currency';

            const META_CHARGE_AMOUNT = '_ghostonix_fib_charge_amount';

            const META_CHARGE_CURRENCY = '_ghostonix_fib_charge_currency';

            const META_RATE = '_ghostonix_fib_rate';

            const META_API_BASE = '_ghostonix_fib_api_base';

            const META_PAID_AT = '_ghostonix_fib_paid_at';

            const META_PAID_BY_NAME = '_ghostonix_fib_paid_by_name';

            const META_PAID_BY_IBAN = '_ghostonix_fib_paid_by_iban';

            const META_DECLINED_AT = '_ghostonix_fib_declined_at';

            const META_DECLINE_REASON = '_ghostonix_fib_decline_reason';

            const META_CREATED_AT = '_ghostonix_fib_created_at';

            public function __construct() {
                $this->id = 'ghostonix_fib';
                $this->method_title = __( 'Ghostonix Connector for FIB Payments', 'ghostonix-connector-for-fib-payments' );
                $this->method_description = __( 'Accept FIB payments in WooCommerce using your own FIB merchant credentials. Ghostonix is the independent plugin developer only and is not affiliated with FIB.', 'ghostonix-connector-for-fib-payments' );
                $this->has_fields = false;
                $this->supports = array('products');
                $this->init_form_fields();
                $this->init_settings();
                $this->ensure_callback_token();
                $this->enabled = $this->get_option( 'enabled', 'no' );
                $this->title = $this->get_option( 'title', 'Pay with FIB' );
                $this->description = $this->get_option( 'description', 'Pay securely using your FIB app.' );
                $this->testmode = 'yes' === $this->get_option( 'testmode', 'yes' );
                $this->debug = 'yes' === $this->get_option( 'debug', 'no' );
                add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array($this, 'process_admin_options') );
                add_action( 'woocommerce_receipt_' . $this->id, array($this, 'receipt_page') );
                add_action( 'wp_enqueue_scripts', array($this, 'enqueue_frontend_assets') );
            }

            public function init_form_fields() {
                $fields = array(
                    'enabled'            => array(
                        'title'   => __( 'Enable/Disable', 'ghostonix-connector-for-fib-payments' ),
                        'type'    => 'toggle',
                        'label'   => __( 'Enable FIB payment gateway', 'ghostonix-connector-for-fib-payments' ),
                        'default' => 'no',
                    ),
                    'title'              => array(
                        'title'   => __( 'Title', 'ghostonix-connector-for-fib-payments' ),
                        'type'    => 'text',
                        'default' => __( 'Pay with FIB', 'ghostonix-connector-for-fib-payments' ),
                    ),
                    'description'        => array(
                        'title'   => __( 'Description', 'ghostonix-connector-for-fib-payments' ),
                        'type'    => 'textarea',
                        'default' => __( 'Pay securely using your FIB app.', 'ghostonix-connector-for-fib-payments' ),
                    ),
                    'testmode'           => array(
                        'title'       => __( 'Test mode', 'ghostonix-connector-for-fib-payments' ),
                        'type'        => 'toggle',
                        'label'       => __( 'Use FIB stage environment', 'ghostonix-connector-for-fib-payments' ),
                        'default'     => 'yes',
                        'description' => __( 'Turn off when using live FIB credentials.', 'ghostonix-connector-for-fib-payments' ),
                    ),
                    'test_api_base'      => array(
                        'title'       => __( 'Stage API Base URL', 'ghostonix-connector-for-fib-payments' ),
                        'type'        => 'text',
                        'default'     => 'https://fib.stage.fib.iq',
                        'description' => __( 'Sandbox base URL. The plugin also retries the alternate stage host if needed.', 'ghostonix-connector-for-fib-payments' ),
                    ),
                    'test_client_id'     => array(
                        'title' => __( 'Test Client ID', 'ghostonix-connector-for-fib-payments' ),
                        'type'  => 'text',
                    ),
                    'test_client_secret' => array(
                        'title' => __( 'Test Client Secret', 'ghostonix-connector-for-fib-payments' ),
                        'type'  => 'password',
                    ),
                    'live_api_base'      => array(
                        'title'       => __( 'Live API Base URL', 'ghostonix-connector-for-fib-payments' ),
                        'type'        => 'text',
                        'default'     => 'https://fib.prod.fib.iq',
                        'description' => __( 'Used only when Test mode is off.', 'ghostonix-connector-for-fib-payments' ),
                    ),
                    'live_client_id'     => array(
                        'title' => __( 'Live Client ID', 'ghostonix-connector-for-fib-payments' ),
                        'type'  => 'text',
                    ),
                    'live_client_secret' => array(
                        'title' => __( 'Live Client Secret', 'ghostonix-connector-for-fib-payments' ),
                        'type'  => 'password',
                    ),
                    'callback_token'     => array(
                        'title'       => __( 'Callback token', 'ghostonix-connector-for-fib-payments' ),
                        'type'        => 'text',
                        'default'     => '',
                        'description' => __( 'Required security token added to the FIB callback URL. Leave blank only when you want the plugin to generate a new token.', 'ghostonix-connector-for-fib-payments' ),
                    ),
                );
                $fields['debug'] = array(
                    'title'       => __( 'Debug logging', 'ghostonix-connector-for-fib-payments' ),
                    'type'        => 'toggle',
                    'label'       => __( 'Log FIB API requests/responses', 'ghostonix-connector-for-fib-payments' ),
                    'default'     => 'no',
                    'description' => __( 'Logs: WooCommerce → Status → Logs → ghostonix_fib.', 'ghostonix-connector-for-fib-payments' ),
                );
                $this->form_fields = $fields;
            }

            public function generate_toggle_html( $key, $data ) {
                $field_key = $this->get_field_key( $key );
                $defaults = array(
                    'title'       => '',
                    'label'       => '',
                    'description' => '',
                    'default'     => 'no',
                    'desc_tip'    => false,
                );
                $data = wp_parse_args( $data, $defaults );
                $value = $this->get_option( $key, $data['default'] );
                ob_start();
                ?>
                    <tr valign="top">
                        <th scope="row" class="titledesc">
                            <label for="<?php 
                echo esc_attr( $field_key );
                ?>"><?php 
                echo esc_html( $data['title'] );
                ?></label>
                        </th>
                        <td class="forminp">
                            <label class="ghostonix-fib-toggle-control" for="<?php 
                echo esc_attr( $field_key );
                ?>">
                                <input type="hidden" name="<?php 
                echo esc_attr( $field_key );
                ?>" value="no" />
                                <input type="checkbox" id="<?php 
                echo esc_attr( $field_key );
                ?>" name="<?php 
                echo esc_attr( $field_key );
                ?>" value="yes" <?php 
                checked( 'yes', $value );
                ?> />
                                <span class="ghostonix-fib-toggle-slider" aria-hidden="true"></span>
                                <span class="ghostonix-fib-toggle-label"><?php 
                echo esc_html( $data['label'] );
                ?></span>
                            </label>
                            <?php 
                if ( !empty( $data['description'] ) ) {
                    ?>
                                <p class="description"><?php 
                    echo wp_kses_post( $data['description'] );
                    ?></p>
                            <?php 
                }
                ?>
                        </td>
                    </tr>
                    <?php 
                return ob_get_clean();
            }

            public function validate_toggle_field( $key, $value ) {
                return ( 'yes' === $value ? 'yes' : 'no' );
            }

            protected function ensure_callback_token() {
                $token = trim( (string) $this->get_option( 'callback_token', '' ) );
                if ( '' !== $token ) {
                    return $token;
                }
                $settings = get_option( $this->get_option_key(), array() );
                if ( !is_array( $settings ) ) {
                    $settings = array();
                }
                $settings = wp_parse_args( $settings, ghostonix_fib_defaults() );
                $settings['callback_token'] = ghostonix_fib_generate_callback_token();
                update_option( $this->get_option_key(), $settings, false );
                $this->settings = $settings;
                return $settings['callback_token'];
            }

            public function process_admin_options() {
                $old = get_option( $this->get_option_key(), array() );
                if ( !is_array( $old ) ) {
                    $old = array();
                }
                parent::process_admin_options();
                $settings = get_option( $this->get_option_key(), array() );
                if ( !is_array( $settings ) ) {
                    $settings = array();
                }
                $settings = wp_parse_args( $settings, ghostonix_fib_defaults() );
                $post_data = $this->get_post_data();
                foreach ( array('test_client_secret', 'live_client_secret') as $secret_key ) {
                    $field_key = $this->get_field_key( $secret_key );
                    $posted = ( isset( $post_data[$field_key] ) ? trim( (string) $post_data[$field_key] ) : '' );
                    if ( '' === $posted && !empty( $old[$secret_key] ) ) {
                        $settings[$secret_key] = $old[$secret_key];
                    }
                }
                $settings['test_api_base'] = ghostonix_fib_trim_base( $settings['test_api_base'] ?? '', 'https://fib.stage.fib.iq' );
                $settings['live_api_base'] = ghostonix_fib_trim_base( $settings['live_api_base'] ?? '', 'https://fib.prod.fib.iq' );
                $callback_token = sanitize_text_field( (string) ($settings['callback_token'] ?? '') );
                $settings['callback_token'] = ( '' !== $callback_token ? $callback_token : ghostonix_fib_generate_callback_token() );
                update_option( $this->get_option_key(), $settings, false );
            }

            public function admin_options() {
                $is_pro = false;
                $pro_badge = '';
                $upgrade_url = ghostonix_fib_upgrade_url();
                echo '<div class="ghostonix-fib-admin-topbar">';
                echo '<div class="ghostonix-fib-admin-topbar-left"><button type="submit" class="button button-primary ghostonix-fib-save-top" name="save" value="' . esc_attr__( 'Save changes', 'ghostonix-connector-for-fib-payments' ) . '">' . esc_html__( 'Save changes', 'ghostonix-connector-for-fib-payments' ) . '</button></div>';
                echo '<div class="ghostonix-fib-admin-topbar-copy"><span>' . esc_html__( 'FIB Payment Connector Settings', 'ghostonix-connector-for-fib-payments' ) . '</span><small>' . esc_html__( 'WooCommerce payment connection by Ghostonix.', 'ghostonix-connector-for-fib-payments' ) . '</small></div>';
                echo '<div class="ghostonix-fib-admin-topbar-actions">';
                if ( '' !== $pro_badge ) {
                    echo wp_kses_post( $pro_badge );
                } else {
                    echo '<a class="ghostonix-fib-upgrade-top" href="' . esc_url( $upgrade_url ) . '">' . esc_html__( 'Upgrade to Pro', 'ghostonix-connector-for-fib-payments' ) . '</a>';
                }
                echo '</div></div>';
                parent::admin_options();
                if ( !$is_pro ) {
                    echo '<div class="ghostonix-fib-pro-card">';
                    echo '<div class="ghostonix-fib-pro-card-content">';
                    echo '<span class="ghostonix-fib-pro-eyebrow">' . esc_html__( 'Ghostonix Pro', 'ghostonix-connector-for-fib-payments' ) . '</span>';
                    echo '<h3>' . esc_html__( 'Need advanced payment workflows?', 'ghostonix-connector-for-fib-payments' ) . '</h3>';
                    echo '<p>' . esc_html__( 'Ghostonix Pro is a separate package distributed outside WordPress.org for merchants with advanced setup needs.', 'ghostonix-connector-for-fib-payments' ) . '</p>';
                    echo '<div class="ghostonix-fib-pro-actions">';
                    echo '<a class="ghostonix-fib-pro-primary" href="' . esc_url( $upgrade_url ) . '">' . esc_html__( 'Upgrade to Pro', 'ghostonix-connector-for-fib-payments' ) . '</a>';
                    echo '<a class="ghostonix-fib-pro-secondary" href="' . esc_url( $upgrade_url ) . '">' . esc_html__( 'View Features', 'ghostonix-connector-for-fib-payments' ) . '</a>';
                    echo '</div>';
                    echo '</div>';
                    echo '<div class="ghostonix-fib-pro-brand">' . esc_html__( 'Powered by Ghostonix', 'ghostonix-connector-for-fib-payments' ) . '</div>';
                    echo '</div>';
                }
                echo '<div class="ghostonix-fib-admin-notice ghostonix-fib-disclaimer"><strong>' . esc_html__( 'Independent developer notice.', 'ghostonix-connector-for-fib-payments' ) . '</strong>';
                echo '<p>' . esc_html__( 'Ghostonix is the independent developer of this plugin. Ghostonix is not a bank, payment processor, payment institution, payment gateway provider, or affiliate of FIB.', 'ghostonix-connector-for-fib-payments' ) . '</p>';
                echo '<p>' . esc_html__( 'This plugin only helps WooCommerce store owners connect their own store to FIB using their own FIB merchant credentials. All payment processing is handled by FIB. Ghostonix does not process, hold, transmit, or settle customer funds.', 'ghostonix-connector-for-fib-payments' ) . '</p></div>';
            }

            public function payment_fields() {
                if ( '' !== $this->description ) {
                    $description_html = wpautop( $this->description );
                    echo wp_kses_post( $description_html );
                }
            }

            public function is_available() {
                if ( !parent::is_available() ) {
                    return false;
                }
                if ( is_admin() && !wp_doing_ajax() ) {
                    return true;
                }
                if ( !function_exists( 'WC' ) || !WC()->cart ) {
                    return parent::is_available();
                }
                $total = (float) WC()->cart->get_total( 'edit' );
                if ( $total <= 0 ) {
                    return false;
                }
                $currency = strtoupper( (string) get_woocommerce_currency() );
                if ( 'IQD' !== $currency ) {
                    return false;
                }
                return true;
            }

            public function enqueue_frontend_assets() {
                if ( !function_exists( 'is_checkout' ) || !is_checkout() && !is_wc_endpoint_url( 'order-pay' ) ) {
                    return;
                }
                wp_enqueue_style(
                    'ghostonix-fib-frontend',
                    GHOSTONIX_FIB_URL . 'assets/css/frontend.css',
                    array(),
                    GHOSTONIX_FIB_VERSION
                );
                wp_enqueue_script(
                    'ghostonix-fib-frontend',
                    GHOSTONIX_FIB_URL . 'assets/js/frontend.js',
                    array('jquery'),
                    GHOSTONIX_FIB_VERSION,
                    true
                );
            }

            public function process_payment( $order_id ) {
                $order = wc_get_order( $order_id );
                if ( !$order instanceof WC_Order ) {
                    wc_add_notice( __( 'Invalid order.', 'ghostonix-connector-for-fib-payments' ), 'error' );
                    return array(
                        'result' => 'failure',
                    );
                }
                $created = $this->ensure_payment( $order, true );
                if ( is_wp_error( $created ) ) {
                    $message = $created->get_error_message();
                    $order->update_meta_data( self::META_ERROR, $message );
                    $order->save();
                    $order->add_order_note( 'FIB payment create failed: ' . $message );
                    wc_add_notice( __( 'Unable to prepare FIB payment.', 'ghostonix-connector-for-fib-payments' ) . ' ' . $message, 'error' );
                    return array(
                        'result' => 'failure',
                    );
                }
                $app_url = $this->best_app_url( $order );
                $payment_id = (string) $order->get_meta( self::META_PAYMENT_ID, true );
                $order->add_order_note( 'FIB payment ready: ' . $payment_id );
                $is_mobile = function_exists( 'wp_is_mobile' ) && wp_is_mobile();
                return array(
                    'result'   => 'success',
                    'redirect' => $order->get_checkout_payment_url( true ),
                );
            }

            public function receipt_page( $order_id ) {
                $order = wc_get_order( $order_id );
                if ( !$order instanceof WC_Order || $order->get_payment_method() !== $this->id ) {
                    return;
                }
                if ( $order->is_paid() ) {
                    wp_safe_redirect( $this->paid_return_url( $order ) );
                    exit;
                }
                $result = sanitize_key( ghostonix_fib_query_arg( 'ghostonix_fib_result', $this->result_nonce_action( $order ), 'ghostonix_fib_result_nonce' ) );
                if ( in_array( $result, array('failed', 'cancelled', 'canceled'), true ) ) {
                    $retry_url = remove_query_arg( array('ghostonix_fib_result', 'ghostonix_fib_result_nonce'), $order->get_checkout_payment_url( true ) );
                    echo '<div class="ghostonix-fib-shell"><div class="ghostonix-fib-card">';
                    echo '<h2>' . esc_html__( 'Payment not completed', 'ghostonix-connector-for-fib-payments' ) . '</h2>';
                    echo '<div class="ghostonix-fib-warning">' . esc_html__( 'FIB payment was cancelled or not completed.', 'ghostonix-connector-for-fib-payments' ) . '</div>';
                    echo '<div class="ghostonix-fib-actions">';
                    echo '<a class="ghostonix-fib-btn ghostonix-fib-primary" href="' . esc_url( $retry_url ) . '">' . esc_html__( 'Try again', 'ghostonix-connector-for-fib-payments' ) . '</a>';
                    echo '<a class="ghostonix-fib-btn" href="' . esc_url( wc_get_checkout_url() ) . '">' . esc_html__( 'Back to checkout', 'ghostonix-connector-for-fib-payments' ) . '</a>';
                    echo '</div></div></div>';
                    return;
                }
                $cancel_requested = '' !== ghostonix_fib_query_arg( 'ghostonix_fib_cancel', $this->cancel_nonce_action( $order ) );
                if ( $cancel_requested ) {
                    $cancel = $this->cancel_payment( $order );
                    if ( !is_wp_error( $cancel ) ) {
                        $order->update_status( 'failed', __( 'FIB payment cancelled by customer.', 'ghostonix-connector-for-fib-payments' ) );
                        echo '<div class="ghostonix-fib-shell"><div class="ghostonix-fib-card"><div class="ghostonix-fib-warning">' . esc_html__( 'Payment cancelled.', 'ghostonix-connector-for-fib-payments' ) . '</div><a class="ghostonix-fib-btn" href="' . esc_url( wc_get_checkout_url() ) . '">' . esc_html__( 'Back to checkout', 'ghostonix-connector-for-fib-payments' ) . '</a></div></div>';
                        return;
                    }
                    echo '<div class="ghostonix-fib-shell"><div class="ghostonix-fib-card"><div class="ghostonix-fib-error">' . esc_html( $cancel->get_error_message() ) . '</div><a class="ghostonix-fib-btn" href="' . esc_url( $order->get_checkout_payment_url( true ) ) . '">' . esc_html__( 'Back', 'ghostonix-connector-for-fib-payments' ) . '</a></div></div>';
                    return;
                }
                $ready = $this->ensure_payment( $order, false );
                if ( is_wp_error( $ready ) ) {
                    echo '<div class="ghostonix-fib-shell"><div class="ghostonix-fib-card"><div class="ghostonix-fib-error">' . esc_html( $ready->get_error_message() ) . '</div><a class="ghostonix-fib-btn" href="' . esc_url( wc_get_checkout_url() ) . '">' . esc_html__( 'Back to checkout', 'ghostonix-connector-for-fib-payments' ) . '</a></div></div>';
                    return;
                }
                $payment_id = (string) $order->get_meta( self::META_PAYMENT_ID, true );
                $status = (string) $order->get_meta( self::META_STATUS, true );
                $app_url = $this->best_app_url( $order );
                $qr = (string) $order->get_meta( self::META_QR, true );
                $code = (string) $order->get_meta( self::META_CODE, true );
                $charge = (string) $order->get_meta( self::META_CHARGE_AMOUNT, true );
                $currency = (string) $order->get_meta( self::META_CHARGE_CURRENCY, true );
                $error = (string) $order->get_meta( self::META_ERROR, true );
                $cancel_url = wp_nonce_url( add_query_arg( 'ghostonix_fib_cancel', '1', $order->get_checkout_payment_url( true ) ), $this->cancel_nonce_action( $order ) );
                echo '<div class="ghostonix-fib-shell"><div class="ghostonix-fib-card">';
                echo '<h2>' . esc_html__( 'Pay with FIB', 'ghostonix-connector-for-fib-payments' ) . '</h2>';
                echo '<p class="ghostonix-fib-muted">' . esc_html__( 'Open FIB, approve payment, then return here. Your order verifies automatically.', 'ghostonix-connector-for-fib-payments' ) . '</p>';
                if ( '' !== $error ) {
                    echo '<div class="ghostonix-fib-error">' . esc_html( $error ) . '</div>';
                }
                echo '<div class="ghostonix-fib-box">';
                echo '<div><strong>' . esc_html__( 'Order:', 'ghostonix-connector-for-fib-payments' ) . '</strong> #' . esc_html( $order->get_order_number() ) . '</div>';
                echo '<div><strong>' . esc_html__( 'FIB amount:', 'ghostonix-connector-for-fib-payments' ) . '</strong> ' . esc_html( $charge . ' ' . $currency ) . '</div>';
                echo '<div><strong>' . esc_html__( 'Status:', 'ghostonix-connector-for-fib-payments' ) . '</strong> <span data-ghostonix-fib-label>' . esc_html( $this->label( $status ) ) . '</span></div>';
                echo '<div class="ghostonix-fib-live" data-ghostonix-fib-status="1" data-order-id="' . esc_attr( $order->get_id() ) . '" data-order-key="' . esc_attr( $order->get_order_key() ) . '" data-status-url="' . esc_url( rest_url( 'ghostonix-fib/v1/status' ) ) . '" data-status-nonce="' . esc_attr( wp_create_nonce( $this->status_nonce_action( $order ) ) ) . '"><span><i></i> ' . esc_html__( 'Waiting for FIB payment confirmation...', 'ghostonix-connector-for-fib-payments' ) . '</span></div>';
                echo '</div>';
                echo '<div class="ghostonix-fib-actions">';
                if ( '' !== $app_url ) {
                    echo '<a class="ghostonix-fib-btn ghostonix-fib-primary" href="' . esc_url( $app_url ) . '" rel="nofollow noopener">' . esc_html__( 'Open FIB', 'ghostonix-connector-for-fib-payments' ) . '</a>';
                }
                echo '<a class="ghostonix-fib-btn" href="#" data-ghostonix-fib-check="1">' . esc_html__( 'Check status', 'ghostonix-connector-for-fib-payments' ) . '</a>';
                echo '<a class="ghostonix-fib-btn ghostonix-fib-danger" href="' . esc_url( $cancel_url ) . '">' . esc_html__( 'Cancel', 'ghostonix-connector-for-fib-payments' ) . '</a>';
                echo '</div>';
                echo '<div class="ghostonix-fib-fallback">';
                if ( '' !== $qr ) {
                    $src = ( 0 === strpos( $qr, 'data:image/' ) ? $qr : esc_url_raw( $qr ) );
                    echo '<div class="ghostonix-fib-qr"><img src="' . esc_attr( $src ) . '" alt="' . esc_attr__( 'FIB QR Code', 'ghostonix-connector-for-fib-payments' ) . '"><div class="ghostonix-fib-small">' . esc_html__( 'Scan this QR inside FIB if direct opening fails.', 'ghostonix-connector-for-fib-payments' ) . '</div></div>';
                }
                if ( '' !== $code ) {
                    echo '<div class="ghostonix-fib-code"><strong>' . esc_html__( 'Manual code:', 'ghostonix-connector-for-fib-payments' ) . '</strong> <span>' . esc_html( $code ) . '</span> <button type="button" class="ghostonix-fib-btn" data-ghostonix-fib-copy="' . esc_attr( $code ) . '">' . esc_html__( 'Copy', 'ghostonix-connector-for-fib-payments' ) . '</button></div>';
                }
                echo '<div class="ghostonix-fib-small">' . esc_html__( 'Payment ID:', 'ghostonix-connector-for-fib-payments' ) . ' ' . esc_html( $payment_id ) . '</div>';
                echo '</div>';
                $raw = (string) $order->get_meta( self::META_RAW, true );
                echo '</div></div>';
            }

            public function register_routes() {
                register_rest_route( 'ghostonix-fib/v1', '/callback', array(
                    'methods'             => 'POST',
                    'callback'            => array($this, 'rest_callback'),
                    'permission_callback' => array($this, 'rest_callback_permission'),
                ) );
                register_rest_route( 'ghostonix-fib/v1', '/status', array(
                    'methods'             => 'GET',
                    'callback'            => array($this, 'rest_status'),
                    'permission_callback' => array($this, 'rest_status_permission'),
                ) );
                register_rest_route( 'ghostonix-fib/v1', '/return', array(
                    'methods'             => 'GET',
                    'callback'            => array($this, 'rest_return'),
                    'permission_callback' => array($this, 'rest_return_permission'),
                ) );
            }

            public function rest_callback_permission( WP_REST_Request $request ) {
                $expected_token = $this->ensure_callback_token();
                $sent_token = sanitize_text_field( (string) $request->get_param( 'token' ) );
                if ( '' === $sent_token || !hash_equals( $expected_token, $sent_token ) ) {
                    return new WP_Error('ghostonix_fib_invalid_callback_token', __( 'Invalid FIB callback token.', 'ghostonix-connector-for-fib-payments' ), array(
                        'status' => 403,
                    ));
                }
                return true;
            }

            public function rest_status_permission( WP_REST_Request $request ) {
                return $this->rest_order_nonce_permission( $request, 'status' );
            }

            public function rest_return_permission( WP_REST_Request $request ) {
                return $this->rest_order_nonce_permission( $request, 'return' );
            }

            protected function rest_order_nonce_permission( WP_REST_Request $request, $context ) {
                $order = $this->order_from_rest_request( $request );
                if ( is_wp_error( $order ) ) {
                    return $order;
                }
                $nonce = sanitize_text_field( (string) $request->get_param( 'nonce' ) );
                $action = ( 'return' === $context ? $this->return_nonce_action( $order ) : $this->status_nonce_action( $order ) );
                if ( '' === $nonce || !wp_verify_nonce( $nonce, $action ) ) {
                    return new WP_Error('ghostonix_fib_invalid_nonce', __( 'Invalid FIB payment request.', 'ghostonix-connector-for-fib-payments' ), array(
                        'status' => 403,
                    ));
                }
                return true;
            }

            protected function order_from_rest_request( WP_REST_Request $request ) {
                $order_id = absint( $request->get_param( 'order_id' ) );
                $order_key = wc_clean( (string) $request->get_param( 'key' ) );
                $order = ( $order_id ? wc_get_order( $order_id ) : false );
                if ( !$order instanceof WC_Order ) {
                    return new WP_Error('ghostonix_fib_order_not_found', __( 'Order not found.', 'ghostonix-connector-for-fib-payments' ), array(
                        'status' => 404,
                    ));
                }
                if ( '' === $order_key || $order->get_order_key() !== $order_key ) {
                    return new WP_Error('ghostonix_fib_invalid_order_key', __( 'Invalid order key.', 'ghostonix-connector-for-fib-payments' ), array(
                        'status' => 403,
                    ));
                }
                if ( $order->get_payment_method() !== $this->id ) {
                    return new WP_Error('ghostonix_fib_invalid_payment_method', __( 'Invalid payment method.', 'ghostonix-connector-for-fib-payments' ), array(
                        'status' => 400,
                    ));
                }
                return $order;
            }

            public function rest_callback( WP_REST_Request $request ) {
                // phpcs:disable WordPress.Security.NonceVerification.Recommended -- FIB server callbacks are public and authenticated by a required callback token/payment lookup.
                $expected_token = $this->ensure_callback_token();
                $sent_token = sanitize_text_field( (string) $request->get_param( 'token' ) );
                if ( '' === $sent_token || !hash_equals( $expected_token, $sent_token ) ) {
                    return new WP_REST_Response(array(
                        'ok'      => false,
                        'message' => 'Invalid token',
                    ), 403);
                }
                $body = $request->get_json_params();
                if ( !is_array( $body ) ) {
                    $body = json_decode( (string) $request->get_body(), true );
                    $body = ( is_array( $body ) ? $body : array() );
                }
                $payment_id = sanitize_text_field( (string) ($body['id'] ?? $body['paymentId'] ?? '') );
                $status = strtoupper( sanitize_text_field( (string) ($body['status'] ?? '') ) );
                if ( '' === $payment_id ) {
                    return new WP_REST_Response(array(
                        'ok'      => false,
                        'message' => 'Missing payment id',
                    ), 400);
                }
                $order = $this->find_order_by_payment_id( $payment_id );
                if ( !$order instanceof WC_Order ) {
                    return new WP_REST_Response(array(
                        'ok'      => false,
                        'message' => 'Order not found',
                    ), 404);
                }
                if ( '' !== $status ) {
                    $order->update_meta_data( self::META_STATUS, $status );
                    $order->save();
                }
                $sync = $this->sync_status( $order );
                if ( is_wp_error( $sync ) ) {
                    $order->add_order_note( 'FIB callback sync failed: ' . $sync->get_error_message() );
                    return new WP_REST_Response(array(
                        'ok'      => false,
                        'message' => $sync->get_error_message(),
                    ), 200);
                }
                // phpcs:enable WordPress.Security.NonceVerification.Recommended
                return new WP_REST_Response(array(
                    'ok' => true,
                ), 200);
            }

            public function rest_return( WP_REST_Request $request ) {
                // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Permission callback validates the WooCommerce order key and nonce before this public FIB return endpoint runs.
                $order_id = absint( $request->get_param( 'order_id' ) );
                $order_key = wc_clean( (string) $request->get_param( 'key' ) );
                // phpcs:enable WordPress.Security.NonceVerification.Recommended
                $order = ( $order_id ? wc_get_order( $order_id ) : false );
                if ( !$order instanceof WC_Order || $order->get_order_key() !== $order_key || $order->get_payment_method() !== $this->id ) {
                    wp_safe_redirect( wc_get_checkout_url() );
                    exit;
                }
                if ( !$order->is_paid() ) {
                    $this->sync_status( $order );
                }
                $status = strtoupper( (string) $order->get_meta( self::META_STATUS, true ) );
                if ( $order->is_paid() || 'PAID' === $status ) {
                    wp_safe_redirect( $this->paid_return_url( $order ) );
                    exit;
                }
                if ( in_array( $status, array(
                    'DECLINED',
                    'FAILED',
                    'CANCELLED',
                    'CANCELED'
                ), true ) ) {
                    wc_add_notice( __( 'FIB payment was not completed. Please try again.', 'ghostonix-connector-for-fib-payments' ), 'error' );
                    wp_safe_redirect( $this->retry_payment_url( $order, 'failed' ) );
                    exit;
                }
                wc_add_notice( __( 'FIB payment is still pending. Please complete the payment or try again.', 'ghostonix-connector-for-fib-payments' ), 'notice' );
                wp_safe_redirect( $order->get_checkout_payment_url( true ) );
                exit;
            }

            public function rest_status( WP_REST_Request $request ) {
                // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Permission callback validates the WooCommerce order key and nonce before status polling runs.
                $order_id = absint( $request->get_param( 'order_id' ) );
                $order_key = wc_clean( (string) $request->get_param( 'key' ) );
                // phpcs:enable WordPress.Security.NonceVerification.Recommended
                $order = ( $order_id ? wc_get_order( $order_id ) : false );
                if ( !$order instanceof WC_Order ) {
                    return new WP_REST_Response(array(
                        'ok'    => false,
                        'label' => 'Order not found',
                        'final' => true,
                    ), 404);
                }
                if ( '' === $order_key || $order->get_order_key() !== $order_key ) {
                    return new WP_REST_Response(array(
                        'ok'    => false,
                        'label' => 'Invalid order key',
                        'final' => true,
                    ), 403);
                }
                if ( $order->get_payment_method() !== $this->id ) {
                    return new WP_REST_Response(array(
                        'ok'    => false,
                        'label' => 'Invalid payment method',
                        'final' => true,
                    ), 400);
                }
                if ( $order->is_paid() ) {
                    return new WP_REST_Response(array(
                        'ok'       => true,
                        'label'    => 'Payment confirmed. Redirecting...',
                        'final'    => true,
                        'redirect' => $this->paid_return_url( $order ),
                    ), 200);
                }
                $sync = $this->sync_status( $order );
                if ( is_wp_error( $sync ) ) {
                    return new WP_REST_Response(array(
                        'ok'    => false,
                        'label' => $sync->get_error_message(),
                        'final' => false,
                    ), 200);
                }
                $status = strtoupper( (string) $order->get_meta( self::META_STATUS, true ) );
                if ( $order->is_paid() || 'PAID' === $status ) {
                    return new WP_REST_Response(array(
                        'ok'       => true,
                        'label'    => 'Payment confirmed. Redirecting...',
                        'final'    => true,
                        'redirect' => $this->paid_return_url( $order ),
                    ), 200);
                }
                if ( in_array( $status, array(
                    'DECLINED',
                    'FAILED',
                    'CANCELLED',
                    'CANCELED'
                ), true ) ) {
                    return new WP_REST_Response(array(
                        'ok'       => false,
                        'label'    => 'Payment was not completed. Redirecting...',
                        'final'    => true,
                        'redirect' => $this->retry_payment_url( $order, 'failed' ),
                    ), 200);
                }
                return new WP_REST_Response(array(
                    'ok'    => true,
                    'label' => $this->label( $status ),
                    'final' => false,
                ), 200);
            }

            public function maybe_handle_return() {
                if ( '' === ghostonix_fib_query_arg( 'ghostonix_fib_return' ) ) {
                    return;
                }
                $order_id = absint( ghostonix_fib_query_arg( 'order_id' ) );
                $order_key = wc_clean( ghostonix_fib_query_arg( 'key' ) );
                $order = ( $order_id ? wc_get_order( $order_id ) : false );
                if ( !$order instanceof WC_Order || $order->get_order_key() !== $order_key || $order->get_payment_method() !== $this->id ) {
                    wp_safe_redirect( wc_get_checkout_url() );
                    exit;
                }
                $return_nonce = ghostonix_fib_query_arg( 'ghostonix_fib_return_nonce' );
                if ( '' === $return_nonce || !wp_verify_nonce( $return_nonce, $this->return_nonce_action( $order ) ) ) {
                    wp_safe_redirect( wc_get_checkout_url() );
                    exit;
                }
                if ( !$order->is_paid() ) {
                    $this->sync_status( $order );
                }
                $status = strtoupper( (string) $order->get_meta( self::META_STATUS, true ) );
                if ( $order->is_paid() || 'PAID' === $status ) {
                    wp_safe_redirect( $this->paid_return_url( $order ) );
                    exit;
                }
                if ( in_array( $status, array(
                    'DECLINED',
                    'FAILED',
                    'CANCELLED',
                    'CANCELED'
                ), true ) ) {
                    wc_add_notice( __( 'FIB payment was not completed. Please try again.', 'ghostonix-connector-for-fib-payments' ), 'error' );
                    wp_safe_redirect( $this->retry_payment_url( $order, 'failed' ) );
                    exit;
                }
                wc_add_notice( __( 'FIB payment is still pending. Please complete the payment or try again.', 'ghostonix-connector-for-fib-payments' ), 'notice' );
                wp_safe_redirect( $order->get_checkout_payment_url( true ) );
                exit;
            }

            protected function paid_return_url( WC_Order $order ) {
                return $this->get_return_url( $order );
            }

            protected function status_nonce_action( WC_Order $order ) {
                return 'ghostonix_fib_status_' . absint( $order->get_id() ) . '_' . $order->get_order_key();
            }

            protected function return_nonce_action( WC_Order $order ) {
                return 'ghostonix_fib_return_' . absint( $order->get_id() ) . '_' . $order->get_order_key();
            }

            protected function result_nonce_action( WC_Order $order ) {
                return 'ghostonix_fib_result_' . absint( $order->get_id() ) . '_' . $order->get_order_key();
            }

            protected function cancel_nonce_action( WC_Order $order ) {
                return 'ghostonix_fib_cancel_' . absint( $order->get_id() ) . '_' . $order->get_order_key();
            }

            protected function retry_payment_url( WC_Order $order, $result = 'pending' ) {
                return add_query_arg( array(
                    'ghostonix_fib_result'       => sanitize_key( $result ),
                    'ghostonix_fib_result_nonce' => wp_create_nonce( $this->result_nonce_action( $order ) ),
                ), $order->get_checkout_payment_url( true ) );
            }

            protected function ensure_payment( WC_Order $order, $force_new = false ) {
                if ( $order->is_paid() ) {
                    return true;
                }
                if ( !$force_new && !$this->needs_new_payment( $order ) ) {
                    return true;
                }
                $context = $this->charge_context( $order );
                if ( is_wp_error( $context ) ) {
                    return $context;
                }
                $created = $this->create_payment( $order, $context );
                if ( is_wp_error( $created ) ) {
                    $order->update_meta_data( self::META_ERROR, $created->get_error_message() );
                    $order->save();
                    return $created;
                }
                $payment_id = sanitize_text_field( (string) ($created['paymentId'] ?? $created['id'] ?? '') );
                if ( '' === $payment_id ) {
                    return new WP_Error('ghostonix_fib_missing_payment_id', __( 'FIB did not return paymentId.', 'ghostonix-connector-for-fib-payments' ));
                }
                $order->update_meta_data( self::META_PAYMENT_ID, $payment_id );
                $order->update_meta_data( self::META_STATUS, strtoupper( (string) ($created['status'] ?? 'UNPAID') ) );
                $order->update_meta_data( self::META_RAW, $this->safe_json_for_storage( $created ) );
                $order->update_meta_data( self::META_ERROR, '' );
                $order->update_meta_data( self::META_VALID_UNTIL, sanitize_text_field( (string) ($created['validUntil'] ?? '') ) );
                $order->update_meta_data( self::META_QR, (string) ($created['qrCode'] ?? '') );
                $order->update_meta_data( self::META_CODE, sanitize_text_field( (string) ($created['readableCode'] ?? '') ) );
                $order->update_meta_data( self::META_PERSONAL_LINK, $this->clean_app_link( (string) ($created['personalAppLink'] ?? $created['personalLink'] ?? '') ) );
                $order->update_meta_data( self::META_BUSINESS_LINK, $this->clean_app_link( (string) ($created['businessAppLink'] ?? $created['businessLink'] ?? '') ) );
                $order->update_meta_data( self::META_CORPORATE_LINK, $this->clean_app_link( (string) ($created['corporateAppLink'] ?? $created['corporateLink'] ?? '') ) );
                $order->update_meta_data( self::META_BASE_AMOUNT, $context['base_amount'] );
                $order->update_meta_data( self::META_BASE_CURRENCY, $context['base_currency'] );
                $order->update_meta_data( self::META_CHARGE_AMOUNT, $context['charge_amount'] );
                $order->update_meta_data( self::META_CHARGE_CURRENCY, $context['charge_currency'] );
                $order->update_meta_data( self::META_RATE, $context['rate'] );
                $order->update_meta_data( self::META_CREATED_AT, current_time( 'mysql', true ) );
                $order->save();
                return true;
            }

            protected function needs_new_payment( WC_Order $order ) {
                $payment_id = (string) $order->get_meta( self::META_PAYMENT_ID, true );
                $status = strtoupper( (string) $order->get_meta( self::META_STATUS, true ) );
                $valid = (string) $order->get_meta( self::META_VALID_UNTIL, true );
                if ( '' === $payment_id ) {
                    return true;
                }
                if ( in_array( $status, array(
                    'DECLINED',
                    'FAILED',
                    'CANCELLED',
                    'CANCELED',
                    'REFUNDED',
                    'REFENDED'
                ), true ) ) {
                    return true;
                }
                if ( '' !== $valid ) {
                    $timestamp = strtotime( $valid );
                    if ( $timestamp && time() >= $timestamp ) {
                        return true;
                    }
                }
                return false;
            }

            protected function charge_context( WC_Order $order ) {
                $existing_amount = (string) $order->get_meta( self::META_CHARGE_AMOUNT, true );
                $existing_currency = (string) $order->get_meta( self::META_CHARGE_CURRENCY, true );
                if ( '' !== $existing_amount && '' !== $existing_currency ) {
                    return array(
                        'base_amount'     => (string) $order->get_meta( self::META_BASE_AMOUNT, true ),
                        'base_currency'   => (string) $order->get_meta( self::META_BASE_CURRENCY, true ),
                        'charge_amount'   => $existing_amount,
                        'charge_currency' => strtoupper( $existing_currency ),
                        'rate'            => (string) $order->get_meta( self::META_RATE, true ),
                    );
                }
                $total = (float) $order->get_total();
                $currency = strtoupper( (string) $order->get_currency() );
                if ( $total <= 0 ) {
                    return new WP_Error('ghostonix_fib_zero_total', __( 'Order total must be greater than zero.', 'ghostonix-connector-for-fib-payments' ));
                }
                if ( 'IQD' === $currency ) {
                    return array(
                        'base_amount'     => ghostonix_fib_money( $total ),
                        'base_currency'   => $currency,
                        'charge_amount'   => ghostonix_fib_money( $total ),
                        'charge_currency' => 'IQD',
                        'rate'            => '1.00',
                    );
                }
                return new WP_Error('ghostonix_fib_currency_not_supported', __( 'This plugin supports WooCommerce stores using IQD as the store currency.', 'ghostonix-connector-for-fib-payments' ));
            }

            protected function create_payment( WC_Order $order, array $context ) {
                $description = substr( 'Order #' . $order->get_order_number(), 0, 50 );
                $amount = ghostonix_fib_money( $context['charge_amount'] );
                $callback_url = $this->callback_url();
                $bases = $this->api_base_candidates();
                $return_url = add_query_arg( array(
                    'ghostonix_fib_return'       => '1',
                    'order_id'                   => $order->get_id(),
                    'key'                        => $order->get_order_key(),
                    'ghostonix_fib_return_nonce' => wp_create_nonce( $this->return_nonce_action( $order ) ),
                ), home_url( '/' ) );
                $payload = array(
                    'monetaryValue'     => array(
                        'amount'   => $amount,
                        'currency' => 'IQD',
                    ),
                    'statusCallbackUrl' => $callback_url,
                    'redirectUri'       => $return_url,
                    'description'       => $description,
                );
                $errors = array();
                foreach ( $bases as $base ) {
                    $token = $this->access_token( $base );
                    if ( is_wp_error( $token ) ) {
                        $errors[] = '[' . $base . ' auth] ' . $token->get_error_message();
                        continue;
                    }
                    $response = $this->api_json(
                        'POST',
                        $base . '/protected/v1/payments',
                        $token,
                        $payload,
                        array(200, 201, 202),
                        'create payment'
                    );
                    if ( !is_wp_error( $response ) ) {
                        $order->update_meta_data( self::META_API_BASE, $base );
                        $order->save();
                        return $response;
                    }
                    $errors[] = '[' . $base . ' create] ' . $response->get_error_message();
                    $status_code = ( is_array( $response->get_error_data() ) && isset( $response->get_error_data()['status'] ) ? (int) $response->get_error_data()['status'] : 0 );
                    if ( in_array( $status_code, array(401, 403), true ) ) {
                        break;
                    }
                }
                return new WP_Error('ghostonix_fib_create_failed', implode( ' || ', array_filter( $errors ) ));
            }

            protected function sync_status( WC_Order $order ) {
                $payment_id = (string) $order->get_meta( self::META_PAYMENT_ID, true );
                if ( '' === $payment_id ) {
                    return new WP_Error('ghostonix_fib_missing_payment_id', __( 'Missing FIB payment ID.', 'ghostonix-connector-for-fib-payments' ));
                }
                $base = (string) $order->get_meta( self::META_API_BASE, true );
                $base = ( '' !== $base ? rtrim( $base, '/' ) : $this->api_base() );
                $token = $this->access_token( $base );
                if ( is_wp_error( $token ) ) {
                    return $token;
                }
                $urls = array($base . '/protected/v1/payments/' . rawurlencode( $payment_id ) . '/status', add_query_arg( 'paymentId', rawurlencode( $payment_id ), $base . '/protected/v1/payments/status' ));
                $status_json = null;
                $last_error = null;
                foreach ( $urls as $url ) {
                    $response = $this->api_json(
                        'GET',
                        $url,
                        $token,
                        null,
                        array(200),
                        'check status'
                    );
                    if ( !is_wp_error( $response ) ) {
                        $status_json = $response;
                        break;
                    }
                    $last_error = $response;
                }
                if ( !is_array( $status_json ) ) {
                    $error = ( $last_error instanceof WP_Error ? $last_error : new WP_Error('ghostonix_fib_status_failed', __( 'FIB status check failed.', 'ghostonix-connector-for-fib-payments' )) );
                    $order->update_meta_data( self::META_ERROR, $error->get_error_message() );
                    $order->save();
                    return $error;
                }
                $status = strtoupper( sanitize_text_field( (string) ($status_json['status'] ?? '') ) );
                $order->update_meta_data( self::META_STATUS, $status );
                $order->update_meta_data( self::META_RAW, $this->safe_json_for_storage( $status_json ) );
                $order->update_meta_data( self::META_ERROR, '' );
                $order->update_meta_data( self::META_VALID_UNTIL, sanitize_text_field( (string) ($status_json['validUntil'] ?? $order->get_meta( self::META_VALID_UNTIL, true )) ) );
                $order->update_meta_data( self::META_PAID_AT, sanitize_text_field( (string) ($status_json['paidAt'] ?? '') ) );
                $order->update_meta_data( self::META_DECLINED_AT, sanitize_text_field( (string) ($status_json['declinedAt'] ?? '') ) );
                $order->update_meta_data( self::META_DECLINE_REASON, sanitize_text_field( (string) ($status_json['decliningReason'] ?? '') ) );
                if ( 'PAID' === $status ) {
                    $valid = $this->validate_paid_amount( $order, $status_json );
                    if ( is_wp_error( $valid ) ) {
                        $order->save();
                        $order->update_status( 'failed', 'FIB validation failed: ' . $valid->get_error_message() );
                        return $valid;
                    }
                    if ( !$order->is_paid() ) {
                        $order->payment_complete( $payment_id );
                        $order->add_order_note( __( 'FIB payment verified.', 'ghostonix-connector-for-fib-payments' ) );
                    }
                    $order->save();
                    return $status_json;
                }
                if ( in_array( $status, array(
                    'DECLINED',
                    'FAILED',
                    'CANCELLED',
                    'CANCELED'
                ), true ) ) {
                    $order->save();
                    if ( !$order->is_paid() && !in_array( $order->get_status(), array('failed', 'cancelled'), true ) ) {
                        $reason = (string) ($status_json['decliningReason'] ?? 'Payment declined.');
                        $order->update_status( 'failed', 'FIB payment declined: ' . sanitize_text_field( $reason ) );
                    }
                    return $status_json;
                }
                $order->save();
                return $status_json;
            }

            protected function validate_paid_amount( WC_Order $order, array $status_json ) {
                $expected_amount = (string) $order->get_meta( self::META_CHARGE_AMOUNT, true );
                $expected_currency = strtoupper( (string) $order->get_meta( self::META_CHARGE_CURRENCY, true ) );
                $amount_obj = ( is_array( $status_json['amount'] ?? null ) ? $status_json['amount'] : array() );
                $monetary_obj = ( is_array( $status_json['monetaryValue'] ?? null ) ? $status_json['monetaryValue'] : array() );
                $returned_amount = (string) ($amount_obj['amount'] ?? $monetary_obj['amount'] ?? (( is_scalar( $status_json['amount'] ?? null ) ? $status_json['amount'] : '' )));
                $returned_currency = strtoupper( (string) ($amount_obj['currency'] ?? $monetary_obj['currency'] ?? $status_json['currency'] ?? '') );
                if ( '' !== $returned_amount && !ghostonix_fib_amount_equal( $returned_amount, $expected_amount ) ) {
                    return new WP_Error('ghostonix_fib_amount_mismatch', 'Amount mismatch. Expected ' . $expected_amount . ' ' . $expected_currency . ', FIB returned ' . $returned_amount . ' ' . $returned_currency . '.');
                }
                if ( '' !== $returned_currency && $returned_currency !== $expected_currency ) {
                    return new WP_Error('ghostonix_fib_currency_mismatch', 'Currency mismatch. Expected ' . $expected_currency . ', FIB returned ' . $returned_currency . '.');
                }
                return true;
            }

            protected function cancel_payment( WC_Order $order ) {
                $payment_id = (string) $order->get_meta( self::META_PAYMENT_ID, true );
                if ( '' === $payment_id ) {
                    return new WP_Error('ghostonix_fib_missing_payment_id', __( 'Missing FIB payment ID.', 'ghostonix-connector-for-fib-payments' ));
                }
                $base = (string) $order->get_meta( self::META_API_BASE, true );
                $base = ( '' !== $base ? rtrim( $base, '/' ) : $this->api_base() );
                $token = $this->access_token( $base );
                if ( is_wp_error( $token ) ) {
                    return $token;
                }
                $urls = array($base . '/protected/v1/payments/' . rawurlencode( $payment_id ) . '/cancel', add_query_arg( 'paymentId', rawurlencode( $payment_id ), $base . '/protected/v1/payments/cancel' ));
                $last_error = null;
                foreach ( $urls as $url ) {
                    $response = $this->api_json(
                        'POST',
                        $url,
                        $token,
                        array(),
                        array(200, 202, 204),
                        'cancel payment'
                    );
                    if ( !is_wp_error( $response ) ) {
                        $order->update_meta_data( self::META_STATUS, 'DECLINED' );
                        $order->update_meta_data( self::META_DECLINE_REASON, 'PAYMENT_CANCELLATION' );
                        $order->save();
                        return true;
                    }
                    $last_error = $response;
                }
                return ( $last_error instanceof WP_Error ? $last_error : new WP_Error('ghostonix_fib_cancel_failed', __( 'FIB cancel failed.', 'ghostonix-connector-for-fib-payments' )) );
            }

            protected function access_token( $base ) {
                $client_id = $this->client_id();
                $client_secret = $this->client_secret();
                if ( '' === $client_id || '' === $client_secret ) {
                    return new WP_Error('ghostonix_fib_missing_credentials', __( 'Missing FIB client ID or client secret.', 'ghostonix-connector-for-fib-payments' ));
                }
                $response = wp_remote_post( $base . '/auth/realms/fib-online-shop/protocol/openid-connect/token', array(
                    'timeout' => 45,
                    'headers' => array(
                        'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8',
                        'Accept'       => 'application/json',
                    ),
                    'body'    => http_build_query( array(
                        'grant_type'    => 'client_credentials',
                        'client_id'     => $client_id,
                        'client_secret' => $client_secret,
                    ), '', '&' ),
                ) );
                if ( is_wp_error( $response ) ) {
                    $this->log( 'auth wp_error: ' . $response->get_error_message() );
                    return $response;
                }
                $code = (int) wp_remote_retrieve_response_code( $response );
                $body = (string) wp_remote_retrieve_body( $response );
                $json = json_decode( $body, true );
                $this->log( 'auth ' . $base . ' HTTP ' . $code );
                if ( 200 !== $code || !is_array( $json ) || empty( $json['access_token'] ) ) {
                    return new WP_Error('ghostonix_fib_auth_failed', 'FIB auth failed HTTP ' . $code . ': ' . $this->api_error_message( $json, $body ), array(
                        'status' => $code,
                    ));
                }
                return (string) $json['access_token'];
            }

            protected function api_json(
                $method,
                $url,
                $token,
                $payload,
                array $accepted,
                $context
            ) {
                $args = array(
                    'method'  => $method,
                    'timeout' => 45,
                    'headers' => array(
                        'Authorization' => 'Bearer ' . $token,
                        'Accept'        => 'application/json',
                    ),
                );
                if ( null !== $payload ) {
                    $args['headers']['Content-Type'] = 'application/json; charset=utf-8';
                    $args['body'] = wp_json_encode( $payload );
                }
                $this->log( $context . ' request ' . $method . ' ' . $url . ' payload: ' . (( null === $payload ? '(none)' : wp_json_encode( $payload ) )) );
                $response = wp_remote_request( $url, $args );
                if ( is_wp_error( $response ) ) {
                    $this->log( $context . ' wp_error: ' . $response->get_error_message() );
                    return $response;
                }
                $code = (int) wp_remote_retrieve_response_code( $response );
                $body = (string) wp_remote_retrieve_body( $response );
                $json = ( '' !== $body ? json_decode( $body, true ) : array() );
                $this->log( $context . ' HTTP ' . $code . ' body: ' . $this->safe_log_body( $body ) );
                if ( !in_array( $code, $accepted, true ) ) {
                    return new WP_Error('ghostonix_fib_api_error', '[' . $context . '] HTTP ' . $code . ': ' . $this->api_error_message( $json, $body ), array(
                        'status' => $code,
                        'body'   => ( $json ?: $body ),
                    ));
                }
                if ( '' === $body || 204 === $code ) {
                    return array();
                }
                if ( !is_array( $json ) ) {
                    return new WP_Error('ghostonix_fib_bad_json', '[' . $context . '] Invalid JSON response.');
                }
                return $json;
            }

            protected function api_error_message( $json, $raw ) {
                if ( is_array( $json ) ) {
                    foreach ( array(
                        'message',
                        'error_description',
                        'error',
                        'detail',
                        'title'
                    ) as $key ) {
                        if ( !empty( $json[$key] ) && is_scalar( $json[$key] ) ) {
                            return (string) $json[$key];
                        }
                    }
                    if ( !empty( $json['errors'] ) && is_array( $json['errors'] ) ) {
                        $parts = array();
                        foreach ( $json['errors'] as $error ) {
                            if ( is_array( $error ) ) {
                                $parts[] = trim( (string) ($error['code'] ?? '') . ' ' . (string) ($error['message'] ?? $error['detail'] ?? $error['title'] ?? '') );
                            } elseif ( is_scalar( $error ) ) {
                                $parts[] = (string) $error;
                            }
                        }
                        $parts = array_filter( $parts );
                        if ( !empty( $parts ) ) {
                            return implode( ' | ', $parts );
                        }
                    }
                    $encoded = wp_json_encode( $json );
                    if ( false !== $encoded && '' !== $encoded ) {
                        return $encoded;
                    }
                }
                $raw = trim( (string) $raw );
                return ( '' !== $raw ? $raw : 'API request failed.' );
            }

            protected function api_base() {
                return ( $this->testmode ? ghostonix_fib_trim_base( $this->get_option( 'test_api_base', 'https://fib.stage.fib.iq' ), 'https://fib.stage.fib.iq' ) : ghostonix_fib_trim_base( $this->get_option( 'live_api_base', 'https://fib.prod.fib.iq' ), 'https://fib.prod.fib.iq' ) );
            }

            protected function api_base_candidates() {
                $primary = $this->api_base();
                if ( !$this->testmode ) {
                    return array($primary);
                }
                $candidates = array($primary, 'https://fib.stage.fib.iq', 'https://fib.stage.fib.iq');
                return array_values( array_unique( array_filter( array_map( 'untrailingslashit', $candidates ) ) ) );
            }

            protected function client_id() {
                return trim( (string) (( $this->testmode ? $this->get_option( 'test_client_id', '' ) : $this->get_option( 'live_client_id', '' ) )) );
            }

            protected function client_secret() {
                return trim( (string) (( $this->testmode ? $this->get_option( 'test_client_secret', '' ) : $this->get_option( 'live_client_secret', '' ) )) );
            }

            protected function callback_url() {
                $url = rest_url( 'ghostonix-fib/v1/callback' );
                $token = $this->ensure_callback_token();
                return add_query_arg( 'token', rawurlencode( $token ), $url );
            }

            protected function best_app_url( WC_Order $order ) {
                foreach ( array(self::META_PERSONAL_LINK, self::META_BUSINESS_LINK, self::META_CORPORATE_LINK) as $key ) {
                    $value = trim( (string) $order->get_meta( $key, true ) );
                    if ( '' !== $value ) {
                        return $value;
                    }
                }
                return '';
            }

            protected function clean_app_link( $url ) {
                $url = trim( (string) $url );
                if ( '' === $url ) {
                    return '';
                }
                $clean = esc_url_raw( $url );
                return ( '' !== $clean ? $clean : $url );
            }

            protected function find_order_by_payment_id( $payment_id ) {
                // phpcs:disable WordPress.DB.SlowDBQuery.slow_db_query_meta_key,WordPress.DB.SlowDBQuery.slow_db_query_meta_value -- Payment callbacks require one lookup by the stored FIB payment ID.
                $orders = wc_get_orders( array(
                    'limit'      => 1,
                    'type'       => 'shop_order',
                    'status'     => array_keys( wc_get_order_statuses() ),
                    'meta_key'   => self::META_PAYMENT_ID,
                    'meta_value' => sanitize_text_field( (string) $payment_id ),
                    'return'     => 'objects',
                ) );
                // phpcs:enable WordPress.DB.SlowDBQuery.slow_db_query_meta_key,WordPress.DB.SlowDBQuery.slow_db_query_meta_value
                return ( !empty( $orders ) && $orders[0] instanceof WC_Order ? $orders[0] : false );
            }

            protected function label( $status ) {
                $status = strtoupper( trim( (string) $status ) );
                if ( 'PAID' === $status ) {
                    return __( 'Paid', 'ghostonix-connector-for-fib-payments' );
                }
                if ( in_array( $status, array(
                    'DECLINED',
                    'FAILED',
                    'CANCELLED',
                    'CANCELED'
                ), true ) ) {
                    return __( 'Declined', 'ghostonix-connector-for-fib-payments' );
                }
                if ( 'UNPAID' === $status || '' === $status ) {
                    return __( 'Waiting for FIB payment confirmation...', 'ghostonix-connector-for-fib-payments' );
                }
                if ( in_array( $status, array('REFUNDED', 'REFENDED'), true ) ) {
                    return __( 'Refunded', 'ghostonix-connector-for-fib-payments' );
                }
                if ( in_array( $status, array('REFUND_REQUESTED', 'REFEND_REQUESTED'), true ) ) {
                    return __( 'Refund requested', 'ghostonix-connector-for-fib-payments' );
                }
                return $status;
            }

            protected function safe_json_for_storage( array $data ) {
                $encoded = wp_json_encode( $this->mask_sensitive_array( $data ) );
                return ( false !== $encoded ? $encoded : '' );
            }

            protected function mask_sensitive_array( array $data ) {
                foreach ( $data as $key => $value ) {
                    $lower_key = strtolower( (string) $key );
                    if ( in_array( $lower_key, array(
                        'access_token',
                        'refresh_token',
                        'client_secret',
                        'secret',
                        'iban',
                        'name',
                        'paidby'
                    ), true ) ) {
                        $data[$key] = '[redacted]';
                        continue;
                    }
                    if ( is_array( $value ) ) {
                        $data[$key] = $this->mask_sensitive_array( $value );
                    }
                }
                return $data;
            }

            protected function safe_log_body( $body ) {
                $body = (string) $body;
                if ( strlen( $body ) > 4000 ) {
                    $body = substr( $body, 0, 4000 ) . '... [trimmed]';
                }
                $decoded = json_decode( $body, true );
                if ( is_array( $decoded ) ) {
                    $encoded = wp_json_encode( $this->mask_sensitive_array( $decoded ) );
                    return ( false !== $encoded ? $encoded : '[redacted]' );
                }
                $body = preg_replace( '/(access_token"?\\s*:?\\s*")([^"]+)(")/i', '$1[redacted]$3', $body );
                return $body;
            }

            protected function log( $message ) {
                if ( !$this->debug ) {
                    return;
                }
                if ( function_exists( 'wc_get_logger' ) ) {
                    wc_get_logger()->debug( (string) $message, array(
                        'source' => $this->id,
                    ) );
                }
            }

        }

        add_filter( 'woocommerce_payment_gateways', function ( $methods ) {
            $methods[] = 'WC_Gateway_Ghostonix_FIB';
            return $methods;
        } );
        add_action( 'rest_api_init', function () {
            if ( class_exists( 'WC_Gateway_Ghostonix_FIB' ) ) {
                $gateway = new WC_Gateway_Ghostonix_FIB();
                $gateway->register_routes();
            }
        }, 99 );
        add_action( 'template_redirect', function () {
            if ( '' === ghostonix_fib_query_arg( 'ghostonix_fib_return' ) || !class_exists( 'WC_Gateway_Ghostonix_FIB' ) ) {
                return;
            }
            $gateway = new WC_Gateway_Ghostonix_FIB();
            $gateway->maybe_handle_return();
        } );
        add_filter( 'woocommerce_available_payment_gateways', function ( $gateways ) {
            if ( is_admin() && !wp_doing_ajax() ) {
                return $gateways;
            }
            if ( !function_exists( 'WC' ) || !WC()->cart ) {
                return $gateways;
            }
            $total = (float) WC()->cart->get_total( 'edit' );
            if ( $total <= 0 && isset( $gateways['ghostonix_fib'] ) ) {
                unset($gateways['ghostonix_fib']);
            }
            if ( isset( $gateways['ghostonix_fib'] ) && 'IQD' !== strtoupper( (string) get_woocommerce_currency() ) ) {
                $allow_non_iqd = false;
                if ( !$allow_non_iqd ) {
                    unset($gateways['ghostonix_fib']);
                }
            }
            return $gateways;
        }, 9999 );
        add_action( 'admin_enqueue_scripts', function ( $hook ) {
            $current_page = sanitize_key( ghostonix_fib_query_arg( 'page' ) );
            $current_tab = sanitize_key( ghostonix_fib_query_arg( 'tab' ) );
            $current_section = sanitize_key( ghostonix_fib_query_arg( 'section' ) );
            $is_gateway_settings = 'wc-settings' === $current_page && 'checkout' === $current_tab && 'ghostonix_fib' === $current_section;
            $is_plugin_page = in_array( $current_page, array('ghostonix-fib-gateway', 'ghostonix-fib-gateway-pricing', 'ghostonix-fib-gateway-contact'), true );
            if ( !$is_gateway_settings && !$is_plugin_page ) {
                return;
            }
            wp_enqueue_style(
                'ghostonix-fib-admin',
                GHOSTONIX_FIB_URL . 'assets/css/admin.css',
                array(),
                GHOSTONIX_FIB_VERSION
            );
            if ( 'ghostonix-fib-gateway-pricing' === $current_page ) {
                $pricing_icon_url = add_query_arg( 'ver', GHOSTONIX_FIB_VERSION, GHOSTONIX_FIB_URL . 'assets/img/ghostonix-fib-icon.png' );
                wp_add_inline_style( 'ghostonix-fib-admin', '.fs-plugin-title-and-logo .fs-plugin-logo{width:64px!important;height:64px!important;object-fit:contain!important;background:transparent!important;opacity:0!important;transition:none!important;}.fs-plugin-title-and-logo .fs-plugin-logo.ghostonix-fib-pricing-logo-ready{opacity:1!important;}' );
                wp_register_script(
                    'ghostonix-fib-pricing-icon',
                    false,
                    array(),
                    GHOSTONIX_FIB_VERSION,
                    true
                );
                wp_enqueue_script( 'ghostonix-fib-pricing-icon' );
                wp_add_inline_script( 'ghostonix-fib-pricing-icon', '(() => { const icon = ' . wp_json_encode( $pricing_icon_url ) . '; const applyIcon = () => { document.querySelectorAll(".fs-plugin-title-and-logo object.fs-plugin-logo, .fs-plugin-title-and-logo img.fs-plugin-logo").forEach((el) => { if ("OBJECT" === el.tagName) { el.setAttribute("data", icon); } else { el.setAttribute("src", icon); } el.classList.add("ghostonix-fib-pricing-logo-ready"); }); }; applyIcon(); document.addEventListener("DOMContentLoaded", applyIcon); const observer = new MutationObserver(applyIcon); observer.observe(document.body, { childList: true, subtree: true }); setTimeout(() => observer.disconnect(), 15000); })();' );
            }
        } );
        add_action( 'admin_init', function () {
            if ( !current_user_can( 'manage_woocommerce' ) ) {
                return;
            }
            if ( 'ghostonix-fib-gateway' === sanitize_key( ghostonix_fib_query_arg( 'page' ) ) ) {
                $is_freemius_activation = false;
                if ( function_exists( 'ghostonix_fib_fs' ) ) {
                    if ( method_exists( ghostonix_fib_fs(), 'is_activation_mode' ) && ghostonix_fib_fs()->is_activation_mode( false ) ) {
                        $is_freemius_activation = true;
                    }
                    if ( method_exists( ghostonix_fib_fs(), 'is_pending_activation' ) && ghostonix_fib_fs()->is_pending_activation() ) {
                        $is_freemius_activation = true;
                    }
                }
                foreach ( array(
                    'fs_action',
                    'pending_activation',
                    'purchase_completed',
                    'plugin_id'
                ) as $freemius_param ) {
                    if ( '' !== ghostonix_fib_query_arg( $freemius_param ) ) {
                        $is_freemius_activation = true;
                        break;
                    }
                }
                if ( !$is_freemius_activation ) {
                    wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=checkout&section=ghostonix_fib' ) );
                    exit;
                }
            }
        } );
        add_action( 'admin_menu', function () {
            add_menu_page(
                __( 'FIB Payments', 'ghostonix-connector-for-fib-payments' ),
                __( 'FIB Payments', 'ghostonix-connector-for-fib-payments' ),
                'manage_woocommerce',
                'ghostonix-fib-gateway',
                function () {
                    echo '<div class="wrap"><h1>' . esc_html__( 'FIB Payments', 'ghostonix-connector-for-fib-payments' ) . '</h1><p><a class="button button-primary" href="' . esc_url( admin_url( 'admin.php?page=wc-settings&tab=checkout&section=ghostonix_fib' ) ) . '">' . esc_html__( 'Open FIB payment settings', 'ghostonix-connector-for-fib-payments' ) . '</a></p></div>';
                },
                'dashicons-money-alt',
                56
            );
        } );
    } );
}
