<?php
namespace WalletUpPro;

use WalletUpPro\Core\BaseSingleton;
use WalletUpPro\Core\ServiceContainer;
use WalletUpPro\Core\PaymentRegistry;
use WalletUpPro\Core\Admin\AdminManager;
use WalletUpPro\Core\Admin\TransactionAdmin;
use WalletUpPro\Core\Installation\InstallationHandler;
use WalletUpPro\Core\Database\DatabaseManager;
use WalletUpPro\Core\Error\ErrorHandler;
use WalletUpPro\Core\Migration\MigrationManager;
use WalletUpPro\Core\Assets\AssetManager;
use WalletUpPro\Core\Display\DisplayHandler;
use WalletUpPro\Services\QRCodeService;
use WalletUpPro\WooCommerce\WooCommerceIntegration;
use WalletUpPro\WpForms\Forms\WPFormsService;
use WalletUpPro\Core\Donations\DonationHandler;
use WalletUpPro\Core\Donations\DonationPageHandler;
use WalletUpPro\Core\Payers\PayerHandler;
use WalletUpPro\Core\Payers\PayerPageHandler;
use WalletUpPro\Services\URLShortenerService;
use WalletUpPro\Core\Utilities\TimestampUtility;
use WalletUpPro\ZenithQR\ZenithQRIntegration;
use WalletUpPro\Core\Translation\EnterpriseTranslationManager;
use WalletUpPro\Core\Admin\TranslationAdmin;
use WalletUpPro\Core\Admin\TranslationHelp;
//use WalletUpPro\Admin\PayPalAdminServiceProvider;
//use WalletUpPro\Core\Cron\WalletOptionsCleanup;
use WalletUpPro\Core\Cron\GeoIPUpdater;


// Use Automattic's WooCommerce CacheHelper directly
use Automattic\WooCommerce\Utilities\CacheHelper as WC_Cache_Helper;
use Exception;
// Security Section - Commented out but might be used in future
/*use WalletUpPro\Core\Security\AccessControl;
use WalletUpPro\Core\Security\AuditLogger;
use WalletUpPro\Core\Security\DataEncryption;
use WalletUpPro\Core\Security\InputValidator;
use WalletUpPro\Core\Security\OutputSanitizer;
use WalletUpPro\Core\Security\PaymentDataProtection;
use WalletUpPro\Core\Security\RateLimiter;
use WalletUpPro\Core\Security\SecurityManager;
use WalletUpPro\Core\Security\SecurityServiceProvider; */
use WalletUpPro\Core\RewriteRulesManager;

if (!defined('ABSPATH')) {
    exit; // Exit if accessed directly.
}

/**
 * Main plugin class for WalletUpPro, managing initialization, services, and WooCommerce integration.
 */
class Plugin extends BaseSingleton
{
    /**
     * @var ServiceContainer Service container instance
     */
    private $container;

    /**
     * @var DatabaseManager Database manager instance
     */
    private $db;

    /**
     * @var PaymentRegistry Payment registry instance
     */
    private $registry;

    /**
     * @var AdminManager Admin manager instance
     */
    private $admin;

    /**
     * @var ErrorHandler Error handler instance
     */
    private $errorHandler;

    /**
     * @var bool Guards the once-per-request cache purge after a settings save.
     */
    private static $cachePurgeScheduled = false;

    /**
     * @var MigrationManager Migration manager instance
     */
    private $migrationManager;

    /**
     * @var ZenithQRIntegration
     */
    private $zenithQRIntegration;

    // /**
    //  * @var PayPalAdminServiceProvider PayPal admin service provider
    //  */
    // private $paypalAdminService;

    /**
     * @var AssetManager Asset manager instance
     */
    private $assetManager;

    /**
     * @var DisplayHandler Display handler instance
     */
    private $displayHandler;

    /**
     * @var QRCodeService QR code service instance
     */
    private $qrService;

    /**
     * @var bool Installation status
     */
    private $installed = false;

    /**
     * @var string Table name
     */
    private $table_name;

    /**
     * @var URLShortenerService URL shortener service
     */
    private $urlShortener;

    /**
     * @var mixed Cache instance
     */
    private $cache;

    /**
     * @var string Clicks table name
     */
    private $clicks_table;

    /**
     * Constructor for the Plugin class.
     * 
     * Initializes components and hooks actions/filters.
     */
    protected function __construct()
    {
        try {
            parent::__construct();

            register_deactivation_hook(WALLET_UP_FILE, [$this, 'deactivate']);

            // Declare WooCommerce compatibility early, before WooCommerce init
            add_action('before_woocommerce_init', [$this, 'declareWooCommerceCompatibility']);

            add_action('plugins_loaded', [$this, 'initializeComponents'], 20);

        } catch (Exception $e) {
            if (isset($this->errorHandler)) {
                $this->errorHandler->log('Constructor initialization failed: ' . $e->getMessage());
            }
            add_action('admin_notices', function () use ($e) {
                printf(
                    '<div class="notice notice-error"><p>%s</p></div>',
                    esc_html('WalletUp Pro: Initialization error — ' . $e->getMessage())
                );
            });
        }
    }

    /**
     * Handles plugin activation process
     */
    public function activate(): void
    {
        try {
            if (!$this->isInitialized()) {
                $this->initialize();
            }

            $this->checkRequirements();

            $installer = new InstallationHandler($this->db, $this->errorHandler);
            $installer->install();

            $this->createDefaultOptions();

            update_option('wallet_up_flush_rules', 'yes');

            if (!$this->installed) {
                $tableName = $this->getTableName();
                $this->migrationManager = new MigrationManager($this->db, $this->errorHandler, $tableName);
                $this->migrationManager->runMigrations();
            }

            flush_rewrite_rules();
            $this->installed = true;
            delete_option('wallet_up_quick_access_count');

            update_option('wallet_up_activated', 'yes');
            update_option('wallet_up_version', WALLET_UP_VERSION);

        } catch (Exception $e) {
            $this->errorHandler->log('Activation failed: ' . $e->getMessage());
            $this->deactivate();
            throw $e;
        }
    }

    protected function initialize(): void
    {
        try {
            $this->errorHandler = ErrorHandler::getInstance();
            $this->container = ServiceContainer::getInstance();
            $this->db = new DatabaseManager($this->getTableName());
            $this->assetManager = AssetManager::getInstance();
            $this->displayHandler = DisplayHandler::getInstance();

            // Initialize AnalyticsHandler before PaymentRegistry (premium only)
            if (wallet_up_fs()->can_use_premium_code__premium_only()) {
                $analyticsHandler = \WalletUpPro\Core\Analytics\AnalyticsHandler::getInstance();
            }

            // QR scan redirect — registered unconditionally so payment QR codes
            // resolve on every site/subsite regardless of license. Scan analytics
            // recording inside the handler stays premium-gated. The rewrite rule
            // serves the cache-bulletproof pretty permalink form; the query-string
            // form still works for legacy QRs already in the wild.
            \WalletUpPro\Services\QRCodeService::registerCacheBypass();
            // Rewrite rule + query var registration must wait until $wp_rewrite is up
            // (it isn't initialized at plugins_loaded; init is the first safe hook).
            add_action('init', ['\\WalletUpPro\\Services\\QRCodeService', 'registerScanRewriteRule'], 0);
            // Query-string form (?wup_scan=) — $_GET is populated at init.
            add_action('init', ['\\WalletUpPro\\Services\\QRCodeService', 'handleScanRedirect'], 1);
            // Pretty permalink form — rewrite-injected query vars arrive at parse_request.
            // The handler is idempotent (it bails if method/encoded_url aren't set) so running
            // both hooks is safe.
            add_action('parse_request', ['\\WalletUpPro\\Services\\QRCodeService', 'handleScanRedirect'], 0);

            // One-shot rewrite flush so the new /wallet-up/scan/ rule takes effect on upgrade.
            if (get_option('wallet_up_scan_rewrite_v1') !== 'yes') {
                add_action('wp_loaded', static function () {
                    flush_rewrite_rules(false);
                    update_option('wallet_up_scan_rewrite_v1', 'yes', false);
                });
            }

            try {
                $this->qrService = QRCodeService::getInstance();
            } catch (Exception $e) {
                $this->errorHandler->log('QR service unavailable (will use fallback): ' . $e->getMessage());
            }
            $this->registry = PaymentRegistry::getInstance();

            // Purge host/page caches after a payment-settings change so the new
            // configuration shows immediately. SiteGround, LiteSpeed, WP Rocket
            // and friends will otherwise serve a stale snapshot — the "I changed
            // it but it isn't showing / a method vanished" reports. Debounced to
            // one purge per request via shutdown; a no-op when no cache plugin is
            // present. Matches every wallet_up*/walletup* option plus the WC
            // gateway settings.
            add_action('updated_option', function ($option) {
                $option = (string) $option;
                if (strpos($option, 'wallet_up') !== 0
                    && strpos($option, 'walletup') !== 0
                    && $option !== 'woocommerce_wallet_up_settings') {
                    return;
                }
                if (self::$cachePurgeScheduled) {
                    return;
                }
                self::$cachePurgeScheduled = true;
                add_action('shutdown', [self::class, 'purgePaymentCaches']);
            }, 10, 1);

            if (wallet_up_fs()->can_use_premium_code__premium_only()) {
                $translationManager = EnterpriseTranslationManager::getInstance();
                $this->container->set('translation_manager', $translationManager);

                if (is_admin()) {
                    new TranslationAdmin();
                    new TranslationHelp();
                }
            }

            new \WalletUpPro\API\QRCodeEndpoint();

            // premium only — advanced shortcode features
            if (wallet_up_fs()->can_use_premium_code__premium_only()) {
                new \WalletUpPro\Core\Shortcodes\QRCodeShortcode();
            }

            if (wallet_up_fs()->can_use_premium_code__premium_only()) {
                \WalletUpPro\Core\Crypto\CryptoConverter::getInstance();
                new \WalletUpPro\Core\Crypto\CryptoRateAjaxHandler();
            }

            $rewriteManager = RewriteRulesManager::getInstance();
            $this->container->set('rewrite_manager', $rewriteManager);

            $premiumManager = \WalletUpPro\Core\Manager\PremiumFeaturesManager::getInstance();
            $this->container->set('premium_manager', $premiumManager);

            if (wallet_up_fs()->can_use_premium_code__premium_only()) { // Fully premium

                $this->initializeDonationSystem();
                $this->initializeDisplaySettings();
                $this->initializePayerSystem();
                $this->zenithQRMenu();


                $currentVersion = get_option('wallet_up_version', '0');
                $pluginVersion = WALLET_UP_PRO_VERSION;
                
                if (!$this->db->tableExists() || version_compare($currentVersion, $pluginVersion, '<')) {
                    $installer = new InstallationHandler($this->db, $this->errorHandler);
                    $installer->install();
                    update_option('wallet_up_version', $pluginVersion);
                    $this->installed = true;
                } else {
                    $this->installed = true;
                }
            }

            // Initialize enhanced PayPal admin services
           // $this->initializePayPalAdminServices();

            $this->initializeServices();
            $this->runMigrations();

            // Initialize merchant auto-provisioning with pay.walletup.app
            if (class_exists(\WalletUpPro\Core\Payments\MerchantProvisioning::class)) {
                \WalletUpPro\Core\Payments\MerchantProvisioning::getInstance()->init();
            }

           
        } catch (Exception $e) {
            $this->errorHandler->log('Plugin initialization failed: ' . $e->getMessage());
            throw $e;
        }
    }

    /**
     * Initializes components for the plugin
     */
    public function initializeComponents(): void
    {
        try {
            if (!$this->isInitialized()) {
                $this->initialize();
            }

            if (wallet_up_fs()->can_use_premium_code__premium_only()) {
                try {
                    $this->urlShortener = new URLShortenerService();
                } catch (Exception $e) {
                    $this->errorHandler->log('URLShortenerService init failed: ' . $e->getMessage());
                }
                try {
                    $this->zenithQRIntegration = new ZenithQRIntegration();
                } catch (Exception $e) {
                    $this->errorHandler->log('ZenithQRIntegration init failed: ' . $e->getMessage());
                }
            }

            // Initialize admin if in admin context
            if (is_admin()) {
                $this->admin = new AdminManager(
                    $this->registry,
                    $this->assetManager,
                    $this->db,
                    $this->qrService
                );

                // Register V2 admin submenus (premium only)
                if (wallet_up_fs()->can_use_premium_code__premium_only()) {
                    if (get_option('wallet_up_admin_v2', 'yes') === 'yes') {
                        add_action('admin_menu', [\WalletUpPro\Core\Admin\AdminV2MenuRegistrar::class, 'register'], 11);
                    }

                    // Initialize Transaction Admin for payment management
                    TransactionAdmin::getInstance();
                }

                $redirect = get_transient('wallet_up_activation_redirect');
                if ($redirect && is_admin() && !wp_doing_ajax()) {
                }
            }

            // Initialize GeoIP auto-updater (premium only)
            if (wallet_up_fs()->can_use_premium_code__premium_only()) {
                GeoIPUpdater::getInstance();
            }
            
            $this->registerAjaxHandlers();

        } catch (Exception $e) {
            if (isset($this->errorHandler)) {
                $this->errorHandler->log('Component initialization failed: ' . $e->getMessage());
            }
            // Show admin notice instead of crashing the site
            add_action('admin_notices', function () use ($e) {
                printf(
                    '<div class="notice notice-error"><p>%s</p></div>',
                    esc_html('WalletUp Pro: Component initialization failed — ' . $e->getMessage())
                );
            });
        }
    }

   /*  private function initializePayPalAdminServices(): void
    {
        try {
            // Initialize PayPal admin service provider
            $this->paypalAdminService = PayPalAdminServiceProvider::getInstance();
            $this->container->set('paypal_admin', $this->paypalAdminService);
            
                'handler_status' => $this->paypalAdminService->getHandlerStatus()
            ]), 'Info');
            
        } catch (Exception $e) {
                'fallback' => 'legacy_handlers_will_be_used',
                'error' => $e->getTraceAsString()
            ]), 'Error');
            
            // Continue with legacy handlers - no need to fail completely
            $this->paypalAdminService = null;
        }
    } */

    /**
     * Sets up services within the service container.
     */
    private function initializeServices(): void
    {
        $this->container->set('database', $this->db);
        $this->container->set('qr', $this->qrService);
        $this->container->set('registry', $this->registry);
        $this->container->set('asset_manager', $this->assetManager);
        $this->container->set('display_handler', $this->displayHandler);
        // $this->container->set('security', new SecurityServiceProvider($this->container));

        $theme_manager = \WalletUpPro\Core\Admin\Themes\AdminThemeManager::getInstance();
        $this->container->set('theme_manager', $theme_manager);

        if (wallet_up_fs()->can_use_premium_code__premium_only()) {
            $urlHandler = \WalletUpPro\Core\URL\URLHandler::getInstance();
            $this->container->set('url_shortener', $urlHandler->getShortener());
        }

        // ZenithQR is initialized via zenithQR() method which loads the loader file

        // WPForms integration (premium only — WPFormsServiceCheckout is stripped)
        if (wallet_up_fs()->can_use_premium_code__premium_only()) {
            $wpformsService = WPFormsService::getInstance($this->errorHandler);
            if ($wpformsService->isActive()) {
                $this->container->set('wpforms', $wpformsService);
                $wpformsService->init();
            }
        }

        // WooCommerce integration (premium only)
        if (wallet_up_fs()->can_use_premium_code__premium_only()) {
            if (class_exists('WooCommerce')) {
                $this->container->set('wc_integration', WooCommerceIntegration::getInstance());
                \WalletUpPro\WooCommerce\OrderStatusBridge::init();
                if (class_exists(\WalletUpPro\Integrations\ZI2NexusBridge::class)) {
                    \WalletUpPro\Integrations\ZI2NexusBridge::init();
                }
            }
        }

        // Schedule expired payment cleanup (runs twice daily)
        if (!wp_next_scheduled('walletup_clean_expired_payments')) {
            wp_schedule_event(time(), 'twicedaily', 'walletup_clean_expired_payments');
        }
        add_action('walletup_clean_expired_payments', function () {
            try {
                \WalletUpPro\Services\PaymentProcessor::getInstance()->cleanExpiredPayments();
            } catch (\Exception $e) {
                // Silently fail — cron cleanup is non-critical
            }
        });

        // Onboarding (available to all tiers)
        if (is_admin() && class_exists(\WalletUpPro\Core\Admin\OnboardingHandler::class)) {
            \WalletUpPro\Core\Admin\OnboardingHandler::init();
            if (class_exists(\WalletUpPro\Core\Admin\Notices\OnboardingBanner::class)) {
                \WalletUpPro\Core\Admin\Notices\OnboardingBanner::init();
            }
            if (class_exists(\WalletUpPro\Core\Onboarding\PaymentPageGenerator::class)) {
                \WalletUpPro\Core\Onboarding\PaymentPageGenerator::init();
            }
            if (class_exists(\WalletUpPro\Core\Admin\Notices\IntegrationDetector::class)) {
                \WalletUpPro\Core\Admin\Notices\IntegrationDetector::init();
            }
            if (class_exists(\WalletUpPro\Core\Admin\Integrations\OneClickAttach::class)) {
                \WalletUpPro\Core\Admin\Integrations\OneClickAttach::init();
            }
        }

        // Gutenberg blocks (available to all tiers; method availability gated by build)
        if (class_exists(\WalletUpPro\Core\Blocks\BlockRegistrar::class)) {
            \WalletUpPro\Core\Blocks\BlockRegistrar::init();
        }

        // Premium-only service initialization
        if (wallet_up_fs()->can_use_premium_code__premium_only()) {
            // Email template AJAX handlers
            \WalletUpPro\Core\Emails\EmailTemplateHandler::init();

            // Donor management AJAX handlers
            \WalletUpPro\Core\Donors\DonorHandler::init();

            // Donation system (campaigns, forms, thermometer, setup check)
            \WalletUpPro\Core\Donations\DonationSystemHandler::init();

            // Reports
            require_once __DIR__ . "/Core/Reports/ReportsHandler.php";
            \WalletUpPro\Core\Reports\ReportsHandler::init();
            add_action("wallet_up_send_scheduled_report", ["\WalletUpPro\Core\Reports\ReportsHandler", "processScheduledReports"]);

            // Stripe + PayPal gateway handlers
            \WalletUpPro\Core\Payments\PaymentGatewayHandler::init();

            // Register webhook endpoints for Cash App Pay API and Venmo/Braintree
            add_action('rest_api_init', function () {
                register_rest_route('walletup/v1', '/webhook/cashapp', [
                    'methods' => 'POST',
                    'callback' => function (\WP_REST_Request $request) {
                        try {
                            $api = \WalletUpPro\Payments\CashAppPayAPI::getInstance();
                            $signature = $request->get_header('X-Signature') ?? '';
                            $payload = $request->get_json_params();

                            if ($api->processWebhook($payload, $signature)) {
                                return new \WP_REST_Response(['status' => 'ok'], 200);
                            }
                            return new \WP_REST_Response(['status' => 'error'], 400);
                        } catch (\Exception $e) {
                            return new \WP_REST_Response(['status' => 'error', 'message' => $e->getMessage()], 500);
                        }
                    },
                    'permission_callback' => '__return_true',
                ]);

                register_rest_route('walletup/v1', '/webhook/venmo', [
                    'methods' => 'POST',
                    'callback' => function (\WP_REST_Request $request) {
                        try {
                            $api = \WalletUpPro\Payments\VenmoBraintreeAPI::getInstance();
                            $btSignature = sanitize_text_field($request->get_param('bt_signature') ?? '');
                            $btPayload = $request->get_param('bt_payload') ?? '';

                            if ($api->processWebhook($btSignature, $btPayload)) {
                                return new \WP_REST_Response(['status' => 'ok'], 200);
                            }
                            return new \WP_REST_Response(['status' => 'error'], 400);
                        } catch (\Exception $e) {
                            return new \WP_REST_Response(['status' => 'error', 'message' => $e->getMessage()], 500);
                        }
                    },
                    'permission_callback' => '__return_true',
            ]);
        });
        } // end premium-only service initialization
    }

    /**
     * Gets the database table name for analytics.
     * 
     * @return string The table name prefixed with WordPress database prefix.
     */
    private function getTableName(): string
    {
        global $wpdb;
        return $wpdb->prefix . 'wallet_up_analytics';
    }

    // REMOVED: Old registerGateway method - now handled by WooCommerceIntegration

    // REMOVED: Old blocks support method - now handled by WalletUpProGateway using official pattern

    private function initializeDonationSystem(): void
    {
        if (wallet_up_fs()->can_use_premium_code__premium_only()) {
            try {
                global $wpdb;
                $donationDb = new DatabaseManager($wpdb->prefix . 'wallet_up_donations');

                $donationHandler = DonationHandler::getInstance();
                $donationPageHandler = DonationPageHandler::getInstance();

                $this->container->set('donation_handler', $donationHandler);
                $this->container->set('donation_page_handler', $donationPageHandler);

                // Add donation database table - only check once per request
                add_action('init', function () {
                    // Only create tables if they don't exist to avoid performance issues
                    if (!$this->areDonationTablesCreated()) {
                        $this->createDonationTables();
                    }
                    if (!\WalletUpPro\Core\Subscriptions\SubscriptionManager::tableExists()) {
                        \WalletUpPro\Core\Subscriptions\SubscriptionManager::createTable();
                    }
                    \WalletUpPro\Core\Subscriptions\SubscriptionManager::getInstance();
                });

                add_action('init', [$this, 'registerDonationEndpoints']);
                add_action('wp_enqueue_scripts', [$this, 'enqueueDonationAssets']);

                if (get_option('wallet_up_admin_v2', 'yes') !== 'yes') {
                    add_action('admin_menu', function () {
                        add_submenu_page(
                            'wallet-up',
                            esc_html__('Donations', 'walletup'),
                            esc_html__('Donations', 'walletup'),
                            'manage_options',
                            'wallet-up-donations',
                            [$this, 'renderDonationSettingsPage']
                        );
                    });
                }

            } catch (Exception $e) {
                $this->errorHandler->log('Donation system initialization failed: ' . $e->getMessage());
                throw $e;
            }
        }
    }

    /**
     * Create donation-related database tables
     * 
     * Fixed to use proper WordPress database API and sanitization
     */
    private function createDonationTables(): void
    {
        if (wallet_up_fs()->can_use_premium_code__premium_only()) { // Fully premium

            global $wpdb;
            $charset_collate = $wpdb->get_charset_collate();

            $donationTrackingTable = $wpdb->prefix . 'wallet_up_donations';

            // Using WordPress dbDelta for safe table creation
            require_once(ABSPATH . 'wp-admin/includes/upgrade.php');

            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table name is safely derived from wpdb prefix.
            $sql = "CREATE TABLE {$donationTrackingTable} (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            donation_id varchar(50) NOT NULL,
            payment_method varchar(50) NOT NULL,
            amount decimal(10,2) NOT NULL,
            currency varchar(10) DEFAULT 'USD',
            status varchar(20) NOT NULL,
            donor_ip varchar(45),
            donor_email varchar(100),
            donor_name varchar(100),
            donor_phone varchar(30),
            message text,
            campaign_id varchar(64),
            form_id varchar(64),
            is_recurring tinyint(1) DEFAULT 0,
            is_anonymous tinyint(1) DEFAULT 0,
            metadata text,
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY  (id),
            KEY donation_id (donation_id),
            KEY payment_method (payment_method),
            KEY status (status),
            KEY campaign_id (campaign_id),
            KEY created_at (created_at)
        ) $charset_collate;";

            dbDelta($sql);
        }
    }
    public function registerDonationEndpoints(): void
    {
        if (wallet_up_fs()->can_use_premium_code__premium_only()) { // Fully premium

         // Rewrite rules are now handled by RewriteRulesManager

        }
    }

    /**
     * Enqueue donation-specific assets
     */
    public function enqueueDonationAssets(): void
    {
        if (wallet_up_fs()->can_use_premium_code__premium_only()) { // Fully premium

            if (get_query_var('wallet_up_donation') || is_page('donate')) {

                $css_path = WALLET_UP_URL . 'assets/css/donations/donations-qr.css';
                $version = file_exists($css_path) ? filemtime($css_path) : WALLET_UP_VERSION;
                wp_enqueue_style(
                    'wallet-up-donations',
                    WALLET_UP_URL . 'assets/css/donations/donations-qr.css',
                    [],
                    $version
                );

            }
        }
    }

    public function renderDonationSettingsPage(): void
    {
        if (wallet_up_fs()->can_use_premium_code__premium_only()) { // Fully premium

            if (!current_user_can('manage_options')) {
                return;
            }

            ?>
            <div class="wrap">
                <!-- <h1><?php echo esc_html__('Donations', 'walletup'); ?></h1> -->
                <div id="wallet-up-admin-root" data-initial-tab="donations"></div>
            </div>
            <?php
        }
    }
    private function initializeDisplaySettings(): void
    {
        if (wallet_up_fs()->can_use_premium_code__premium_only()) { // Fully premium

            try {
                if (get_option('wallet_up_admin_v2', 'yes') !== 'yes') {
                    // Add menu callback for QR Settings (Display)
                    add_action('admin_menu', function () {
                        add_submenu_page(
                            'wallet-up',
                            esc_html__('QR Settings', 'walletup'),
                            esc_html__('QR Settings', 'walletup'),
                            'manage_options',
                            'wallet-up-qr-display',
                            [$this, 'renderQRSettingsPage']
                        );
                    });

                    // Add menu callback for QR Analytics
                    add_action('admin_menu', function () {
                        add_submenu_page(
                            'wallet-up',
                            esc_html__('QR Analytics', 'walletup'),
                            esc_html__('QR Analytics', 'walletup'),
                            'manage_options',
                            'wallet-up-qr-analytics',
                            [$this, 'renderQRAnalyticsPage']
                        );
                    });
                }
            } catch (Exception $e) {
                $this->errorHandler->log('Menu system initialization failed: ' . $e->getMessage());
                throw $e;
            }
        }
    }
    public function renderQRSettingsPage(): void
    {
        if (wallet_up_fs()->can_use_premium_code__premium_only()) { // Fully premium

            if (!current_user_can('manage_options')) {
                wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'walletup'));
                return;
            }

            ?>
            <div class="wrap">
                <!-- <h1><?php echo esc_html__('QR Settings', 'walletup'); ?></h1> -->
                <div id="wallet-up-admin-root" data-initial-tab="display"></div>
            </div>
            <?php
        }
    }

    public function renderQRAnalyticsPage(): void
    {
        if (wallet_up_fs()->can_use_premium_code__premium_only()) { // Fully premium

            if (!current_user_can('manage_options')) {
                wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'walletup'));
                return;
            }

            ?>
            <div class="wrap">
                <!-- <h1><?php echo esc_html__('QR Analytics', 'walletup'); ?></h1> -->
                <div id="wallet-up-admin-root" data-initial-tab="analytics"></div>
            </div>
            <?php
        }
    }

    private function zenithQRMenu(): void {
        if (wallet_up_fs()->can_use_premium_code__premium_only()) {
            if (file_exists(WALLET_UP_PRO_BASE_DIR . '/zenithQR/zenith-qr-loader.php')) {
                require_once WALLET_UP_PRO_BASE_DIR . '/zenithQR/zenith-qr-loader.php';
            }
        }
    }

    private function initializePayerSystem(): void
    {
        if (wallet_up_fs()->can_use_premium_code__premium_only()) { // Fully premium

            try {
                global $wpdb;
                $payerDb = new DatabaseManager($wpdb->prefix . 'wallet_up_payers');

                $payerHandler = PayerHandler::getInstance();
                $payerPageHandler = PayerPageHandler::getInstance();

                $this->container->set('payer_handler', $payerHandler);
                $this->container->set('payer_page_handler', $payerPageHandler);

                // Add payer database table - only check once per request
                add_action('init', function () {
                    // Only create tables if they don't exist to avoid performance issues
                    if (!$this->arePayerTablesCreated()) {
                        $this->createPayerTables();
                    }
                });

                add_action('init', [$this, 'registerPayerEndpoints']);
                add_action('wp_enqueue_scripts', [$this, 'enqueuePayerAssets']);

                if (get_option('wallet_up_admin_v2', 'yes') !== 'yes') {
                    // Add menu callback for payer settings
                    add_action('admin_menu', function () {
                        add_submenu_page(
                            'wallet-up',
                            esc_html__('Business Card', 'walletup'),
                            esc_html__('Business Card', 'walletup'),
                            'manage_options',
                            'wallet-up-business-card',
                            [$this, 'renderBusinessCardPage']
                        );
                    });

                    // Add menu callback for Shortcodes
                    add_action('admin_menu', function () {
                        add_submenu_page(
                            'wallet-up',
                            esc_html__('Shortcodes', 'walletup'),
                            esc_html__('Shortcodes', 'walletup'),
                            'manage_options',
                            'wallet-up-shortcodes',
                            [$this, 'renderShortcodesPage']
                        );
                    });

                    // Add menu callback for QR & URL Shortener
                    add_action('admin_menu', function () {
                        add_submenu_page(
                            'wallet-up',
                            esc_html__('URL Shortener', 'walletup'),
                            esc_html__('URL Shortener', 'walletup'),
                            'manage_options',
                            'wallet-up-qr-shortener',
                            [$this, 'renderQRShortenerPage']
                        );
                    });
                }
            } catch (Exception $e) {
                $this->errorHandler->log('Payer system initialization failed: ' . $e->getMessage());
                throw $e;
            }
        }
    }

    /**
     * Create payer-related database tables
     * 
     * Fixed to use proper WordPress database API and sanitization
     */
    private function createPayerTables(): void
    {
        if (wallet_up_fs()->can_use_premium_code__premium_only()) { // Fully premium

            global $wpdb;
            $charset_collate = $wpdb->get_charset_collate();

            $payerTrackingTable = $wpdb->prefix . 'wallet_up_payers';

            // Using WordPress dbDelta for safe table creation
            require_once(ABSPATH . 'wp-admin/includes/upgrade.php');

            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table name is safely derived from wpdb prefix.
            $sql = "CREATE TABLE {$payerTrackingTable} (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            payer_id varchar(50) NOT NULL,
            payment_method varchar(50) NOT NULL,
            amount decimal(10,2) NOT NULL,
            status varchar(20) NOT NULL,
            payer_ip varchar(45),
            payer_email varchar(100),
            payer_name varchar(100),
            metadata text,
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY  (id),
            KEY payer_id (payer_id),
            KEY payment_method (payment_method),
            KEY status (status),
            KEY created_at (created_at)
        ) $charset_collate;";

            dbDelta($sql);
        }
    }

    public function registerPayerEndpoints(): void
    {
        if (wallet_up_fs()->can_use_premium_code__premium_only()) { // Fully premium

            // Rewrite rules are now handled by RewriteRulesManager

        }
    }
    /**
     * Enqueue payer-specific assets
     */
    public function enqueuePayerAssets(): void
    {
        if (wallet_up_fs()->can_use_premium_code__premium_only()) { // Fully premium

            if (get_query_var('wallet_up_payer') || is_page('pay')) {

                $css_path = WALLET_UP_URL . 'assets/css/payers/payers-qr.css';
                $version = file_exists($css_path) ? filemtime($css_path) : WALLET_UP_VERSION;
                wp_enqueue_style(
                    'wallet-up-payers',
                    WALLET_UP_URL . 'assets/css/payers/payers-qr.css',
                    [],
                    $version
                );

            }
        }
    }

    public function renderPayerSettingsPage(): void
    {
        if (wallet_up_fs()->can_use_premium_code__premium_only()) { // Fully premium

            if (!current_user_can('manage_options')) {
                return;
            }

            ?>
            <div class="wrap">
                <!-- <h1> <?php echo esc_html__('URL Shortener', 'walletup'); ?></h1> -->
                <div id="wallet-up-admin-root" data-initial-tab="shorts"></div>
            </div>
            <?php
        }
    }

    public function renderBusinessCardPage(): void
    {
        if (wallet_up_fs()->can_use_premium_code__premium_only()) {
            if (!current_user_can('manage_options')) {
                return;
            }
            ?>
            <div class="wrap">
                <div id="wallet-up-admin-root" data-initial-tab="shorts" data-initial-section="business-card"></div>
            </div>
            <?php
        }
    }

    public function renderShortcodesPage(): void
    {
        if (wallet_up_fs()->can_use_premium_code__premium_only()) {
            if (!current_user_can('manage_options')) {
                return;
            }
            ?>
            <div class="wrap">
                <div id="wallet-up-admin-root" data-initial-tab="shortcodes"></div>
            </div>
            <?php
        }
    }

    public function renderQRShortenerPage(): void
    {
        if (wallet_up_fs()->can_use_premium_code__premium_only()) {
            if (!current_user_can('manage_options')) {
                return;
            }
            ?>
            <div class="wrap">
                <div id="wallet-up-admin-root" data-initial-tab="shorts" data-initial-section="qr-shortener"></div>
            </div>
            <?php
        }
    }

    /**
     * Plugin deactivation handler
     */
    public function deactivate(): void
    {
        try {
            if (class_exists('WooCommerce')) {
                if (class_exists('WC_Cache_Helper')) {
                    \WC_Cache_Helper::get_transient_version('payment_gateways', true);
                    \WC_Cache_Helper::get_transient_version('shipping', true);
                    delete_transient('wc_blocks_payment_method_type_registry');
                }

                if ($this->container->has('woocommerce')) {
                    $wc = $this->container->get('woocommerce');
                    if (method_exists($wc, 'reset')) {
                        $wc::reset();
                    }
                }
                $this->cleanupDonationData();

                $this->cleanupPayerData();

                if ($this->container->has('theme_manager')) {
                    $this->container->get('theme_manager')->cleanup();
                }

                if (class_exists('Automattic\WooCommerce\Blocks\Integrations\IntegrationRegistry')) {
                    global $woocommerce_blocks_integration_registry;
                    if (
                        isset($woocommerce_blocks_integration_registry) &&
                        method_exists($woocommerce_blocks_integration_registry, 'is_registered')
                    ) {
                        if ($woocommerce_blocks_integration_registry->is_registered('wallet_up')) {
                            $woocommerce_blocks_integration_registry->unregister('wallet_up');
                        }
                    }
                }
            }

            wp_clear_scheduled_hook('wallet_up_cleanup_analytics');
            $this->clearTransients();

            wp_cache_delete('woocommerce_payment_gateways', 'options');
            delete_transient('wc_gateway_wallet_up_initialized');

            flush_rewrite_rules();
            $this->resetSingletons();

        } catch (Exception $e) {
            $this->errorHandler->log('Deactivation failed: ' . $e->getMessage());
        }
    }

    /**
     * Cleanup donation data on deactivation if configured
     */
    private function cleanupDonationData(): void
    {
        if (wallet_up_fs()->can_use_premium_code__premium_only()) { // Fully premium

            // Only remove if explicitly configured
            if (defined('WALLET_UP_REMOVE_DATA_ON_DEACTIVATE') && WALLET_UP_REMOVE_DATA_ON_DEACTIVATE) {
                global $wpdb;
                // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Cleanup on deactivation when explicitly configured.
                $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}wallet_up_donations");
                delete_option('wallet_up_donation_settings');
                delete_option('wallet_up_flush_rules');
            }
        }
    }

    /**
     * Cleanup Payer data on deactivation if configured
     */
    private function cleanupPayerData(): void
    {
        if (wallet_up_fs()->can_use_premium_code__premium_only()) { // Fully premium

            // Only remove if explicitly configured
            if (defined('WALLET_UP_REMOVE_DATA_ON_DEACTIVATE') && WALLET_UP_REMOVE_DATA_ON_DEACTIVATE) {
                global $wpdb;
                // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Cleanup on deactivation when explicitly configured.
                $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}wallet_up_payers");
                delete_option('wallet_up_payer_settings');
                delete_option('wallet_up_flush_rules');
            }
        }
    }
    /**
     * Logs an error with optional method context.
     * 
     * @param string $message The error message to log.
     * @param string $method The method where the error occurred, if applicable.
     */
    private function logError(string $message, string $method = ''): void
    {
        $this->errorHandler->log(sprintf('[%s] %s', $method, $message));
    }

    /**
     * Resets singleton instances to clean up after deactivation.
     */
    private function resetSingletons(): void
    {
        $classes = [
            QRCodeService::class,
            PaymentRegistry::class,
            AssetManager::class,
            DisplayHandler::class,
            ErrorHandler::class,
            WooCommerceIntegration::class,
            WPFormsService::class
        ];

        foreach ($classes as $class) {
            if (method_exists($class, 'reset')) {
                $class::reset();
            }
        }
    }

    /**
     * Runs database migrations if the plugin has not been installed.
     */
    private function runMigrations(): void
    {
        $currentVersion = get_option('wallet_up_version', '0');
        $pluginVersion = WALLET_UP_PRO_VERSION;
        
        if (!$this->installed && version_compare($currentVersion, $pluginVersion, '<')) {
            $tableName = $this->getTableName();
            if (empty($tableName)) {
                throw new Exception(esc_html('Table name cannot be empty'));
            }
            $this->migrationManager = new MigrationManager(
                $this->db,
                $this->errorHandler,
                $tableName
            );
            $this->migrationManager->runMigrations();
            
            // Update version to prevent running migrations again
            update_option('wallet_up_version', $pluginVersion);
            $this->installed = true;
        }
    }

    /**
     * Checks if system requirements are met, like QR code generation capabilities.
     */
    private function checkRequirements(): void
    {
        $this->verifyQRCapabilities();
    }

    /**
     * Verifies if QR code generation capabilities are available on the server.
     */
    private function verifyQRCapabilities(): void
    {
        if (!extension_loaded('gd') && !extension_loaded('imagick')) {
            $this->errorHandler->log('WARNING: Neither GD nor ImageMagick extension is available');
            define('WALLET_UP_QR_CODE_API', true);
            define('WALLET_UP_QR_CODE_EXTERNAL_API_FALLBACK', 'https://api.qrserver.com/v1/create-qr-code/?size=180x180&ecc=L&margin=0&data=');
        } else {
            define('WALLET_UP_QR_CODE_API', false);
        }
    }

    // REMOVED: Old WooCommerce handlers registration - now handled by WooCommerceIntegration

    /**
 * Sanitizes content based on its type while preserving special characters safely
 * 
 * @param string $content The content to sanitize
 * @param string $type The content type ('url', 'text', or 'json')
 * @param bool $decode Whether to URL-decode before sanitizing (for handling double-encoded content)
 * @return string|array Sanitized content
 */
private function sanitizeContent(string $content, string $type = 'url', bool $decode = false): mixed
{
    if (empty($content)) {
        return '';
    }

    // Optional URL-decode to handle potential double-encoding
    if ($decode && $type === 'url' && strpos($content, '%') !== false) {
        $content = urldecode($content);
    }
    
    switch ($type) {
        case 'url':
            // For URLs, use esc_url_raw to preserve query parameters and special characters
            // while still preventing malicious protocols and XSS
            $sanitized = esc_url_raw($content);
            
            // Add protocol if missing (raw URL sanitization might strip it if invalid)
            if (!empty($sanitized) && !preg_match('~^(?:f|ht)tps?://~i', $sanitized)) {
                $sanitized = 'https://' . $sanitized;
            }
            
            if (empty($sanitized) || $sanitized === 'https://') {
                $this->errorHandler->log('URL completely removed during sanitization: ' . substr($content, 0, 100));
                return '';
            }
            
            return $sanitized;
            
        case 'text':
            // For general text, use wp_kses to remove dangerous HTML but keep special characters
            // This is more permissive than sanitize_text_field but still prevents XSS
            $allowed_html = array(
                'br' => array(),
                'em' => array(),
                'strong' => array(),
                'b' => array(),
                'i' => array(),
                'u' => array(),
                'p' => array(),
            );
            return wp_kses($content, $allowed_html);
            
        case 'json':
            $decoded = json_decode($content, true);

            if (json_last_error() !== JSON_ERROR_NONE) {
                $this->errorHandler->log('JSON decode error: ' . json_last_error_msg());
                return [];
            }

            if (!is_array($decoded)) {
                return [];
            }

            $sanitized = $this->sanitizeArrayRecursive($decoded);
            return $sanitized;

        default:
            return sanitize_text_field($content);
    }
}

/**
 * Recursively sanitizes all elements in an array
 * 
 * @param array $array The array to sanitize
 * @return array Sanitized array
 */
private function sanitizeArrayRecursive(array $array): array
{
    foreach ($array as $key => $value) {
        $clean_key = sanitize_text_field($key);

        if (is_array($value)) {
            $array[$clean_key] = $this->sanitizeArrayRecursive($value);
            if ($clean_key !== $key) {
                unset($array[$key]);
            }
        } else {
            if (filter_var($value, FILTER_VALIDATE_URL)) {
                $array[$clean_key] = $this->sanitizeContent($value, 'url');
            } else {
                $array[$clean_key] = sanitize_text_field($value);
            }
            
            if ($clean_key !== $key) {
                unset($array[$key]);
            }
        }
    }
    
    return $array;
}

/**
 * Enhanced URL validation that preserves special characters but ensures security
 * 
 * @param string $url The URL to validate
 * @return bool Whether the URL is valid
 */
private function isValidUrl(string $url): bool
{
    if (empty($url)) {
        return false;
    }

    $parsed = wp_parse_url($url);

    if (!$parsed || !isset($parsed['scheme']) || !isset($parsed['host'])) {
        return false;
    }

    if (!in_array(strtolower($parsed['scheme']), ['http', 'https'])) {
        return false;
    }

    if (strpos($parsed['host'], '.') === false) {
        return false;
    }

    $suspicious_patterns = [
        // Script injection attempts
        '/<script/i',
        '/javascript:/i',
        '/data:text/i',
        // SQL injection patterns
        '/union\s+select/i',
        // Shell command injection
        '/;\s*rm\s/i',
        '/;\s*wget\s/i',
        // Basic XSS patterns
        '/onload=/i',
        '/onerror=/i'
    ];
    
    foreach ($suspicious_patterns as $pattern) {
        if (preg_match($pattern, $url)) {
            $this->errorHandler->log('Suspicious pattern detected in URL: ' . substr($url, 0, 100));
            return false;
        }
    }
    
    return filter_var($url, FILTER_VALIDATE_URL) !== false;
}
    /**
     * Validates nonce for AJAX requests
     * 
     * @param string $action The nonce action
     * @return bool Whether the nonce is valid
     */
    private function validateNonce(string $action): bool
    {
        if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), $action)) {
            wp_send_json_error(['message' => 'Invalid security token']);
            return false;
        }
        return true;
    }

    /**
     * Parses settings from JSON string
     * 
     * @param string $settings JSON string of settings
     * @return array|null Parsed settings or null if invalid
     */
    private function parseSettings(string $settings): ?array
    {
        $parsed = json_decode(stripslashes($settings), true);
        if (!is_array($parsed)) {
            wp_send_json_error(['message' => 'Invalid settings data']);
            return null;
        }
        return $parsed;
    }

    // REMOVED: Old payment methods initialization - now handled by WooCommerceIntegration

    /**
     * Registers general AJAX handlers for the plugin.
     */
    private function registerAjaxHandlers(): void
    {
        add_action('wp_ajax_wallet_up_generate_qr', [$this, 'handleQRGeneration']);
        add_action('wp_ajax_nopriv_wallet_up_generate_qr', [$this, 'handleQRGeneration']);
        add_action('wp_ajax_wallet_up_get_quick_access_count', [$this, 'getQuickAccessCount']);
        add_action('wp_ajax_wallet_up_increment_quick_access', [$this, 'incrementQuickAccess']);

        if (wallet_up_fs()->can_use_premium_code__premium_only()) { // Fully premium

            // URL Shortener Service
            add_action('wp_ajax_wallet_up_standalone_shorten_url', [$this, 'handleStandaloneUrlShortening']);
            add_action('wp_ajax_wallet_up_standalone_url_analytics', [$this, 'handleStandaloneUrlAnalytics']);
            add_action('wp_ajax_wallet_up_get_user_urls', [$this, 'handleGetUserUrls']);

            add_action('wp_ajax_wallet_up_update_long_url', [$this, 'handleUpdateLongUrl']);
            add_action('wp_ajax_wallet_up_upload_qr_logo', [$this, 'handleQRLogoUpload']);
            add_action('wp_ajax_wallet_up_upload_qr_logo_base64', [$this, 'handleQRLogoUploadBase64']);


            add_action('wp_ajax_wallet_up_delete_url', [$this, 'handleDeleteURLAjax']);
            add_action('wp_ajax_wallet_up_restore_url', [$this, 'handleRestoreURLAjax']);

            add_action('wp_ajax_wallet_up_save_timezone', [$this, 'handleSaveUserTimezone']);

            add_action('wp_ajax_wallet_up_fix_permalinks', [$this, 'handleFixPermalinks']);
            add_action('wp_ajax_wallet_up_dismiss_permalink_notice', [$this, 'handleDismissPermalinkNotice']);
            add_action('wp_ajax_wallet_up_get_permalink_status', [$this, 'handleGetPermalinkStatus']);
    }
}
    

    /**
 * Handles logo upload for QR codes with enhanced security
 */
public function handleQRLogoUpload(): void
{
    try {
        if (!current_user_can('manage_options')) {
            wp_send_json_error('Unauthorized', 403);
        }

        if (!check_ajax_referer('wallet_up_admin_nonce', 'nonce', false)) {
            throw new Exception(esc_html('Invalid security token'));
        }

        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.InputNotValidated -- $_FILES validated via isset() and is_uploaded_file(); MIME checks below.
        if (!isset($_FILES['logo']['tmp_name']) || !is_uploaded_file($_FILES['logo']['tmp_name'])) {
            throw new Exception(esc_html('No logo file uploaded'));
        }

        // Security checks for the uploaded file
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- $_FILES is validated via is_uploaded_file, wp_check_filetype, and MIME checks below.
        $file = $_FILES['logo'];

        $max_size = 2 * 1024 * 1024; // 2MB
        if ($file['size'] > $max_size) {
            throw new Exception(esc_html('Logo file exceeds maximum size of 2MB'));
        }

        $allowed_types = ['image/png', 'image/jpeg', 'image/svg+xml'];
        // Use server-side MIME detection, not client-supplied type
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $detected_type = finfo_file($finfo, $file['tmp_name']);
        finfo_close($finfo);
        if (!in_array($detected_type, $allowed_types)) {
            throw new Exception(esc_html('Invalid file type. Only PNG, JPEG, and SVG are allowed'));
        }

        // Additional validation for SVG files to prevent XSS
        if ($detected_type === 'image/svg+xml') {
            $svg_content = file_get_contents($file['tmp_name']);

            if (preg_match('/<script|javascript:|on[a-z]+\s*=|<foreignObject|xlink:href|data:\s*text\/html|<iframe|<embed|<object|expression\s*\(|url\s*\(\s*["\']?\s*javascript/i', $svg_content)) {
                throw new Exception(esc_html('SVG contains potentially malicious content'));
            }
        }
        
        $upload_dir = wp_upload_dir();
        $temp_dir = $upload_dir['basedir'] . '/wallet-up-temp';

        if (!file_exists($temp_dir)) {
            wp_mkdir_p($temp_dir);

            // Add .htaccess to prevent direct access
            file_put_contents($temp_dir . '/.htaccess', 'Deny from all');
        }

        $filename = md5(uniqid((string) wp_rand(), true)) . '.' . pathinfo($file['name'], PATHINFO_EXTENSION);
        $filepath = $temp_dir . '/' . $filename;

        if (!wp_is_writable($temp_dir) || !move_uploaded_file($file['tmp_name'], $filepath)) { // phpcs:ignore Generic.PHP.ForbiddenFunctions.Found -- WordPress wp_handle_upload() not applicable for non-standard upload directories.
            throw new Exception(esc_html('Failed to upload logo file'));
        }

        wp_send_json_success([
            'message' => 'Logo uploaded successfully',
            'file' => [
                'name' => $filename,
                'url' => $upload_dir['baseurl'] . '/wallet-up-temp/' . $filename,
                'path' => $filepath
            ]
        ]);
        
    } catch (Exception $e) {
        $this->errorHandler->log('Logo upload error: ' . $e->getMessage());
        wp_send_json_error(['message' => $e->getMessage()]);
    }
}

/**
 * Handles base64 logo upload for QR codes
 */
public function handleQRLogoUploadBase64(): void
{
    try {
        if (!current_user_can('manage_options')) {
            wp_send_json_error('Unauthorized', 403);
        }

        if (!check_ajax_referer('wallet_up_admin_nonce', 'nonce', false)) {
            throw new Exception(esc_html('Invalid security token'));
        }

        if (!isset($_POST['logo_data']) || empty($_POST['logo_data'])) {
            throw new Exception(esc_html('No logo data provided'));
        }

        $logo_data = sanitize_text_field(wp_unslash($_POST['logo_data'] ?? ''));

        if (!preg_match('/^data:image\/(\w+);base64,/', $logo_data, $matches)) {
            throw new Exception(esc_html('Invalid base64 format'));
        }

        $file_extension = $matches[1];
        $file_type = 'image/' . $file_extension;

        $allowed_types = ['image/png', 'image/jpeg', 'image/svg+xml'];
        $allowed_extensions = ['png', 'jpg', 'jpeg', 'svg'];

        if (!in_array($file_type, $allowed_types) || !in_array($file_extension, $allowed_extensions)) {
            throw new Exception(esc_html('Invalid file type. Only PNG, JPEG, and SVG are allowed'));
        }

        $base64_data = substr($logo_data, strpos($logo_data, ',') + 1);
        $decoded_data = base64_decode($base64_data);

        if (!$decoded_data) {
            throw new Exception(esc_html('Invalid base64 data'));
        }

        if (strlen($decoded_data) > 2 * 1024 * 1024) {
            throw new Exception(esc_html('Logo file exceeds maximum size of 2MB'));
        }

        // Additional validation for SVG files to prevent XSS
        if ($file_type === 'image/svg+xml') {
            if (preg_match('/<script|javascript:|on[a-z]+=/i', $decoded_data)) {
                throw new Exception(esc_html('SVG contains potentially malicious content'));
            }
        }

        $upload_dir = wp_upload_dir();
        $temp_dir = $upload_dir['basedir'] . '/wallet-up-temp';

        if (!file_exists($temp_dir)) {
            wp_mkdir_p($temp_dir);
            file_put_contents($temp_dir . '/.htaccess', 'Deny from all');
        }

        $filename = md5(uniqid((string) wp_rand(), true)) . '.' . $file_extension;
        $filepath = $temp_dir . '/' . $filename;

        if (!file_put_contents($filepath, $decoded_data)) {
            throw new Exception(esc_html('Failed to save logo file'));
        }

        $public_url = $upload_dir['baseurl'] . '/wallet-up-temp/' . $filename;
        
        // Send success response
        wp_send_json_success([
            'filename' => $filename,
            'url' => $public_url,
            'path' => $filepath
        ]);
        
    } catch (Exception $e) {
        $this->errorHandler->log('Base64 logo upload error: ' . $e->getMessage());
        wp_send_json_error(['message' => $e->getMessage()]);
    }
}

/**
 * Handles AJAX request for QR code generation with type-aware content handling
 */
public function handleQRGeneration(): void
{
    try {
        // Set proper content type for consistent encoding
        header('Content-Type: application/json; charset=UTF-8');
        
        if (!check_ajax_referer('wallet_up_admin_nonce', 'nonce', false)) {
            throw new Exception(esc_html('Invalid QR Generation security token'));
        }

        $contentType = isset($_POST['content_type']) ? sanitize_text_field(wp_unslash($_POST['content_type'])) : 'url';
        $data = isset($_POST['data']) ? $this->sanitizeContent(sanitize_text_field(wp_unslash($_POST['data'] ?? '')), $contentType) : '';
        $settings = isset($_POST['settings']) ? $this->sanitizeContent(sanitize_text_field(wp_unslash($_POST['settings'] ?? '')), 'json') : [];

        // Add content type to settings array instead of passing as separate parameter
        $settings['contentType'] = $contentType;

        if (empty($data)) {
            throw new Exception(esc_html('No data provided for QR code'));
        }

        $qrImage = $this->qrService->generateQR($data, $settings);

        wp_send_json_success(['qr' => $qrImage]);
    } catch (Exception $e) {
        $this->errorHandler->log('QR generation error: ' . $e->getMessage());
        wp_send_json_error(['message' => $e->getMessage()]);
    }
}

    /**
     * Controls the Payment Settings Quick Button in WalletUpProAdmin.jsx
     */
    public function getQuickAccessCount(): void
    {
        try {
            if (!check_ajax_referer('wallet_up_admin_nonce', 'nonce', false)) {
                throw new Exception(esc_html('Invalid security token'));
            }

            $count = get_option('wallet_up_quick_access_count', 0);
            wp_send_json_success(['count' => $count]);

        } catch (Exception $e) {
            wp_send_json_error(['message' => $e->getMessage()]);
        }
    }

    /**
     * Increment quick access count
     */
    public function incrementQuickAccess(): void
    {
        try {
            if (!current_user_can('manage_options')) {
                wp_send_json_error('Unauthorized', 403);
            }

            if (!check_ajax_referer('wallet_up_admin_nonce', 'nonce', false)) {
                throw new Exception(esc_html('Invalid security token'));
            }

            $count = get_option('wallet_up_quick_access_count', 0);
            update_option('wallet_up_quick_access_count', $count + 1);
            wp_send_json_success(['count' => $count + 1]);

        } catch (Exception $e) {
            wp_send_json_error(['message' => $e->getMessage()]);
        }
    }

   /**
 * Handle AJAX request to shorten a URL with enhanced security and character preservation
 */
public function handleStandaloneUrlShortening(): void
{
    if (!current_user_can('manage_options')) {
        wp_send_json_error('Unauthorized', 403);
    }

    if (wallet_up_fs()->can_use_premium_code__premium_only()) { // Fully premium
        // Set proper headers with charset to help with special characters
        header('Content-Type: application/json; charset=UTF-8');
        header('Access-Control-Allow-Origin: *');
        header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
        header('Access-Control-Allow-Headers: Content-Type');

        // Handle preflight OPTIONS request
        if (sanitize_text_field(wp_unslash($_SERVER['REQUEST_METHOD'] ?? '')) === 'OPTIONS') {
            status_header(200);
            exit();
        }
        
        try {
            if (!check_ajax_referer('wallet_up_admin_nonce', 'nonce', false)) {
                throw new Exception(esc_html('Invalid security token'));
            }

            $long_url = isset($_POST['long_url']) ? $this->sanitizeContent(sanitize_text_field(wp_unslash($_POST['long_url'] ?? '')), 'url') : '';

            if (empty($long_url)) {
                throw new Exception(esc_html('URL is required'));
            }

            if (!$this->isValidUrl($long_url)) {
                throw new Exception(esc_html('Invalid URL format - please check the URL and try again'));
            }

            $shortener = $this->container->get('url_shortener');

            $options = [];

            if (isset($_POST['expires_in']) && !empty($_POST['expires_in']) && sanitize_text_field(wp_unslash($_POST['expires_in'] ?? '')) !== 'never') {
                $options['expires_in'] = intval(wp_unslash($_POST['expires_in']));
            }

            if (isset($_POST['custom_slug']) && !empty($_POST['custom_slug'])) {
                // Validate slug format (alphanumeric + hyphens, max 12 chars)
                $custom_slug = sanitize_text_field(wp_unslash($_POST['custom_slug']));
                if (!preg_match('/^[a-zA-Z0-9-]{1,12}$/', $custom_slug)) {
                    throw new Exception(esc_html('Custom slug must contain only letters, numbers, and hyphens (max 12 characters)'));
                }
                $options['custom_slug'] = $custom_slug;
            }

            if (isset($_POST['metadata']) && !empty($_POST['metadata'])) {
                try {
                    // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized via sanitizeContent() JSON sanitizer below.
                    $raw_metadata = wp_unslash($_POST['metadata']);
                    $metadata = $this->sanitizeContent($raw_metadata, 'json');
                    if (empty($metadata)) {
                        throw new Exception(esc_html('Invalid metadata format'));
                    }
                    $options['metadata'] = $metadata;
                } catch (Exception $e) {
                    $this->errorHandler->log('Metadata parsing error: ' . $e->getMessage());
                    // Continue without metadata
                }
            }

            $options['track_clicks'] = isset($_POST['track_clicks']) && sanitize_text_field(wp_unslash($_POST['track_clicks'] ?? '')) === '1';

            if (is_user_logged_in()) {
                $options['user_id'] = get_current_user_id();
            }

            $short_url = $shortener->shortenURL($long_url, $options);

            wp_send_json_success([
                'message' => 'URL shortened successfully',
                'short_url' => $short_url,
                'long_url' => $long_url
            ]);

        } catch (Exception $e) {
            $this->errorHandler->log('URL shortening error: ' . $e->getMessage());
            wp_send_json_error([
                'message' => $e->getMessage()
            ]);
        }
    }
}

        /**
     * Handle AJAX request to update a long URL with robust security and encoding preservation
     */
    public function handleUpdateLongUrl(): void
    {
        if (wallet_up_fs()->can_use_premium_code__premium_only()) { // Fully premium
            // Set proper headers for consistent encoding
            header('Content-Type: application/json; charset=UTF-8');
            
            try {
                if (!check_ajax_referer('wallet_up_admin_nonce', 'nonce', false)) {
                    throw new Exception(esc_html('Invalid security token'));
                }

                $userId = get_current_user_id();
                if (!$userId) {
                    throw new Exception(esc_html('User not logged in'));
                }

                $code = isset($_POST['code']) ? sanitize_text_field(wp_unslash($_POST['code'])) : '';
                $newLongUrl = isset($_POST['new_long_url']) ? $this->sanitizeContent(sanitize_text_field(wp_unslash($_POST['new_long_url'] ?? '')), 'url') : '';

                $modifiedAt = isset($_POST['modified_at']) ? sanitize_text_field(wp_unslash($_POST['modified_at'])) : null;

                if (empty($code)) {
                    throw new Exception(esc_html('Missing URL code'));
                }

                if (empty($newLongUrl)) {
                    throw new Exception(esc_html('Missing new URL destination'));
                }

                if (!$this->isValidUrl($newLongUrl)) {
                    throw new Exception(esc_html('Invalid URL format. Please check the URL and try again.'));
                }
                
                // Add additional logging for debugging
                $this->errorHandler->log(sprintf(
                    'URL update request: Code=%s, NewURL=%s, UserID=%d, ModifiedAt=%s',
                    $code,
                    substr($newLongUrl, 0, 100),
                    $userId,
                    $modifiedAt ?? 'auto'
                ));

                $shortener = $this->container->get('url_shortener');
                $success = $shortener->updateLongUrl($code, $newLongUrl, $userId, $modifiedAt);

                if (!$success) {
                    throw new Exception(esc_html('Failed to update URL destination'));
                }

                $formattedTimestamp = \WalletUpPro\Core\Utilities\TimestampUtility::formatTimestamp(
                    \WalletUpPro\Core\Utilities\TimestampUtility::toUTCTimestamp($modifiedAt),
                    'mysql'
                );

                wp_send_json_success([
                    'message' => 'URL updated successfully',
                    'code' => $code,
                    'new_long_url' => $newLongUrl,
                    'modified_at' => $formattedTimestamp
                ]);
            } catch (Exception $e) {
                $this->errorHandler->log('URL update error: ' . $e->getMessage());
                wp_send_json_error(['message' => $e->getMessage()]);
            }
        } else {
            wp_send_json_error(['message' => 'This feature requires a premium license']);
        }
    }

public function handleStandaloneUrlAnalytics(): void
{
    if (wallet_up_fs()->can_use_premium_code__premium_only()) { // Fully premium

        header('Content-Type: application/json');
        header('Access-Control-Allow-Origin: *');
        header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
        header('Access-Control-Allow-Headers: Content-Type');

        // Handle preflight OPTIONS request
        if (sanitize_text_field(wp_unslash($_SERVER['REQUEST_METHOD'] ?? '')) === 'OPTIONS') {
            status_header(200);
            exit();
        }

        try {
            if (!check_ajax_referer('wallet_up_admin_nonce', 'nonce', false)) {
                throw new Exception(esc_html('Invalid security token'));
            }

            $code = isset($_POST['code']) ? sanitize_text_field(wp_unslash($_POST['code'])) : '';
            if (empty($code)) {
                throw new Exception(esc_html('URL code is required'));
            }

            $userId = get_current_user_id();
            if (!$userId) {
                throw new Exception(esc_html('User not authenticated'));
            }

            $period = isset($_POST['period']) ? sanitize_text_field(wp_unslash($_POST['period'])) : 'all';
            $includeDetails = isset($_POST['include_details']) ? filter_var(wp_unslash($_POST['include_details']), FILTER_VALIDATE_BOOLEAN) : true;

            $shortener = $this->container->get('url_shortener');
            $analytics = $shortener->getAnalytics($code, $userId);

            if (!$analytics) {
                throw new Exception(esc_html('No analytics data found for this URL'));
            }

            if (isset($analytics['user_id']) && $analytics['user_id'] != $userId && !current_user_can('manage_options')) {
                throw new Exception(esc_html('You do not have permission to view analytics for this URL'));
            }

            $analytics['_request'] = [
                'period' => $period,
                'include_details' => $includeDetails,
                'requested_at' => TimestampUtility::getCurrentUTCTimestamp(),
                'user_id' => $userId
            ];

            wp_send_json_success($analytics);
        } catch (Exception $e) {
            $this->errorHandler->log('URL analytics error: ' . $e->getMessage());
            wp_send_json_error([
                'message' => $e->getMessage()
            ]);
        }
    } else {
        wp_send_json_error(['message' => 'This feature requires a premium license']);
    }
}
    public function handleGetUserUrls(): void
    {
        if (wallet_up_fs()->can_use_premium_code__premium_only()) { // Fully premium

            try {
                if (!check_ajax_referer('wallet_up_admin_nonce', 'nonce', false)) {
                    throw new Exception(esc_html('Invalid security token'));
                }

                $userId = get_current_user_id();
                if (!$userId) {
                    throw new Exception(esc_html('User not logged in'));
                }

                $shortener = $this->container->get('url_shortener');
                $urls = $shortener->getUserURLs($userId, 50, 0);

                wp_send_json_success([
                    'urls' => $urls
                ]);
            } catch (Exception $e) {
                wp_send_json_error(['message' => $e->getMessage()]);
            }
        }
    }

    public function handleDeleteURLAjax(): void
    {
        if (wallet_up_fs()->can_use_premium_code__premium_only()) { // Fully premium

            try {
                if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'wallet_up_admin_nonce')) {
                    wp_send_json_error([
                        'message' => 'Security check failed'
                    ], 403);
                    return;
                }

                if (!current_user_can('manage_options')) {
                    wp_send_json_error('Unauthorized', 403);
                }

                if (!isset($_POST['code']) || empty($_POST['code'])) {
                    wp_send_json_error([
                        'message' => 'Missing URL code'
                    ], 400);
                    return;
                }

                $code = sanitize_text_field(wp_unslash($_POST['code']));

                $userId = get_current_user_id();

                // Default to soft delete (deactivation) unless explicitly requested otherwise
                $hardDelete = isset($_POST['hard_delete']) && sanitize_text_field(wp_unslash($_POST['hard_delete'] ?? '')) === 'true';

                if (!isset($this->urlShortener)) {
                    $this->urlShortener = new URLShortenerService();
                }

                $result = $this->urlShortener->deleteShortUrl($code, $userId, $hardDelete);

                if ($result['success']) {
                    wp_send_json_success([
                        'message' => $result['message'],
                        'code' => $result['code'],
                        'hardDelete' => $hardDelete
                    ]);
                } else {
                    $statusCode = $result['status'] ?? 500;

                    wp_send_json_error([
                        'message' => $result['message'],
                        'code' => $result['code']
                    ], $statusCode);
                }
            } catch (Exception $e) {
                $this->errorHandler->log('URL deletion error: ' . $e->getMessage());
                wp_send_json_error([
                    'message' => $e->getMessage()
                ], 500);
            }
        }
    }

    public function handleRestoreURLAjax(): void
    {
        if (wallet_up_fs()->can_use_premium_code__premium_only()) { // Fully premium
            if (wallet_up_fs()->is_plan('pro', true)) {

                try {
                    if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'wallet_up_admin_nonce')) {
                        wp_send_json_error([
                            'message' => 'Security check failed'
                        ], 403);
                        return;
                    }

                    if (!current_user_can('manage_options')) {
                        wp_send_json_error('Unauthorized', 403);
                    }

                    if (!isset($_POST['code']) || empty($_POST['code'])) {
                        wp_send_json_error([
                            'message' => 'Missing URL code'
                        ], 400);
                        return;
                    }

                    $code = sanitize_text_field(wp_unslash($_POST['code']));

                    $userId = get_current_user_id();

                    if (!isset($this->urlShortener)) {
                        $this->urlShortener = new \WalletUpPro\Services\URLShortenerService();
                    }

                    $result = $this->urlShortener->restoreURL($code, $userId);

                    if ($result['success']) {
                        wp_send_json_success([
                            'message' => $result['message'],
                            'code' => $result['code']
                        ]);
                    } else {
                        $statusCode = $result['status'] ?? 500;

                        wp_send_json_error([
                            'message' => $result['message'],
                            'code' => $result['code']
                        ], $statusCode);
                    }
                } catch (Exception $e) {
                    $this->errorHandler->log('URL restoration error: ' . $e->getMessage());
                    wp_send_json_error([
                        'message' => $e->getMessage()
                    ], 500);
                }
            }
        }
    }

public function handleSaveUserTimezone(): void
{
    try {
        if (!check_ajax_referer('wallet_up_admin_nonce', 'nonce', false)) {
            throw new Exception(esc_html('Invalid security token'));
        }

        $userId = get_current_user_id();
        if (!$userId) {
            throw new Exception(esc_html('User not logged in'));
        }

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

        if (empty($timezone)) {
            throw new Exception(esc_html('No timezone provided'));
        }

        $validTimezones = timezone_identifiers_list();
        if (!in_array($timezone, $validTimezones) && !preg_match('/^UTC[+-]\d{1,2}(:\d{2})?$/', $timezone)) {
            throw new Exception(esc_html('Invalid timezone format'));
        }

        update_user_meta($userId, 'wallet_up_timezone', $timezone);

        wp_send_json_success([
            'message' => 'Timezone preference saved',
            'timezone' => $timezone
        ]);
    } catch (Exception $e) {
        wp_send_json_error(['message' => $e->getMessage()]);
    }
}

    /**
     * Creates default plugin options if they do not exist.
     */
    private function createDefaultOptions(): void
    {
        $defaults = [
            'wallet_up_transfer_call' => [],
            'wallet_up_display_settings' => [
                'defaultMode' => 'qr',
                'qrSize' => 'medium',
                'qrColor' => '#674FBF',
                'qrBackground' => '#F4F4FF',
                'qrBorder' => true,
                'qrStyle' => 'rounded',
                'showDefaultMessage' => true,
                'customMessage' => '',
                'hideMessage' => false
            ]
        ];

        foreach ($defaults as $option => $value) {
            if (false === get_option($option)) {
                add_option($option, $value);
            }
        }
    }

    public function handleFixPermalinks(): void
    {
        try {
            if (!check_ajax_referer('wallet_up_fix_permalinks', '_wpnonce', false)) {
                throw new Exception(esc_html('Invalid security token'));
            }

            if (!current_user_can('manage_options')) {
                throw new Exception(esc_html('You do not have permission to change permalinks'));
            }

            update_option('permalink_structure', '/%postname%/');

            flush_rewrite_rules();

            // Also trigger our rewrite manager flush
            if ($this->container->has('rewrite_manager')) {
                $rewriteManager = $this->container->get('rewrite_manager');
                $rewriteManager->forceFlushRules();
            }
            
            wp_send_json_success([
                'message' => 'Permalink structure updated successfully'
            ]);
            
        } catch (Exception $e) {
            wp_send_json_error(['message' => $e->getMessage()]);
        }
    }

    public function handleDismissPermalinkNotice(): void
    {
        if (!check_ajax_referer('wallet_up_dismiss_notice', '_wpnonce', false)) {
            wp_send_json_error(['message' => 'Invalid security token']);
            return;
        }

        update_user_meta(get_current_user_id(), 'wallet_up_permalink_notice_dismissed', true);
        
        wp_send_json_success();
    }

    public function handleGetPermalinkStatus(): void
    {
        if (!current_user_can('manage_options')) {
            wp_send_json_error(['message' => 'Insufficient permissions']);
            return;
        }
        
        if ($this->container->has('rewrite_manager')) {
            $rewriteManager = $this->container->get('rewrite_manager');
            $status = $rewriteManager->getPermalinkStatus();
            wp_send_json_success($status);
        } else {
            wp_send_json_error(['message' => 'Rewrite manager not available']);
        }
    }

    /**
     * Health check for plugin services and integrations
     * 
     * @return array Status information for plugin components
     */
    public function healthCheck(): array
    {
        $health = [
            'wpforms' => [
                'status' => 'error',
                'message' => 'WPForms service not registered in container.'
            ]
        ];

        if ($this->container->has('wpforms')) {
            $wpformsService = $this->container->get('wpforms');
            if ($wpformsService->isActive()) {
                $health['wpforms'] = [
                    'status' => 'ok',
                    'message' => sprintf(
                        'WPForms v%s is active and integrated. Template is %s.',
                        $wpformsService->getVersion(),
                        $wpformsService->isTemplateEnabled() ? 'enabled' : 'disabled'
                    )
                ];
            } else {
                $health['wpforms'] = [
                    'status' => 'error',
                    'message' => 'WPForms is installed but not active.'
                ];
            }
        }

        return $health;
    }

    /**
     * Clears plugin transients from the database.
     */
    private function clearTransients(): void
    {
        global $wpdb;
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Direct query required, caching not applicable.
        $wpdb->query(
            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Prepared query with safe table name.
            $wpdb->prepare(
                // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table name/variable is safely derived.
                "DELETE FROM $wpdb->options WHERE option_name LIKE %s",
                $wpdb->esc_like('_transient_wallet_up_') . '%'
            )
        );
    }

    // Getter methods

    /**
     * Gets the database manager instance.
     * 
     * @return DatabaseManager The database manager.
     */
    public function getDatabase(): DatabaseManager
    {
        return $this->db;
    }

    /**
     * Gets the payment registry instance.
     * 
     * @return PaymentRegistry The payment registry.
     */
    public function getRegistry(): PaymentRegistry
    {
        return $this->registry;
    }

    /**
     * Purge known host/page/object caches so a payment-settings change is visible
     * right away. Every integration is called only when present, so this is a safe
     * no-op on a site without it. Wrapped per-call so one missing/erroring cache
     * plugin can't abort the rest.
     */
    public static function purgePaymentCaches(): void
    {
        $purges = [
            // WordPress object cache (Redis/Memcached drop-ins included)
            static function () {
                if (function_exists('wp_cache_flush')) {
                    wp_cache_flush();
                }
            },
            // SiteGround Optimizer
            static function () {
                if (function_exists('sg_cachepress_purge_cache')) {
                    sg_cachepress_purge_cache();
                } elseif (has_action('siteground_optimizer_flush_cache') || class_exists('\\SiteGround_Optimizer\\Supercacher\\Supercacher')) {
                    do_action('siteground_optimizer_flush_cache');
                }
            },
            // LiteSpeed Cache
            static function () {
                if (defined('LSCWP_V') || has_action('litespeed_purge_all')) {
                    do_action('litespeed_purge_all');
                }
            },
            // WP Rocket
            static function () {
                if (function_exists('rocket_clean_domain')) {
                    rocket_clean_domain();
                }
            },
            // W3 Total Cache
            static function () {
                if (function_exists('w3tc_flush_all')) {
                    w3tc_flush_all();
                }
            },
            // WP Super Cache
            static function () {
                if (function_exists('wp_cache_clear_cache')) {
                    wp_cache_clear_cache();
                }
            },
            // WP Fastest Cache
            static function () {
                if (function_exists('wpfc_clear_all_cache')) {
                    wpfc_clear_all_cache(true);
                }
            },
            // Autoptimize
            static function () {
                if (class_exists('\\autoptimizeCache') && method_exists('\\autoptimizeCache', 'clearall')) {
                    \autoptimizeCache::clearall();
                }
            },
        ];

        foreach ($purges as $purge) {
            try {
                $purge();
            } catch (\Throwable $e) {
                // A failing cache integration must not break the save flow.
            }
        }
    }

    /**
     * Gets the QR code service instance.
     * 
     * @return QRCodeService The QR code service.
     */
    public function getQRService(): QRCodeService
    {
        return $this->qrService;
    }

    /**
     * Gets the error handler instance.
     * 
     * @return ErrorHandler The error handler.
     */
    public function getErrorHandler(): ErrorHandler
    {
        return $this->errorHandler;
    }

    /**
     * Declare compatibility with WooCommerce features
     * Following Fluid Checkout pattern for proper block integration
     */
    public function declareWooCommerceCompatibility(): void
    {
        try {
            if (!class_exists('\Automattic\WooCommerce\Utilities\FeaturesUtil')) {
                return;
            }

            // CRITICAL: WC requires the MAIN plugin file (wallet-up.php with Plugin Name header)
            // WALLET_UP_FILE points to wallet-up-start.php which WC won't recognize
            $main_plugin_file = dirname(WALLET_UP_FILE) . '/wallet-up.php';

            // Declare compatibility with WooCommerce HPOS (High-Performance Order Storage)
            \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility(
                'custom_order_tables',
                $main_plugin_file,
                true
            );

            // Declare compatibility with WooCommerce Cart & Checkout Blocks
            \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility(
                'cart_checkout_blocks',
                $main_plugin_file,
                true
            );


        } catch (Exception $e) {
            $this->errorHandler->log('Failed to declare WooCommerce compatibility: ' . $e->getMessage());
        }
    }

    private function areDonationTablesCreated(): bool
    {
        // Use transient cache to avoid repeated database checks
        $cache_key = 'wallet_up_donation_tables_exist';
        $cached_result = get_transient($cache_key);
        
        if ($cached_result !== false) {
            return $cached_result;
        }
        
        global $wpdb;
        
        $donations_table = $wpdb->prefix . 'wallet_up_donations';
        $transaction_table = $wpdb->prefix . 'wallet_up_donation_transactions';
        
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Fresh data required for accurate results.
        $tables_exist = $wpdb->get_var("SHOW TABLES LIKE '$donations_table'") == $donations_table &&
                        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Fresh data required for accurate results.
                        $wpdb->get_var("SHOW TABLES LIKE '$transaction_table'") == $transaction_table;
        
        // Cache for 1 hour since tables don't change frequently
        set_transient($cache_key, $tables_exist, 3600);
        
        return $tables_exist;
    }

    private function arePayerTablesCreated(): bool
    {
        // Use transient cache to avoid repeated database checks
        $cache_key = 'wallet_up_payer_tables_exist';
        $cached_result = get_transient($cache_key);
        
        if ($cached_result !== false) {
            return $cached_result;
        }
        
        global $wpdb;
        
        $payers_table = $wpdb->prefix . 'wallet_up_payers';
        $transaction_table = $wpdb->prefix . 'wallet_up_payer_transactions';
        
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Fresh data required for accurate results.
        $tables_exist = $wpdb->get_var("SHOW TABLES LIKE '$payers_table'") == $payers_table &&
                        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Fresh data required for accurate results.
                        $wpdb->get_var("SHOW TABLES LIKE '$transaction_table'") == $transaction_table;
        
        // Cache for 1 hour since tables don't change frequently
        set_transient($cache_key, $tables_exist, 3600);
        
        return $tables_exist;
    }

    /**
     * Cleans up resources used by the plugin.
     */
    public function cleanup(): void
    {
        $this->container->cleanup();
    }
}