<?php

if (!defined('ABSPATH')) exit; 
if (!class_exists('AIEO')) {

    class AIEO
    {
        
        private $uuid_bin_expression = null;

        public function __construct()
        {
            
            add_action('admin_menu', array($this, 'aieo_add_admin_menu'));
            
            
            add_action('admin_menu', array($this, 'aieo_reorder_admin_submenu'), 9999);
            add_action('admin_bar_menu', array($this, 'aieo_add_admin_bar_menu'), 75);
            
            
            
            add_action('wp_head',    array($this, 'aieo_admin_bar_css'), 100);
            add_action('admin_head', array($this, 'aieo_admin_bar_css'), 100);
            add_action('admin_aieo_normalize_path', array($this, 'aieo_normalize_path'));

            
            add_action('admin_post_eshop_optimizer_export_csv', array($this, 'aieo_export_upsells_cross_sells_to_csv'));
            add_action('admin_post_eshop_optimizer_handle_export_orders', array($this, 'aieo_handle_export_orders'));
            add_action('admin_post_delete_exported_file', array($this, 'aieo_delete_exported_file'));

            
            add_action('admin_post_eshop_optimizer_handle_upload', array($this, 'aieo_handle_recommendations_upload'));

            
            add_action('admin_post_eshop_optimizer_display_references', array($this, 'aieo_handle_display_references_setting'));

            
            add_action('admin_post_eshop_optimizer_utm_stats', array($this, 'aieo_handle_utm_stats_setting'));

            
            add_action('admin_post_eshop_optimizer_session_tracker', array($this, 'aieo_handle_session_tracker_setting'));

            
            add_action('admin_notices', array($this, 'aieo_display_all_admin_notices'));

            
            add_action('admin_post_eshop_optimizer_transfer_to_remote', array($this, 'aieo_handle_eshop_optimizer_transfer_to_remote'));

            
            add_action('admin_post_eshop_optimizer_account', array($this, 'aieo_handle_eshop_optimizer_account'));

            
            add_action('admin_post_aieo_rooster_connector', array($this, 'aieo_handle_rooster_connector'));
            add_action('admin_post_aieo_transfer_to_rooster', array($this, 'aieo_handle_transfer_to_rooster'));
            add_action('wp_ajax_aieo_rooster_transfer_init', array($this, 'aieo_rooster_transfer_init'));
            add_action('wp_ajax_aieo_rooster_transfer_batch', array($this, 'aieo_rooster_transfer_batch'));
            add_action('wp_ajax_aieo_check_rooster_credits', array($this, 'aieo_check_rooster_credits'));

            
            add_action('admin_post_aieo_logout_account', array($this, 'aieo_handle_logout_account'));

            
            

            
            add_action('wp_ajax_aieo_init_export', array($this, 'aieo_init_export'));
            add_action('wp_ajax_aieo_process_export_batch', array($this, 'aieo_process_export_batch'));
            add_action('wp_ajax_aieo_get_download_section', array($this, 'aieo_get_download_section'));
            add_action('wp_ajax_aieo_get_statistics_section', array($this, 'aieo_get_statistics_section'));
            add_action('wp_ajax_aieo_init_upsell_export', array($this, 'aieo_init_upsell_export'));
            add_action('wp_ajax_aieo_process_upsell_batch', array($this, 'aieo_process_upsell_batch'));
            add_action('wp_ajax_aieo_init_upsell_import', array($this, 'aieo_init_upsell_import'));
            add_action('wp_ajax_aieo_process_upsell_import_batch', array($this, 'aieo_process_upsell_import_batch'));

            
            add_action('wp_ajax_aieo_save_settings', array($this, 'aieo_save_settings'));

            
            add_action('wp_ajax_aieo_check_vitals_data', array($this, 'aieo_check_vitals_data'));

            
            add_action('wp_ajax_aieo_optimize_database', array($this, 'aieo_optimize_database'));
            add_action('wp_ajax_aieo_get_index_stats', array($this, 'aieo_get_index_stats'));
            add_action('wp_ajax_aieo_fix_collations', array($this, 'aieo_fix_collations'));
        }

        
        private function aieo_ensure_mysql_completion()
        {
            global $wpdb;

            try {
                
                
                $wpdb->query("DO SLEEP(0)"); 

                
                
                usleep(250000); 

                
                $wpdb->query("UNLOCK TABLES");

                return true;
            } catch (Exception $e) {
                
                return true;
            }
        }

        
        private function aieo_log($message, array $context = array())
        {
            $entry = 'AIEO: ' . $message;
            if (!empty($context)) {
                $encoded = wp_json_encode($context);
                if ($encoded !== false) {
                    $entry .= ' ' . $encoded;
                }
            }
            aieo_debug_log($entry);
        }

        
        private function aieo_get_uuid_bin_expression()
        {
            if ($this->uuid_bin_expression !== null) {
                return $this->uuid_bin_expression;
            }

            global $wpdb;

            
            $previous_suppression = $wpdb->suppress_errors(true);
            $previous_show_errors = property_exists($wpdb, 'show_errors') ? $wpdb->show_errors : null;
            if (method_exists($wpdb, 'hide_errors') && $previous_show_errors !== null) {
                $wpdb->hide_errors();
            }

            $wpdb->get_var('SELECT UUID_TO_BIN(UUID())');
            $wpdb->suppress_errors($previous_suppression);
            if (method_exists($wpdb, 'show_errors') && $previous_show_errors) {
                $wpdb->show_errors();
            }

            if (empty($wpdb->last_error)) {
                $this->uuid_bin_expression = 'UUID_TO_BIN(UUID())';
                $wpdb->last_error = '';
                $this->aieo_log('Using native UUID_TO_BIN() for binary UUID generation.');
                return $this->uuid_bin_expression;
            }

            
            $this->aieo_log(
                'UUID_TO_BIN() not available on this database server, falling back to UNHEX(REPLACE(UUID(), \'-\', \'\')).',
                array('db_error' => $wpdb->last_error)
            );
            $wpdb->last_error = '';
            $this->uuid_bin_expression = "UNHEX(REPLACE(UUID(), '-', ''))";

            return $this->uuid_bin_expression;
        }

        
        private function aieo_table_exists($table_name)
        {
            global $wpdb;
            $result = $wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $table_name));
            return ($result === $table_name);
        }

        
        private function aieo_uuid_empty_clause($column, $alias = '')
        {
            $prefix = $alias ? "{$alias}." : '';
            return "({$prefix}{$column} IS NULL OR LENGTH({$prefix}{$column}) = 0)";
        }

        
        private function aieo_ensure_temp_orders_schema($table_name)
        {
            global $wpdb;

            if (!$this->aieo_table_exists($table_name)) {
                $this->aieo_log('Temp orders table missing; recreating.', array('table' => $table_name));
                aieo_create_temp_orders_table($table_name);
                return;
            }

            $columns = array(
                'OrderIdGraphUUID' => 'BINARY(16) NULL DEFAULT NULL',
                'OrderItemIdGraphUUID' => 'BINARY(16) NULL DEFAULT NULL',
                'PPIdGraphUUID' => 'BINARY(16) NULL DEFAULT NULL',
                'ProdIdGraphUUID' => 'BINARY(16) NULL DEFAULT NULL',
                'EpoIdGraphUUID' => 'BINARY(16) NULL DEFAULT NULL',
                'O_PP_GraphUUID' => 'BINARY(16) NULL DEFAULT NULL',
                'O_PP_Freq' => 'INT NULL DEFAULT NULL',
                'O_Prod_GraphUUID' => 'BINARY(16) NULL DEFAULT NULL',
                'O_Prod_Freq' => 'INT NULL DEFAULT NULL',
                'O_Epo_GraphUUID' => 'BINARY(16) NULL DEFAULT NULL',
                'O_Epo_Freq' => 'INT NULL DEFAULT NULL',
                'PP_Epo_GraphUUID' => 'BINARY(16) NULL DEFAULT NULL',
                'PP_Epo_Freq' => 'INT NULL DEFAULT NULL',
                'Prod_Epo_GraphUUID' => 'BINARY(16) NULL DEFAULT NULL',
                'Prod_Epo_Freq' => 'INT NULL DEFAULT NULL',
            );

            foreach ($columns as $column => $definition) {
                $column_info = $wpdb->get_row(
                    $wpdb->prepare(
                        "SELECT COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS
                         WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s AND COLUMN_NAME = %s",
                        $table_name,
                        $column
                    ),
                    ARRAY_A
                );

                if (!$column_info) {
                    $wpdb->query("ALTER TABLE `{$table_name}` ADD COLUMN `{$column}` {$definition}");
                    if ($wpdb->last_error) {
                        $this->aieo_log('Failed adding missing column to temp orders table.', array(
                            'table' => $table_name,
                            'column' => $column,
                            'error' => $wpdb->last_error,
                        ));
                    }
                    continue;
                }

                $expects_binary = stripos($definition, 'BINARY(16)') !== false;
                if ($expects_binary && stripos($column_info['COLUMN_TYPE'], 'binary(16)') === false) {
                    $wpdb->query("ALTER TABLE `{$table_name}` MODIFY `{$column}` BINARY(16) NULL DEFAULT NULL");
                    if ($wpdb->last_error) {
                        $this->aieo_log('Failed converting column to BINARY(16).', array(
                            'table' => $table_name,
                            'column' => $column,
                            'current_type' => $column_info['COLUMN_TYPE'],
                            'error' => $wpdb->last_error,
                        ));
                    }
                }
            }
        }

        public function aieo_wpse_edit_text($content)
        {
            
            
            if (isset($_GET['page']) && $_GET['page'] === 'ai-eshop-optimizer') {
                
                if (class_exists('WooCommerce')) {
                    return "Thank you for choosing <a href='https://eshop-optimizer.com'>AI eShop Optimizer</a> for Woocommerce by <i><a href='https://oxfordmetadata.co.uk'>Oxford Metadata Ltd</a></i>";
                } else {
                    return "Thank you for choosing <a href='https://eshop-optimizer.com'>AI eShop Optimizer</a> for Wordpress by <i><a href='https://oxfordmetadata.co.uk'>Oxford Metadata Ltd</a></i>";
                }
            }

            return $content;
        }
        public function aieo_normalize_path($csv_path)
        {
            if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
                $csv_path = str_replace('\\', '/', $csv_path);
            }
            return $csv_path;
        }

        
        public function aieo_enqueue_styles_scripts()
        {
            
            wp_enqueue_style(
                'ai-eshop-optimizer-admin', 
                AIEO_URI . 'assets/css/aieo-admin-panel.css', 
                array(), 
                AIEO_VERSION . '.3' 
            );

            
            wp_enqueue_script(
                'ai-eshop-optimizer-form-validation',
                AIEO_URI . 'assets/js/form-validation.js',
                array('jquery'), 
                AIEO_VERSION,
                true 
            );

            
            wp_enqueue_script(
                'aieo-export-progress',
                AIEO_URI . 'assets/js/export-progress.js',
                array('jquery'),
                AIEO_VERSION . '.' . time(), 
                true
            );

            
            wp_localize_script(
                'aieo-export-progress',
                'aieoExport',
                array(
                    'ajaxurl' => admin_url('admin-ajax.php'),
                    'nonce' => wp_create_nonce('aieo_export_nonce'),

                    
                    'i18nNoOptionsSelected' => __('No export options selected. Please check at least one option.', 'ai-eshop-optimizer'),
                    
                    'i18nStagesSelected' => __('Selected %d stage(s) to process', 'ai-eshop-optimizer'),
                    'i18nExportInitSuccess' => __('Export initialized successfully', 'ai-eshop-optimizer'),
                    'i18nExportInitFailed' => __('Failed to initialize export: ', 'ai-eshop-optimizer'),
                    'i18nAjaxErrorInit' => __('AJAX error during initialization', 'ai-eshop-optimizer'),
                    'i18nConfirmExport' => __('Start the data analysis process? This may take several minutes.', 'ai-eshop-optimizer'),

                    
                    'i18nStartingStage' => __('Starting: ', 'ai-eshop-optimizer'),
                    
                    'i18nStageProgress' => __('Stage %1$d/%2$d: %3$s', 'ai-eshop-optimizer'),
                    
                    'i18nStageComplete' => __('✓ %1$s: %2$s', 'ai-eshop-optimizer'),
                    
                    'i18nStageError' => __('Error in %1$s: %2$s', 'ai-eshop-optimizer'),

                    
                    
                    'i18nTimeoutWarning' => __('⚠ Timeout in %s. The operation may still be running on the server.', 'ai-eshop-optimizer'),
                    'i18nTimeoutRefresh' => __('Please wait a few moments, then refresh the page and check if the operation completed.', 'ai-eshop-optimizer'),
                    'i18nTimeoutTabs' => __('If you have multiple browser tabs open, close them to avoid conflicts.', 'ai-eshop-optimizer'),
                    
                    'i18nAjaxErrorStage' => __('AJAX error in %1$s: %2$s', 'ai-eshop-optimizer'),

                    
                    'i18nExportCompleted' => __('Export completed successfully!', 'ai-eshop-optimizer'),
                    'i18nExportSuccess' => __('🎉 Export process completed successfully!', 'ai-eshop-optimizer'),
                    'i18nExportFailed' => __('❌ Export process failed. Please check the errors above.', 'ai-eshop-optimizer'),
                    'i18nNoExportRequested' => __('✓ Process complete. No export file was requested.', 'ai-eshop-optimizer'),

                    
                    'i18nLoadingDownload' => __('Loading download section...', 'ai-eshop-optimizer'),
                    'i18nDownloadLoaded' => __('✓ Download section loaded! Scroll down to download your file.', 'ai-eshop-optimizer'),
                    
                    'i18nRetrying' => __('File not ready yet, retrying... (%1$d/%2$d)', 'ai-eshop-optimizer'),
                    
                    'i18nDownloadFailed' => __('⚠ Could not load download section after %d attempts.', 'ai-eshop-optimizer'),
                    'i18nRefreshPage' => __('Please refresh the page to see the download link.', 'ai-eshop-optimizer'),
                    
                    'i18nErrorRetrying' => __('Error loading, retrying... (%1$d/%2$d)', 'ai-eshop-optimizer'),
                    
                    'i18nErrorDownloadFailed' => __('⚠ Error loading download section after %d attempts.', 'ai-eshop-optimizer'),
                    'i18nErrorDetails' => __('Error details: ', 'ai-eshop-optimizer'),

                    
                    'i18nCheckingStats' => __('Checking for statistics...', 'ai-eshop-optimizer'),
                    'i18nStatsLoaded' => __('✓ Statistics section loaded!', 'ai-eshop-optimizer'),
                    
                    'i18nStatsRetrying' => __('Statistics not ready yet, retrying... (%1$d/%2$d)', 'ai-eshop-optimizer'),
                    'i18nStatsNotAvailable' => __('⚠ Statistics not available: ', 'ai-eshop-optimizer'),
                    'i18nRefreshLater' => __('You may need to refresh the page later.', 'ai-eshop-optimizer'),
                    
                    'i18nStatsErrorRetrying' => __('Error loading statistics, retrying... (%1$d/%2$d)', 'ai-eshop-optimizer'),
                    'i18nStatsLoadError' => __('⚠ Could not load statistics section: ', 'ai-eshop-optimizer'),
                    'i18nServerResponse' => __('Server response: ', 'ai-eshop-optimizer'),
                    'i18nCheckConsole' => __('Check browser console for full error details', 'ai-eshop-optimizer'),
                    'i18nUnknownError' => __('Unknown error', 'ai-eshop-optimizer'),

                    
                    'i18nUpsellConfirm' => __('Start exporting current upsell/cross-sell assignments? This may take a few minutes.', 'ai-eshop-optimizer'),
                    'i18nUpsellComplete' => __('✓ Upsell export completed successfully!', 'ai-eshop-optimizer'),
                    'i18nUpsellFailed' => __('❌ Upsell export failed. Please review the log and try again.', 'ai-eshop-optimizer'),
                    'i18nUpsellExportError' => __('Unexpected error during upsell export.', 'ai-eshop-optimizer'),
                    'i18nAjaxErrorUpsellExport' => __('AJAX error in upsell export: ', 'ai-eshop-optimizer'),
                    'i18nUpsellExportInitFailed' => __('Failed to initialize upsell export.', 'ai-eshop-optimizer'),
                    'i18nUpsellExportComplete' => __('Upsell export complete.', 'ai-eshop-optimizer'),
                    'i18nUpsellExportStarted' => __('Upsell export started.', 'ai-eshop-optimizer'),
                    'i18nStartingExport' => __('Starting export...', 'ai-eshop-optimizer'),
                    'i18nAjaxErrorUpsellInit' => __('AJAX error while initializing upsell export: ', 'ai-eshop-optimizer'),

                    
                    'i18nUpsellImportConfirm' => __('Start importing the uploaded upsell and cross-sell recommendations?', 'ai-eshop-optimizer'),
                    'i18nUpsellImportComplete' => __('✓ Upsell import completed successfully!', 'ai-eshop-optimizer'),
                    'i18nUpsellImportFailed' => __('❌ Upsell import failed. Please review the log and try again.', 'ai-eshop-optimizer'),
                    'i18nUpsellImportSelect' => __('Please choose a CSV file before starting the import.', 'ai-eshop-optimizer'),
                    'i18nUpsellImportError' => __('Unexpected error during upsell import.', 'ai-eshop-optimizer'),
                    'i18nAjaxErrorUpsellImport' => __('AJAX error in upsell import: ', 'ai-eshop-optimizer'),
                    'i18nUpsellImportInitFailed' => __('Failed to initialize upsell import.', 'ai-eshop-optimizer'),
                    'i18nUpsellImportCompleted' => __('Upsell import completed.', 'ai-eshop-optimizer'),
                    'i18nUpsellImportStarted' => __('Upsell import started.', 'ai-eshop-optimizer'),
                    'i18nStartingImport' => __('Starting import...', 'ai-eshop-optimizer'),
                    'i18nAjaxErrorUpsellImportInit' => __('AJAX error while initializing upsell import: ', 'ai-eshop-optimizer'),

                    
                    'i18nInitializing' => __('Initializing...', 'ai-eshop-optimizer'),
                    'i18nProcessingBatch' => __('Processing batch...', 'ai-eshop-optimizer'),

                    
                    'i18nDownloadCSV' => __('Download CSV', 'ai-eshop-optimizer'),
                    'i18nOptimizing' => __('Optimizing...', 'ai-eshop-optimizer'),
                    'i18nPleaseWaitOptimizing' => __('Please wait, optimizing database indexes...', 'ai-eshop-optimizer'),
                    'i18nSuccess' => __('✓ Success!', 'ai-eshop-optimizer'),
                    'i18nOptimizationComplete' => __('✓ Optimization Complete', 'ai-eshop-optimizer'),
                    'i18nError' => __('✗ Error:', 'ai-eshop-optimizer'),
                    'i18nRetryOptimization' => __('Retry Optimization', 'ai-eshop-optimizer'),
                    'i18nServerCommError' => __('Failed to communicate with server', 'ai-eshop-optimizer'),
                    'i18nLoading' => __('Loading...', 'ai-eshop-optimizer'),
                    'i18nRefreshIndexes' => __('Refresh Indexes', 'ai-eshop-optimizer'),
                    'i18nNoIndexesFound' => __('No indexes found or error loading data.', 'ai-eshop-optimizer'),
                    'i18nRetry' => __('Retry', 'ai-eshop-optimizer'),
                    'i18nErrorLoadingIndexes' => __('Error loading index information.', 'ai-eshop-optimizer'),
                    'i18nFixingCollations' => __('Fixing Collations...', 'ai-eshop-optimizer'),
                    'i18nPleaseWaitCollations' => __('Please wait, standardizing collations...', 'ai-eshop-optimizer'),
                    'i18nCollationFixComplete' => __('✓ Collation Fix Complete', 'ai-eshop-optimizer'),
                    'i18nRetryCollationFix' => __('Retry Collation Fix', 'ai-eshop-optimizer'),
                    'i18nConfirmCollationFix' => __('This will standardize all table collations to utf8mb4_unicode_ci. Continue?', 'ai-eshop-optimizer'),

                    
                    'stageNames' => array(
                        'create_attributes' => __('Creating product core attributes and categories', 'ai-eshop-optimizer'),
                        'create_needs' => __('Populating product needs', 'ai-eshop-optimizer'),
                        'create_catalogue' => __('Creating full product catalogue', 'ai-eshop-optimizer'),
                        'process_eshop_orders' => __('Processing eshop orders', 'ai-eshop-optimizer'),
                        'process_instore_orders' => __('Processing in-store orders', 'ai-eshop-optimizer'),
                        'merge_orders' => __('Merging orders', 'ai-eshop-optimizer'),
                        'include_unsold' => __('Including unsold products', 'ai-eshop-optimizer'),
                        'aggregate_product_stats' => __('Aggregating product statistics', 'ai-eshop-optimizer'),
                        'aggregate_category_brand_stats' => __('Aggregating category/brand popularity', 'ai-eshop-optimizer'),
                        'aggregate_customer_std_stats' => __('Aggregating customer standard statistics', 'ai-eshop-optimizer'),
                        'aggregate_customer_adv_stats' => __('Aggregating customer advanced statistics', 'ai-eshop-optimizer'),
                        'create_uuids' => __('Creating UUIDs', 'ai-eshop-optimizer'),
                        'create_need_suggestions' => __('Generating need-based suggestions', 'ai-eshop-optimizer'),
                        'create_export' => __('Creating export file', 'ai-eshop-optimizer')
                    )
                )
            );
        }

        
        public function aieo_add_admin_menu()
        {
            
            $custom_icon = AIEO_URI . 'assets/images/aieo-icon.webp';

            
            
            $hook_suffix = add_menu_page(
                __('AI eShop Optimizer', 'ai-eshop-optimizer'), 
                __('AI Optimizer', 'ai-eshop-optimizer'),       
                AIEO_CAPABILITY,                                
                'ai-eshop-optimizer',                           
                array($this, 'render_eshop_optimizer_admin_page'), 
                $custom_icon,                                   
                26                                              
            );

            
            add_submenu_page(
                'ai-eshop-optimizer',                           
                __('Data Prep', 'ai-eshop-optimizer'),          
                __('⚙️ Data Prep', 'ai-eshop-optimizer'),       
                AIEO_CAPABILITY,                                
                'ai-eshop-optimizer',                           
                array($this, 'render_eshop_optimizer_admin_page') 
            );

            
            add_action('admin_enqueue_scripts', function ($hook) use ($hook_suffix) {
                if ($hook == $hook_suffix) {
                    $this->aieo_enqueue_styles_scripts(); 
                }
            });
        }

        
        public function aieo_reorder_admin_submenu()
        {
            global $submenu;
            $parent = 'ai-eshop-optimizer';
            if (empty($submenu[$parent]) || !is_array($submenu[$parent])) { return; }

            
            remove_submenu_page($parent, 'aieo-session-migration');

            
            $order = array(
                'ai-eshop-optimizer'         => 0, 
                'ai-eshop-dmm'               => 1, 
                'ai-eshop-chat'              => 2, 
                'aieo-iapi'                  => 3, 
                'aieo-recommendations-cache' => 4, 
            );
            usort($submenu[$parent], function ($a, $b) use ($order) {
                $ra = isset($a[2], $order[$a[2]]) ? $order[$a[2]] : 900;
                $rb = isset($b[2], $order[$b[2]]) ? $order[$b[2]] : 900;
                return ($ra === $rb) ? 0 : (($ra < $rb) ? -1 : 1);
            });
        }

        public function aieo_add_admin_bar_menu($wp_admin_bar) {
            if (!current_user_can(AIEO_CAPABILITY)) { return; }

            $icon_url = AIEO_URI . 'assets/images/aieo-icon.webp';
            $icon_img = '<img src="' . esc_url($icon_url) . '" style="display:inline-block;height:20px;width:20px;vertical-align:middle;margin-right:6px;border-radius:3px;max-width:none;" alt="">';

            $wp_admin_bar->add_node(array(
                'id'    => 'aieo-toolbar',
                'title' => $icon_img . 'AI Optimizer',
                'href'  => admin_url('admin.php?page=ai-eshop-optimizer'),
                'meta'  => array('class' => 'aieo-toolbar-node'),
            ));

            $items = array(
                array('data-prep',     'Data Prep',      'ai-eshop-optimizer'),
                array('eshop-manager', 'e-shop Manager', 'ai-eshop-dmm'),
                array('ai-chat',       'AI Chat',        'ai-eshop-chat'),
            );
            foreach ($items as $item) {
                $wp_admin_bar->add_node(array(
                    'id'     => 'aieo-toolbar-' . $item[0],
                    'parent' => 'aieo-toolbar',
                    'title'  => $item[1],
                    'href'   => admin_url('admin.php?page=' . $item[2]),
                ));
            }
        }

        
        public function aieo_admin_bar_css()
        {
            if (!is_admin_bar_showing() || !current_user_can(AIEO_CAPABILITY)) { return; }
            echo '<style id="aieo-toolbar-css">'
                . '#wpadminbar #wp-admin-bar-aieo-toolbar > .ab-item{white-space:nowrap !important;}'
                . '#wpadminbar #wp-admin-bar-aieo-toolbar > .ab-item img{display:inline-block !important;float:none !important;height:20px !important;width:20px !important;max-width:none !important;margin:0 6px 0 0 !important;padding:0 !important;vertical-align:middle !important;border-radius:3px;box-shadow:none !important;}'
                . '</style>';
        }

        public function aieo_display_all_admin_notices()
        {
            

            
            if ($products_impacted = get_transient('aieo_products_updated_count')) {
                $message = sprintf(
                    
                    _n('%d product has been updated in the catalogue.', '%d products have been updated in the catalogue.', $products_impacted, 'ai-eshop-optimizer'),
                    esc_html($products_impacted)
                );
                echo '<div class="notice notice-success is-dismissible"><p>' . esc_html($message) . '</p></div>';
                delete_transient('aieo_products_updated_count');
                
            }

            
            global $pagenow;
            if ($pagenow == 'admin.php' && isset($_GET['page']) && $_GET['page'] == 'ai-eshop-optimizer') {
                if (isset($_GET['exported_orders']) && $_GET['exported_orders'] == '1') {
                    
                    $nonce = isset($_GET['_wpnonce']) ? sanitize_text_field(wp_unslash($_GET['_wpnonce'])) : '';
                    
                    if ($nonce && wp_verify_nonce($nonce, 'exported_orders_action')) {
                        $message = get_option('aieo_export_orders_message', false);
                        if ($message) {
                            
                            echo '<div class="notice notice-success is-dismissible"><p>' . esc_html($message) . '</p></div>';
                            delete_option('aieo_export_orders_message');
                        }
                    } else {
                        wp_die(esc_html__('Security check failed.', 'ai-eshop-optimizer')); 
                    }
                }
            }

            
            if ($notice = get_transient('aieo_upload_notice')) {
                echo '<div class="notice notice-success is-dismissible"><p>' . esc_html($notice) . '</p></div>';
                delete_transient('aieo_upload_notice');
                
            }
            if ($error = get_transient('aieo_upload_error')) {
                echo '<div class="notice notice-error is-dismissible"><p>' . esc_html($error) . '</p></div>';
                delete_transient('aieo_upload_error');
                
            }

            
            $account_message = get_option('aieo_account_message', false);
            if ($account_message) {
                $class = strpos($account_message, 'Error') !== false ? 'notice-error' : 'notice-success';
                echo '<div class="notice ' . esc_attr($class) . ' is-dismissible"><p>' . wp_kses_post($account_message) . '</p></div>';
                delete_option('aieo_account_message');
                
            }

            
            $remote_connection_message = get_option('aieo_remote_connection_message', false);
            if ($remote_connection_message) {
                $class = strpos($remote_connection_message, 'Error') !== false ? 'notice-error' : 'notice-success';
                echo '<div class="notice ' . esc_attr($class) . ' is-dismissible"><p>' . esc_html($remote_connection_message) . '</p></div>';
                delete_option('aieo_remote_connection_message');
                
            }

            
            $file_deletion_message = get_option('aieo_file_deletion_message', false);
            if ($file_deletion_message) {
                $class = strpos($file_deletion_message, 'Error') !== false ? 'notice-error' : 'notice-success';
                echo '<div class="notice ' . esc_attr($class) . ' is-dismissible"><p>' . esc_html($file_deletion_message) . '</p></div>';
                delete_option('aieo_file_deletion_message');
            }
        }

        public function aieo_handle_display_references_setting()
        {
            
            if (
                isset($_POST['eshop_optimizer_nonce_field_1']) && 
                wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['eshop_optimizer_nonce_field_1'])), 'eshop_optimizer_update_display_preferences') 
            ) {
                if (current_user_can(AIEO_CAPABILITY)) {
                    
                    update_option('aieo_display_upsells', isset($_POST['aieo_display_upsells']) ? '1' : '0');
                    update_option('aieo_display_cross_sells', isset($_POST['aieo_display_cross_sells']) ? '1' : '0');
                    update_option('aieo_display_related', isset($_POST['aieo_display_related']) ? '1' : '0');
                    update_option('aieo_display_recently_viewed_products', isset($_POST['aieo_display_recently_viewed_products']) ? '1' : '0');
                    update_option('aieo_display_same_needs', isset($_POST['aieo_display_same_needs']) ? '1' : '0');
                    update_option('aieo_display_categories_by_sales', isset($_POST['aieo_display_categories_by_sales']) ? '1' : '0');
                    update_option('aieo_category_sales_period', isset($_POST['aieo_category_sales_period']) ? sanitize_text_field(wp_unslash($_POST['aieo_category_sales_period'])) : 'all_time');
                    update_option('aieo_recommendations_display_order', isset($_POST['aieo_recommendations_display_order']) ? '1' : '0');
                }
            } else {
                
                wp_die(esc_html__('Invalid nonce!', 'ai-eshop-optimizer')); 
            }

            
            wp_safe_redirect(esc_url(admin_url('admin.php?page=ai-eshop-optimizer')));
            exit;
        }

        public function aieo_handle_utm_stats_setting()
        {
            
            if (
                isset($_POST['eshop_optimizer_utm_stats_nonce_2']) &&
                wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['eshop_optimizer_utm_stats_nonce_2'])), 'eshop_optimizer_utm_stats_action')
            ) {
                
                if (current_user_can(AIEO_CAPABILITY)) {
                    
                    if (isset($_POST['aieo_activate_utm_stats'])) {
                        $ga4tag = isset($_POST['aieo_google_ga4']) ? sanitize_text_field(wp_unslash($_POST['aieo_google_ga4'])) : '';
                        update_option('aieo_activate_utm_stats', 1);
                        update_option('aieo_google_ga4', $ga4tag);
                    } else {
                        delete_option('aieo_activate_utm_stats');
                        delete_option('aieo_google_ga4');
                    }
                }

                
                wp_safe_redirect(esc_url(admin_url('admin.php?page=ai-eshop-optimizer')));
                exit;
            }

            
        }

        
        public function aieo_handle_session_tracker_setting()
        {
            
            if (
                isset($_POST['eshop_optimizer_session_tracker_nonce']) &&
                wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['eshop_optimizer_session_tracker_nonce'])), 'eshop_optimizer_session_tracker_action')
            ) {
                
                if (current_user_can(AIEO_CAPABILITY)) {
                    
                    if (isset($_POST['aieo_session_tracking_enabled'])) {
                        update_option('aieo_session_tracking_enabled', 1);
                    } else {
                        update_option('aieo_session_tracking_enabled', 0);
                    }

                    
                    if (isset($_POST['aieo_track_scroll_depth'])) {
                        update_option('aieo_track_scroll_depth', 1);
                    } else {
                        update_option('aieo_track_scroll_depth', 0);
                    }

                    
                    if (isset($_POST['aieo_track_clicks'])) {
                        update_option('aieo_track_clicks', 1);
                    } else {
                        update_option('aieo_track_clicks', 0);
                    }

                    
                    if (isset($_POST['aieo_throttle_clicks'])) {
                        update_option('aieo_throttle_clicks', 1);
                    } else {
                        update_option('aieo_throttle_clicks', 0);
                    }

                    
                    if (isset($_POST['aieo_session_bypass_consent'])) {
                        update_option('aieo_session_bypass_consent', 1);
                    } else {
                        update_option('aieo_session_bypass_consent', 0);
                    }

                    
                    if (isset($_POST['aieo_custom_image_click_rules'])) {
                        update_option('aieo_custom_image_click_rules', sanitize_textarea_field(wp_unslash($_POST['aieo_custom_image_click_rules'])));
                    }

                    
                    if (isset($_POST['aieo_session_retention_days'])) {
                        $retention_days = absint(wp_unslash($_POST['aieo_session_retention_days']));
                        
                        $retention_days = max(7, min(90, $retention_days));
                        update_option('aieo_session_retention_days', $retention_days);
                    }

                    
                    if (isset($_POST['aieo_session_archive_frequency'])) {
                        $frequency = sanitize_text_field(wp_unslash($_POST['aieo_session_archive_frequency']));
                        $allowed_frequencies = array('daily', 'weekly', 'monthly');
                        if (in_array($frequency, $allowed_frequencies)) {
                            update_option('aieo_session_archive_frequency', $frequency);
                            
                            $tracker = AIEO_Session_Tracker::get_instance();
                            $tracker->schedule_archive_cron();
                        }
                    }

                    
                    if (isset($_POST['aieo_session_archive_hour'])) {
                        $hour = absint(wp_unslash($_POST['aieo_session_archive_hour']));
                        
                        $hour = max(0, min(23, $hour));
                        update_option('aieo_session_archive_hour', $hour);
                        
                        $tracker = AIEO_Session_Tracker::get_instance();
                        $tracker->schedule_archive_cron();
                    }

                    
                    $this->generate_custom_tracker_js();

                    
                    
                    $base = time();
                    $random_suffix = wp_rand(1, 999999999); 
                    $new_version = $base . $random_suffix;
                    
                    $new_version = substr($new_version, 0, wp_rand(8, strlen($new_version)));
                    update_option('aieo_session_tracker_version', $new_version);
                }

                
                wp_safe_redirect(esc_url(admin_url('admin.php?page=ai-eshop-optimizer')));
                exit;
            }

            
        }

        
        private function generate_custom_tracker_js()
        {
            
            $custom_rules_raw = get_option('aieo_custom_image_click_rules', '');
            $rules_js_code = '';

            if (!empty($custom_rules_raw)) {
                $lines = array_filter(array_map('trim', explode("\n", $custom_rules_raw)));
                $rules = array();

                foreach ($lines as $line) {
                    if (strpos($line, '|') !== false) {
                        list($event_name, $selector) = array_map('trim', explode('|', $line, 2));
                        if (!empty($event_name) && !empty($selector)) {
                            $event_name_safe = sanitize_key($event_name);
                            $selector_safe = addslashes($selector);
                            $rules[] = "                        // Rule: {$event_name_safe}\n" .
                                     "                        if (\$target.is('{$selector_safe}') || \$target.closest('{$selector_safe}').length > 0 || \$target.find('{$selector_safe}').length > 0) {\n" .
                                     "                            self.clickCount++;  // Count custom rule click\n" .
                                     "                            self.trackCustomClick(\$target, '{$event_name_safe}');\n" .
                                     "                            return true;  // Prevent double tracking\n" .
                                     "                        }";
                        }
                    }
                }

                if (!empty($rules)) {
                    $rules_js_code = "\n" . implode("\n\n", $rules) . "\n                        return false;  // No custom rule matched";
                }
            }

            
            update_option('aieo_custom_image_click_rules_js', $rules_js_code);
        }

        public function render_eshop_optimizer_admin_page()
        {
            
            header('Cache-Control: no-cache, no-store, must-revalidate');
            header('Pragma: no-cache');
            header('Expires: 0');

            
            
            wp_cache_delete('aieo_create_attributes', 'options');
            wp_cache_delete('aieo_create_catalogue', 'options');
            wp_cache_delete('aieo_create_orders', 'options');
            wp_cache_delete('aieo_erp_consolidation', 'options');
            wp_cache_delete('aieo_erp_merge_orders', 'options');
            wp_cache_delete('aieo_include_unsold', 'options');
            wp_cache_delete('aieo_include_aggregate_stats', 'options');
            wp_cache_delete('aieo_include_aggregate_cust_std_stats', 'options');
            wp_cache_delete('aieo_include_aggregate_cust_adv_stats', 'options');
            wp_cache_delete('aieo_create_uuids', 'options');
            wp_cache_delete('aieo_create_export', 'options');
            
            wp_cache_delete('aieo_include_text', 'options');
            wp_cache_delete('aieo_include_attributes', 'options');
            wp_cache_delete('aieo_include_full_text', 'options');
            wp_cache_delete('aieo_include_price', 'options');
            wp_cache_delete('aieo_variations_choice', 'options');
            wp_cache_delete('aieo_include_eponymous', 'options');
            
            wp_cache_delete('aieo_include_reciprocity', 'options');
            wp_cache_delete('aieo_include_seasonality', 'options');
            wp_cache_delete('aieo_include_restricted_seasonality', 'options');
            wp_cache_delete('aieo_instore_anonymous', 'options');
            
            wp_cache_delete('aieo_season_days_past', 'options');
            wp_cache_delete('aieo_season_days_after', 'options');

            require_once AIEO_DIR . 'assets/pages/ai-eshop-optimizer.php';

            add_filter('admin_footer_text', array($this, 'aieo_wpse_edit_text'), 11);
        }

        
        public function aieo_export_upsells_cross_sells_to_csv()
        {
            wp_die(esc_html__('This export now runs asynchronously. Please use the Export button on the settings page to generate the file.', 'ai-eshop-optimizer'));
        }

        
        public function aieo_init_upsell_export()
        {
            check_ajax_referer('aieo_export_nonce', 'nonce');

            if (!current_user_can(AIEO_CAPABILITY)) {
                wp_send_json_error(array('message' => __('Insufficient permissions.', 'ai-eshop-optimizer')));
                return;
            }

            global $wpdb;

            $statuses = apply_filters('aieo_upsell_export_statuses', array('publish', 'private', 'draft', 'pending', 'future'));
            $placeholders = implode(',', array_fill(0, count($statuses), '%s'));
            $total_products = (int) $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_type = %s AND post_status IN ({$placeholders})",
                array_merge(array('product'), $statuses)
            ));

            $uploads_dir = wp_upload_dir();
            $parsed_url = wp_parse_url(home_url());
            $domain = isset($parsed_url['host']) ? $parsed_url['host'] : 'site';
            $timestamp = gmdate('Ymd_His');
            $export_id = uniqid('upsell_export_', true);
            $filename = sprintf('%s_upsells_crossells_%s_%s.csv', $domain, $timestamp, substr(md5($export_id), 0, 8));
            $file_path = trailingslashit($uploads_dir['basedir']) . $filename;
            $file_url = trailingslashit($uploads_dir['baseurl']) . $filename;

            if (!function_exists('wp_mkdir_p')) {
                require_once ABSPATH . 'wp-admin/includes/file.php';
            }
            if (!wp_mkdir_p(dirname($file_path))) {
                wp_send_json_error(array('message' => __('Unable to prepare export directory.', 'ai-eshop-optimizer')));
                return;
            }

            $state = array(
                'file_path' => $this->aieo_normalize_path($file_path),
                'file_url' => $file_url,
                'file_name' => $filename,
                'header_written' => false,
                'last_id' => 0,
                'processed' => 0,
                'total' => $total_products,
                'batch_size' => 3000,
                'statuses' => $statuses,
            );

            set_transient('aieo_upsell_export_state_' . $export_id, $state, 2 * HOUR_IN_SECONDS);

            if ($total_products === 0) {
                
                
                $handle = fopen($state['file_path'], 'w');
                if ($handle) {
                    fputcsv($handle, array('original_product_id', 'related_upsells_list', 'related_crossells_list', 'aieo_neo4j_params'));
                    
                    fclose($handle);
                }
                update_option('aieo_last_upsell_export', array(
                    'filename' => $filename,
                    'path' => $state['file_path'],
                    'url' => $file_url,
                    'generated_at' => current_time('mysql', true),
                ));
                delete_transient('aieo_upsell_export_state_' . $export_id);

                wp_send_json_success(array(
                    'complete' => true,
                    'message' => __('No products found. Generated empty export file.', 'ai-eshop-optimizer'),
                    'download_url' => $file_url,
                    'filename' => $filename,
                ));
                return;
            }

            wp_send_json_success(array(
                
                'message' => sprintf(__('Initializing upsell & cross-sell export for %d products...', 'ai-eshop-optimizer'), $total_products),
                'export_id' => $export_id,
                'total' => $total_products,
            ));
        }

        
        public function aieo_process_upsell_batch()
        {
            check_ajax_referer('aieo_export_nonce', 'nonce');

            if (!current_user_can(AIEO_CAPABILITY)) {
                wp_send_json_error(array('message' => __('Insufficient permissions.', 'ai-eshop-optimizer')));
                return;
            }

            $export_id = isset($_POST['export_id']) ? sanitize_text_field(wp_unslash($_POST['export_id'])) : '';
            if (!$export_id) {
                wp_send_json_error(array('message' => __('Missing export identifier.', 'ai-eshop-optimizer')));
                return;
            }

            $state_key = 'aieo_upsell_export_state_' . $export_id;
            $state = get_transient($state_key);
            if (!$state) {
                wp_send_json_error(array('message' => __('Export session expired. Please restart the export.', 'ai-eshop-optimizer')));
                return;
            }

            global $wpdb;

            $statuses = $state['statuses'];
            $placeholders = implode(',', array_fill(0, count($statuses), '%s'));
            $batch_size = (int) $state['batch_size'];
            $last_id = (int) $state['last_id'];

            
            $product_ids = $wpdb->get_col($wpdb->prepare(
                "SELECT ID FROM {$wpdb->posts}
                 WHERE post_type = %s
                 AND post_status IN ({$placeholders})
                 AND ID > %d
                 ORDER BY ID ASC
                 LIMIT %d",
                array_merge(array('product'), $statuses, array($last_id, $batch_size))
            ));

            if (empty($product_ids)) {
                
                update_option('aieo_last_upsell_export', array(
                    'filename' => $state['file_name'],
                    'path' => $state['file_path'],
                    'url' => $state['file_url'],
                    'generated_at' => current_time('mysql', true),
                ));
                delete_transient($state_key);

                wp_send_json_success(array(
                    'complete' => true,
                    
                    'message' => sprintf(__('✓ Upsell & cross-sell export completed: %d products processed.', 'ai-eshop-optimizer'), $state['processed']),
                    'download_url' => $state['file_url'],
                    'filename' => $state['file_name'],
                    'current' => $state['processed'],
                    'total' => $state['total'],
                ));
                return;
            }

            set_time_limit(0);

            
            $handle = fopen($state['file_path'], $state['header_written'] ? 'a' : 'w');
            if (!$handle) {
                delete_transient($state_key);
                wp_send_json_error(array('message' => __('Unable to write to export file.', 'ai-eshop-optimizer')));
                return;
            }

            if (!$state['header_written']) {
                fputcsv($handle, array('original_product_id', 'related_upsells_list', 'related_crossells_list', 'aieo_neo4j_params'));
                $state['header_written'] = true;
            }

            update_postmeta_cache($product_ids);

            foreach ($product_ids as $product_id) {
                $upsells = get_post_meta($product_id, '_upsell_ids', true);
                $upsells = is_array($upsells) ? array_map('intval', $upsells) : array();
                $upsells = array_filter($upsells);

                $crossells = get_post_meta($product_id, '_crosssell_ids', true);
                $crossells = is_array($crossells) ? array_map('intval', $crossells) : array();
                $crossells = array_filter($crossells);

                $params = get_post_meta($product_id, 'aieo_neo4j_params', true);
                if (is_array($params) || is_object($params)) {
                    $params = wp_json_encode($params);
                }
                $params = is_scalar($params) ? (string) $params : '';

                fputcsv($handle, array(
                    $product_id,
                    implode(',', $upsells),
                    implode(',', $crossells),
                    $params,
                ));
            }

            
            fclose($handle);

            $state['processed'] += count($product_ids);
            $state['last_id'] = (int) end($product_ids);

            set_transient($state_key, $state, 2 * HOUR_IN_SECONDS);
            update_option('aieo_upsell_import_state_store_' . $import_id, $state, false);

            $percent = $state['total'] > 0 ? round(($state['processed'] / $state['total']) * 100) : 100;

            wp_send_json_success(array(
                'complete' => false,
                'message' => sprintf(
                    
                    __('Processing products %1$d-%2$d of %3$d (%4$s%% complete)...', 'ai-eshop-optimizer'),
                    max(1, $state['processed'] - count($product_ids) + 1),
                    $state['processed'],
                    $state['total'],
                    $percent
                ),
                'current' => $state['processed'],
                'total' => $state['total'],
                'progress' => $percent,
            ));
        }

        
        public function aieo_init_upsell_import()
        {
            check_ajax_referer('aieo_export_nonce', 'nonce');

            if (!current_user_can(AIEO_CAPABILITY)) {
                wp_send_json_error(array('message' => __('Insufficient permissions.', 'ai-eshop-optimizer')));
                return;
            }

            if (!isset($_POST['eshop_optimizer_process_params_nonce_6']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['eshop_optimizer_process_params_nonce_6'])), 'eshop_optimizer_handle_upload_action')) {
                wp_send_json_error(array('message' => __('Security check failed. Please reload the page and try again.', 'ai-eshop-optimizer')));
                return;
            }

            if (empty($_FILES['csv_file']['tmp_name'])) {
                wp_send_json_error(array('message' => __('Please select a CSV file to upload.', 'ai-eshop-optimizer')));
                return;
            }

            global $wpdb;

            $monitor = isset($_POST['aieo_monitor_performance']) && sanitize_text_field(wp_unslash($_POST['aieo_monitor_performance'])) === '1';
            $batch_size = isset($_POST['aieo_batch_size']) ? max(1, intval(sanitize_text_field(wp_unslash($_POST['aieo_batch_size'])))) : 300;
            $batch_sleep = isset($_POST['aieo_batch_sleep']) ? max(0, intval(sanitize_text_field(wp_unslash($_POST['aieo_batch_sleep'])))) : 0;

            update_option('aieo_monitor_performance', $monitor ? '1' : '0');
            update_option('aieo_batch_size', $batch_size);
            update_option('aieo_batch_sleep', $batch_sleep);

            $table_name = $wpdb->prefix . 'aieo_' . gmdate('Y_m') . '_new_recommendations';
            if (!preg_match('/^[a-zA-Z0-9_]+$/', $table_name)) {
                wp_send_json_error(array('message' => __('Invalid temporary table name.', 'ai-eshop-optimizer')));
                return;
            }

            $wpdb->query("DROP TABLE IF EXISTS `{$table_name}`");
            $wpdb->query("CREATE TABLE `{$table_name}` (
                original_product_id BIGINT(20) UNSIGNED NOT NULL,
                related_upsells_list TEXT,
                related_crossells_list TEXT,
                aieo_neo4j_params TEXT,
                PRIMARY KEY (original_product_id)
            )");

            if ($monitor) {
                $performance_table = $wpdb->prefix . 'aieo_performance_tuning';
                $wpdb->query("DROP TABLE IF EXISTS {$performance_table}");
                $wpdb->query("CREATE TABLE {$performance_table} (
                        id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
                        batch_size INT(11) UNSIGNED NOT NULL,
                        processing_time FLOAT NOT NULL,
                        total_processing_time FLOAT NOT NULL,
                        date_recorded TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                        PRIMARY KEY (id)
                    )");
            }

            if (!function_exists('wp_handle_upload')) {
                require_once ABSPATH . 'wp-admin/includes/file.php';
            }

            
            $uploaded_file = $_FILES['csv_file'];
            $uploaded_file['name'] = sanitize_file_name($uploaded_file['name']);
            $movefile = wp_handle_upload($uploaded_file, array('test_form' => false));

            if (!$movefile || isset($movefile['error'])) {
                wp_send_json_error(array('message' => isset($movefile['error']) ? $movefile['error'] : __('Upload failed.', 'ai-eshop-optimizer')));
                return;
            }

            $file_path = $movefile['file'];
            
            $handle = fopen($file_path, 'r');
            if (!$handle) {
                wp_delete_file($file_path);
                wp_send_json_error(array('message' => __('Unable to open uploaded file.', 'ai-eshop-optimizer')));
                return;
            }

            set_time_limit(0);

            $row_number = 0;
            while (($row = fgetcsv($handle)) !== false) {
                if ($row_number === 0) {
                    $row_number++;
                    continue; 
                }

                if (empty($row)) {
                    continue;
                }

                $product_id = isset($row[0]) ? intval($row[0]) : 0;
                if ($product_id <= 0) {
                    continue;
                }

                $upsells = isset($row[1]) ? sanitize_text_field($row[1]) : '';
                $crossells = isset($row[2]) ? sanitize_text_field($row[2]) : '';
                $params = isset($row[3]) ? sanitize_text_field($row[3]) : '';

                $wpdb->replace(
                    $table_name,
                    array(
                        'original_product_id' => $product_id,
                        'related_upsells_list' => $upsells,
                        'related_crossells_list' => $crossells,
                        'aieo_neo4j_params' => $params,
                    ),
                    array('%d', '%s', '%s', '%s')
                );
            }

            
            fclose($handle);

            $total_rows = (int) $wpdb->get_var("SELECT COUNT(*) FROM `{$table_name}` WHERE related_upsells_list <> '' OR related_crossells_list <> ''");

            if ($total_rows === 0) {
                wp_delete_file($file_path);
                $wpdb->query("DROP TABLE IF EXISTS `{$table_name}`");
                wp_send_json_success(array(
                    'complete' => true,
                    'message' => __('No records found in the uploaded file. Nothing to import.', 'ai-eshop-optimizer'),
                    'total' => 0,
                ));
                return;
            }

            $import_id = uniqid('upsell_import_', true);
            $state = array(
                'table' => $table_name,
                'file' => $file_path,
                'processed' => 0,
                'impacted' => 0,
                'total' => $total_rows,
                'last_id' => 0,
                'batch_size' => $batch_size,
                'batch_sleep' => $batch_sleep,
                'monitor' => $monitor,
            );

            set_transient('aieo_upsell_import_state_' . $import_id, $state, 2 * HOUR_IN_SECONDS);
            update_option('aieo_upsell_import_state_store_' . $import_id, $state, false);

            wp_send_json_success(array(
                
                'message' => sprintf(__('Initializing upsell import for %d records...', 'ai-eshop-optimizer'), $total_rows),
                'import_id' => $import_id,
                'total' => $total_rows,
            ));
        }

        
        public function aieo_process_upsell_import_batch()
        {
            check_ajax_referer('aieo_export_nonce', 'nonce');

            if (!current_user_can(AIEO_CAPABILITY)) {
                wp_send_json_error(array('message' => __('Insufficient permissions.', 'ai-eshop-optimizer')));
                return;
            }

            $import_id = isset($_POST['import_id']) ? sanitize_text_field(wp_unslash($_POST['import_id'])) : '';
            if (!$import_id) {
                wp_send_json_error(array('message' => __('Missing import identifier.', 'ai-eshop-optimizer')));
                return;
            }

            $state_key = 'aieo_upsell_import_state_' . $import_id;
            $state = get_transient($state_key);
            if (!$state || !is_array($state)) {
                $state = get_option('aieo_upsell_import_state_store_' . $import_id, false);
            }
            if (!$state || !is_array($state)) {
                delete_option('aieo_upsell_import_state_store_' . $import_id);
                wp_send_json_error(array('message' => __('Import session expired. Please restart the import.', 'ai-eshop-optimizer')));
                return;
            }

            global $wpdb;

            $table_name = $state['table'];
            if (!preg_match('/^[a-zA-Z0-9_]+$/', $table_name)) {
                delete_transient($state_key);
                wp_send_json_error(array('message' => __('Invalid temporary table detected.', 'ai-eshop-optimizer')));
                return;
            }

            $batch_size = max(1, (int) $state['batch_size']);
            $batch_sleep = max(0, (int) $state['batch_sleep']);
            $last_id = (int) $state['last_id'];

            set_time_limit(0);

            $rows = $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM `{$table_name}`
                 WHERE (related_upsells_list <> '' OR related_crossells_list <> '')
                 AND original_product_id > %d
                 ORDER BY original_product_id ASC
                 LIMIT %d",
                $last_id,
                $batch_size
            ), ARRAY_A);

            if (empty($rows)) {
                wp_delete_file($state['file']);
                $wpdb->query("DROP TABLE IF EXISTS `{$table_name}`");
                delete_transient($state_key);
                delete_option('aieo_upsell_import_state_store_' . $import_id);

                update_option('aieo_last_upsell_import', array(
                    'processed' => $state['processed'],
                    'impacted' => $state['impacted'],
                    'completed_at' => current_time('mysql', true),
                ));

                wp_send_json_success(array(
                    'complete' => true,
                    
                    'message' => sprintf(__('✓ Upsell import completed: %d records processed.', 'ai-eshop-optimizer'), $state['processed']),
                    
                    'summary' => sprintf(__('Total products updated: %d', 'ai-eshop-optimizer'), $state['impacted']),
                    'current' => $state['processed'],
                    'total' => $state['total'],
                ));
                return;
            }

            $start_time = microtime(true);
            $impacted = 0;

            foreach ($rows as $row) {
                $product_id = intval($row['original_product_id']);
                $upsells = array_filter(array_map('intval', array_map('trim', explode(',', $row['related_upsells_list']))));
                $crossells = array_filter(array_map('intval', array_map('trim', explode(',', $row['related_crossells_list']))));
                $params = $row['aieo_neo4j_params'];

                $impacted += $this->assign_upsells_cross_sells($product_id, $upsells, $crossells, $params);
            }

            $elapsed = microtime(true) - $start_time;
            if (!empty($state['monitor'])) {
                $performance_table = $wpdb->prefix . 'aieo_performance_tuning';
                $wpdb->insert(
                    $performance_table,
                    array(
                        'batch_size' => count($rows),
                        'processing_time' => $elapsed,
                        'total_processing_time' => ($state['processed'] + count($rows)) > 0 ? ($elapsed * ($state['total'] / max(1, count($rows)))) : 0,
                    ),
                    array('%d', '%f', '%f')
                );
            }

            $state['processed'] += count($rows);
            $state['impacted'] += $impacted;
            $last_row = end($rows);
            $state['last_id'] = $last_row ? (int) $last_row['original_product_id'] : $state['last_id'];

            set_transient($state_key, $state, 2 * HOUR_IN_SECONDS);

            if ($batch_sleep > 0) {
                usleep($batch_sleep * 1000000);
            }

            $percent = $state['total'] > 0 ? round(($state['processed'] / $state['total']) * 100) : 100;

            wp_send_json_success(array(
                'complete' => false,
                'message' => sprintf(
                    
                    __('Processed %1$d of %2$d records (%3$s%% complete).', 'ai-eshop-optimizer'),
                    $state['processed'],
                    $state['total'],
                    $percent
                ),
                'current' => $state['processed'],
                'total' => $state['total'],
                'progress' => $percent,
            ));
        }

        
        public function aieo_handle_export_orders()
        {
            if (
                isset($_POST['eshop_optimizer_handle_export_orders_nonce_3']) &&
                wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['eshop_optimizer_handle_export_orders_nonce_3'])), 'eshop_optimizer_handle_export_orders_action')
            ) {

                global $wpdb; 

                
                $original_time_limit = ini_get('max_execution_time');

                
                $product_count = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_type = 'product' AND post_status = 'publish'");

                
                $order_item_count = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}woocommerce_order_items");

                
                $timeout = ($product_count + $order_item_count) / 50;

                
                set_time_limit($timeout);

                
                register_shutdown_function(function () use ($original_time_limit) {
                    set_time_limit($original_time_limit);
                });

                $site_prefix = $wpdb->prefix;

                $orders_table_name = $wpdb->prefix . "aieo_" . gmdate('Y_m') . "_orders";
                $orders_table_name = sanitize_text_field($orders_table_name);

                
                if (!preg_match('/^[a-zA-Z0-9_]+$/', $orders_table_name)) {
                    
                    return false;
                }

                $drop_orders_table_query = $wpdb->prepare("DROP TABLE IF EXISTS {$orders_table_name};");

                

                $order_id = 0;
                if (isset($_POST['export_orders'])) {
                    
                    if (isset($_POST['aieo_order_id']) && !empty($_POST['aieo_order_id'])) {
                        $order_id = absint($_POST['aieo_order_id']);
                        $max_records = isset($_POST['aieo_max_records']) ? absint($_POST['aieo_max_records']) : 0;
                    }
                    
                    if (current_user_can(AIEO_CAPABILITY)) {

                        

                        update_option('aieo_create_orders', (isset($_POST['aieo_create_orders']) && $_POST['aieo_create_orders'] == '1') ? '1' : '0');
                        update_option('aieo_activate_account', (isset($_POST['aieo_activate_account']) && $_POST['aieo_activate_account'] == '1') ? '1' : '0');
                        update_option('aieo_erp_consolidation', (isset($_POST['aieo_erp_consolidation']) && $_POST['aieo_erp_consolidation'] == '1') ? '1' : '0');
                        update_option('aieo_erp_merge_orders', (isset($_POST['aieo_erp_merge_orders']) && $_POST['aieo_erp_merge_orders'] == '1') ? '1' : '0');
                        update_option('aieo_erp_anonymous_consolidation', (isset($_POST['aieo_erp_anonymous_consolidation']) && $_POST['aieo_erp_anonymous_consolidation'] == '1') ? '1' : '0');
                        update_option('aieo_erp_stats_per_channel', (isset($_POST['aieo_erp_stats_per_channel']) && $_POST['aieo_erp_stats_per_channel'] == '1') ? '1' : '0');
                        update_option('aieo_include_eponymous', (isset($_POST['aieo_include_eponymous']) && $_POST['aieo_include_eponymous'] == '1') ? '1' : '0');
                        update_option('aieo_include_reciprocity', (isset($_POST['aieo_include_reciprocity']) && $_POST['aieo_include_reciprocity'] == '1') ? '1' : '0');
                        update_option('aieo_include_seasonality', (isset($_POST['aieo_include_seasonality']) && $_POST['aieo_include_seasonality'] == '1') ? '1' : '0');
                        update_option('aieo_include_restricted_seasonality', (isset($_POST['aieo_include_restricted_seasonality']) && $_POST['aieo_include_restricted_seasonality'] == '1') ? '1' : '0');
                        update_option('aieo_instore_anonymous', (isset($_POST['aieo_instore_anonymous']) && $_POST['aieo_instore_anonymous'] == '1') ? '1' : '0');
                        update_option('aieo_include_price', (isset($_POST['aieo_include_price']) && $_POST['aieo_include_price'] == '1') ? '1' : '0');
                        update_option('aieo_variations_choice', (isset($_POST['aieo_variations_choice']) && $_POST['aieo_variations_choice'] == '1') ? '1' : '0');
                        update_option('aieo_include_aggregate_stats', (isset($_POST['aieo_include_aggregate_stats']) && $_POST['aieo_include_aggregate_stats'] == '1') ? '1' : '0');
                        update_option('aieo_include_aggregate_category_brand_stats', (isset($_POST['aieo_include_aggregate_category_brand_stats']) && $_POST['aieo_include_aggregate_category_brand_stats'] == '1') ? '1' : '0');
                        update_option('aieo_include_aggregate_cust_std_stats', (isset($_POST['aieo_include_aggregate_cust_std_stats']) && $_POST['aieo_include_aggregate_cust_std_stats'] == '1') ? '1' : '0');
                        update_option('aieo_include_aggregate_cust_adv_stats', (isset($_POST['aieo_include_aggregate_cust_adv_stats']) && $_POST['aieo_include_aggregate_cust_adv_stats'] == '1') ? '1' : '0');
                        update_option('aieo_include_text', (isset($_POST['aieo_include_text']) && $_POST['aieo_include_text'] == '1') ? '1' : '0');
                        update_option('aieo_include_attributes', (isset($_POST['aieo_include_attributes']) && $_POST['aieo_include_attributes'] == '1') ? '1' : '0');
                        update_option('aieo_include_full_text', (isset($_POST['aieo_include_full_text']) && $_POST['aieo_include_full_text'] == '1') ? '1' : '0');
                        update_option('aieo_create_attributes', (isset($_POST['aieo_create_attributes']) && $_POST['aieo_create_attributes'] == '1') ? '1' : '0');
                        update_option('aieo_create_needs', (isset($_POST['aieo_create_needs']) && $_POST['aieo_create_needs'] == '1') ? '1' : '0');
                        update_option('aieo_create_need_suggestions', (isset($_POST['aieo_create_need_suggestions']) && $_POST['aieo_create_need_suggestions'] == '1') ? '1' : '0');
                        update_option('aieo_create_catalogue', (isset($_POST['aieo_create_catalogue']) && $_POST['aieo_create_catalogue'] == '1') ? '1' : '0');
                        update_option('aieo_include_unsold', (isset($_POST['aieo_include_unsold']) && $_POST['aieo_include_unsold'] == '1') ? '1' : '0');
                        update_option('aieo_create_uuids', (isset($_POST['aieo_create_uuids']) && $_POST['aieo_create_uuids'] == '1') ? '1' : '0');
                        update_option('aieo_create_export', (isset($_POST['aieo_create_export']) && $_POST['aieo_create_export'] == '1') ? '1' : '0');

                        
                        if (isset($_POST['aieo_order_id'])) {
                            update_option('aieo_order_id', sanitize_text_field(wp_unslash($_POST['aieo_order_id'])));
                        }

                        if (isset($_POST['aieo_max_records'])) {
                            update_option('aieo_max_records', sanitize_text_field(wp_unslash($_POST['aieo_max_records'])));
                        }

                        
                        if (isset($_POST['aieo_core_attribute_vendor'])) {
                            update_option('aieo_core_attribute_vendor', sanitize_text_field(wp_unslash($_POST['aieo_core_attribute_vendor'])));
                        }

                        if (isset($_POST['aieo_core_attribute_brands'])) {
                            update_option('aieo_core_attribute_brands', sanitize_text_field(wp_unslash($_POST['aieo_core_attribute_brands'])));
                        }

                        if (isset($_POST['aieo_core_attribute_size'])) {
                            update_option('aieo_core_attribute_size', sanitize_text_field(wp_unslash($_POST['aieo_core_attribute_size'])));
                        }

                        if (isset($_POST['aieo_core_attribute_color'])) {
                            update_option('aieo_core_attribute_color', sanitize_text_field(wp_unslash($_POST['aieo_core_attribute_color'])));
                        }

                        if (isset($_POST['aieo_core_attribute_need'])) {
                            update_option('aieo_core_attribute_need', sanitize_text_field(wp_unslash($_POST['aieo_core_attribute_need'])));
                        }

                        if (isset($_POST['aieo_season_days_past'])) {
                            update_option('aieo_season_days_past', sanitize_text_field(wp_unslash($_POST['aieo_season_days_past'])));
                        }

                        if (isset($_POST['aieo_season_days_after'])) {
                            update_option('aieo_season_days_after', sanitize_text_field(wp_unslash($_POST['aieo_season_days_after'])));
                        }

                        if (isset($_POST['aieo_erp_store_anonymous_invoice_users'])) {
                            update_option('aieo_erp_store_anonymous_invoice_users', sanitize_text_field(wp_unslash($_POST['aieo_erp_store_anonymous_invoice_users'])));
                        }

                        if (isset($_POST['aieo_erp_series_to_ignore'])) {
                            update_option('aieo_erp_series_to_ignore', sanitize_text_field(wp_unslash($_POST['aieo_erp_series_to_ignore'])));
                        }

                        if (isset($_POST['aieo_erp_products_to_ignore'])) {
                            update_option('aieo_erp_products_to_ignore', sanitize_text_field(wp_unslash($_POST['aieo_erp_products_to_ignore'])));
                        }

                        if (isset($_POST['aieo_erp_product_price_to_ignore'])) {
                            update_option('aieo_erp_product_price_to_ignore', sanitize_text_field(wp_unslash($_POST['aieo_erp_product_price_to_ignore'])));
                        }
                    }

                    

                    $create_orders = isset($_POST['aieo_create_orders']) && $_POST['aieo_create_orders'] === '1';
                    $orders_sql_choice = $create_orders ? 1 : 0;

                    $erp_orders = isset($_POST['aieo_erp_consolidation']) && $_POST['aieo_erp_consolidation'] === '1';
                    $erp_sql_choice = $erp_orders ? 1 : 0;

                    $erp_merge_orders = isset($_POST['aieo_erp_merge_orders']) && $_POST['aieo_erp_merge_orders'] === '1';
                    $erp_merge_orders_sql_choice = $erp_merge_orders ? 1 : 0;

                    $erp_anonymous_orders = isset($_POST['aieo_erp_anonymous_consolidation']) && $_POST['aieo_erp_anonymous_consolidation'] === '1';
                    $erp_anonymous_sql_choice = $erp_anonymous_orders ? 1 : 0;

                    $erp_stats_per_channel = isset($_POST['aieo_erp_stats_per_channel']) && $_POST['aieo_erp_stats_per_channel'] === '1';
                    $erp_stats_per_channel_sql_choice = $erp_stats_per_channel ? 1 : 0;

                    $include_text = isset($_POST['aieo_include_text']) && $_POST['aieo_include_text'] === '1';
                    $text_sql_choice = $include_text ? 1 : 0;

                    $include_attributes = isset($_POST['aieo_include_attributes']) && $_POST['aieo_include_attributes'] === '1';
                    $attributes_sql_choice = $include_attributes ? 1 : 0;

                    $include_full_text = isset($_POST['aieo_include_full_text']) && $_POST['aieo_include_full_text'] === '1';
                    $full_text_sql_choice = $include_full_text ? 1 : 0;

                    $include_price = isset($_POST['aieo_include_price']) && $_POST['aieo_include_price'] === '1';
                    $price_sql_choice = $include_price ? 1 : 0;

                    $season_days_past = sanitize_text_field(wp_unslash($_POST['aieo_season_days_past']));
                    $season_days_after = sanitize_text_field(wp_unslash($_POST['aieo_season_days_after']));

                    $variations_choice = isset($_POST['aieo_variations_choice']) && $_POST['aieo_variations_choice'] === '1';
                    $variations_sql_choice = $variations_choice ? 1 : 0;

                    $include_aggregate_stats = isset($_POST['aieo_include_aggregate_stats']) && $_POST['aieo_include_aggregate_stats'] === '1';
                    $aggregate_stats_sql_choice = $include_aggregate_stats ? 1 : 0;

                    $create_attributes = isset($_POST['aieo_create_attributes']) && $_POST['aieo_create_attributes'] === '1';
                    $attributes_sql_choice = $create_attributes ? 1 : 0;

                    $create_needs = isset($_POST['aieo_create_needs']) && $_POST['aieo_create_needs'] === '1';
                    $needs_sql_choice = $create_needs ? 1 : 0;

                    $create_catalogue = isset($_POST['aieo_create_catalogue']) && $_POST['aieo_create_catalogue'] === '1';
                    $catalogue_sql_choice = $create_catalogue ? 1 : 0;

                    $create_uuids = isset($_POST['aieo_create_uuids']) && $_POST['aieo_create_uuids'] === '1';
                    $uuids_sql_choice = $create_uuids ? 1 : 0;

                    $create_export = isset($_POST['aieo_create_export']) && $_POST['aieo_create_export'] === '1';
                    $export_sql_choice = $create_export ? 1 : 0;

                    $include_unsold = isset($_POST['aieo_include_unsold']) && $_POST['aieo_include_unsold'] === '1';
                    $unsold_sql_choice = $include_unsold ? 1 : 0;

                    $include_seasonality = isset($_POST['aieo_include_seasonality']) && $_POST['aieo_include_seasonality'] === '1';
                    $include_restricted_seasonality = isset($_POST['aieo_include_restricted_seasonality']) && $_POST['aieo_include_restricted_seasonality'] === '1';

                    if ($include_seasonality && $include_restricted_seasonality) {
                        $seasonality_sql_choice = 2;
                    } elseif ($include_seasonality) {
                        $seasonality_sql_choice = 1;
                    } elseif ($include_restricted_seasonality) {
                        $seasonality_sql_choice = 0;
                    } else {
                        $seasonality_sql_choice = 0;
                    }

                    $include_instore_anonymous = isset($_POST['aieo_instore_anonymous']) && $_POST['aieo_instore_anonymous'] === '1';
                    $instore_anonymous_sql_choice = $include_instore_anonymous ? 1 : 0;

                    $instore_anonymous_list =  get_option('aieo_erp_store_anonymous_invoice_users');
                    $instore_anonymous_list = sanitize_text_field($instore_anonymous_list);

                    $instore_invoices_list =  get_option('aieo_erp_series_to_ignore');
                    $instore_invoices_list = sanitize_text_field($instore_invoices_list);

                    $instore_products_list =  get_option('aieo_erp_products_to_ignore');
                    $instore_products_list = sanitize_text_field($instore_products_list);

                    $instore_product_threshold =  get_option('aieo_erp_product_price_to_ignore');
                    $instore_product_threshold = sanitize_text_field($instore_product_threshold);

                    $instore_product_threshold_sql_choice = !empty($instore_product_threshold) ? 1 : 0;

                    $instore_invoices_list_sql_choice = !empty($instore_invoices_list) ? 1 : 0;

                    $include_reciprocicty = isset($_POST['aieo_include_reciprocity']) && $_POST['aieo_include_reciprocity'] === '1';
                    $reciprocity_sql_choice = $include_reciprocicty ? 1 : 0;

                    $include_eponymous = isset($_POST['aieo_include_eponymous']) && $_POST['aieo_include_eponymous'] === '1';
                    $eponymous_sql_choice = $include_eponymous ? 1 : 0;

                    
                    $temp_orders_table_name = get_option('aieo_site_orders_table');
                    $temp_orders_table_name = sanitize_text_field($temp_orders_table_name);

                    
                    if (!preg_match('/^[a-zA-Z0-9_]+$/', $temp_orders_table_name)) {
                        
                        return false;
                    }
                    $temp_products_table_name = get_option('aieo_site_products_table');

                    $eponymousStatus = ($eponymous_sql_choice == '1') ? ', and user ids provided' : '';
                    $seasonalityStatus = ($seasonality_sql_choice !== '0') ? ', and seasonality active' : '';

                    $script_version = 'Progress Report: ';

                    if ((isset($_POST['aieo_create_attributes']) && $_POST['aieo_create_attributes'] == '1') || get_option('aieo_create_attributes', '1') == '1') {

                        $vendor_attribute = get_option('aieo_core_attribute_vendor');
                        $brand_attribute = get_option('aieo_core_attribute_brands');
                        $size_attributes = get_option('aieo_core_attribute_size');
                        $color_attributes = get_option('aieo_core_attribute_color');

                        
                        $aieo_clean_attributes = function ($attributes) {
                            return implode(", ", array_map(function ($attr) {
                                return "'" . trim($attr) . "'";
                            }, explode(",", $attributes)));
                        };

                        
                        $cleaned_size_attributes = $aieo_clean_attributes($size_attributes);
                        $cleaned_color_attributes = $aieo_clean_attributes($color_attributes);

                        $wpdb->query($wpdb->prepare(
                            "CALL `{$site_prefix}AIEO_InsertCoreProductAttributes` (%s, %s, %s, %s)",
                            $vendor_attribute,
                            $brand_attribute,
                            $cleaned_size_attributes,
                            $cleaned_color_attributes
                        ));

                        $wpdb->query($wpdb->prepare(
                            "CALL `{$site_prefix}AIEO_InsertProductCategoryHierarchy` ();"
                        ));

                        
                        delete_option('aieo_chat_cached_categories');

                        $wpdb->query($wpdb->prepare(
                            "CALL `{$site_prefix}AIEO_InsertProductVitals` ();"
                        ));

                        $wpdb->query($wpdb->prepare(
                            "CALL `{$site_prefix}AIEO_InsertVariationVitals` ();"
                        ));

                        $wpdb->query($wpdb->prepare(
                            "CALL `{$site_prefix}AIEO_CombineVariationVitalsInProductVitals` ();"
                        ));

                        
                        
                        
                        
                        
                        
                        
                        if (!class_exists('AI_eShop_Product_Needs')) {
                            require_once plugin_dir_path(__FILE__) . 'class-product-needs.php';
                        }
                        AI_eShop_Product_Needs::get_instance()->populate_product_needs();

                        
                        
                        delete_transient('aieo_chat_sellable_breakdown');
                        delete_transient('aieo_chat_count_sellable_units_0');
                        delete_transient('aieo_chat_count_sellable_units_1');

                        $script_version = $script_version . 'Created the product vital attributes and product category hierarchy. ';
                    }

                    
                    
                    
                    if ((isset($_POST['aieo_create_needs']) && $_POST['aieo_create_needs'] == '1') || get_option('aieo_create_needs', '1') == '1') {
                        
                        require_once plugin_dir_path(__FILE__) . 'class-product-needs.php';
                        $needs_handler = AI_eShop_Product_Needs::get_instance();

                        
                        if ($needs_handler->populate_product_needs()) {
                            $script_version = $script_version . 'Successfully populated product needs data. ';
                        } else {
                            $script_version = $script_version . 'Warning: Failed to populate product needs data. ';
                        }
                    }

                    if ((isset($_POST['aieo_create_catalogue']) && $_POST['aieo_create_catalogue'] == '1') || get_option('aieo_create_catalogue', '1') == '1') {
                        $wpdb->query($wpdb->prepare(
                            "CALL `{$site_prefix}AIEO_Create_Product_Catalogue_HPOS` (%d, %d, %d)",
                            $price_sql_choice,
                            $text_sql_choice,
                            $full_text_sql_choice
                        ));
                        $script_version = $script_version . 'A fresh product catalogue has been created. ';
                    }

                    if ((isset($_POST['aieo_create_orders']) && $_POST['aieo_create_orders'] == '1') || get_option('aieo_create_orders', '1') == '1') {

                        if (class_exists('Automattic\WooCommerce\Utilities\OrderUtil') && function_exists('WC')) {
                            
                            if (Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled()) {
                                

                                

                                $script_version = 'HPOS via SP for ' . $max_records . ' records starting at Order_Id ' . $order_id . $eponymousStatus . $seasonalityStatus;

                                $wpdb->query($wpdb->prepare(
                                    "CALL `{$site_prefix}AIEO_Export_Orders_HPOS` (%d, %d, %d, %d, %d, %d, %d)",
                                    $price_sql_choice,
                                    $text_sql_choice,
                                    $full_text_sql_choice,
                                    $eponymous_sql_choice,
                                    $seasonality_sql_choice,
                                    $order_id,
                                    $max_records
                                ));
                            }
                            
                            else {
                                $script_version = $script_version . 'Non-HPOS via SP for ' . $max_records . ' records starting at Order_Id ' . $order_id . $eponymousStatus . $seasonalityStatus;

                                $wpdb->query($wpdb->prepare(
                                    "CALL `{$site_prefix}AIEO_Export_Orders_non_HPOS` (%d, %d, %d, %d, %d, %d, %d)",
                                    $price_sql_choice,
                                    $text_sql_choice,
                                    $full_text_sql_choice,
                                    $eponymous_sql_choice,
                                    $seasonality_sql_choice,
                                    $order_id,
                                    $max_records
                                ));
                            }
                        }
                    } else {
                        $script_version = $script_version . 'The eshop orders were not processed this time!';
                    }

                    if ((isset($_POST['aieo_erp_consolidation']) && $_POST['aieo_erp_consolidation'] == '1') || get_option('aieo_erp_consolidation', '1') == '1') {

                        $include_instore_anonymous = isset($_POST['aieo_instore_anonymous']) && $_POST['aieo_instore_anonymous'] === '1';
                        $instore_anonymous_sql_choice = $include_instore_anonymous ? 1 : 0;

                        $instore_anonymous_list =  get_option('aieo_erp_store_anonymous_invoice_users');
                        $instore_anonymous_list = sanitize_text_field($instore_anonymous_list);

                        $instore_invoices_list =  get_option('aieo_erp_series_to_ignore');
                        $instore_invoices_list = sanitize_text_field($instore_invoices_list);

                        $instore_product_threshold =  get_option('aieo_erp_product_price_to_ignore');
                        $instore_product_threshold = sanitize_text_field($instore_product_threshold);
                        
                        $instore_invoices_list_sql_choice = !empty($instore_invoices_list) ? 1 : 0;

                        
                        $aieo_clean_list_values = function ($list_values) {
                            return implode(", ", array_map(function ($attr) {
                                return "'" . trim($attr) . "'";
                            }, explode(",", $list_values)));
                        };

                        
                        $cleaned_instore_invoices_list = $aieo_clean_list_values($instore_invoices_list);
                        $cleaned_instore_anonymous_list = $aieo_clean_list_values($instore_anonymous_list);

                            
                        $wpdb->query($wpdb->prepare(
                            "CALL `{$site_prefix}AIEO_Export_Store_Orders` (%d, %d, %d, %d, %d, %d, %s, %d, %s)",
                            $price_sql_choice,
                            $eponymous_sql_choice,
                            $seasonality_sql_choice,
                            $season_days_past,
                            $season_days_after,
                            $instore_invoices_list_sql_choice,
                            $instore_invoices_list,
                            $instore_anonymous_sql_choice,
                            $instore_anonymous_list
                        ));
                        
                        $script_version = $script_version . 'Integrated the in-store orders. ';
                    }

                    if ((isset($_POST['aieo_erp_merge_orders']) && $_POST['aieo_erp_merge_orders'] == '1') || get_option('aieo_erp_merge_orders', '1') == '1') {

                         $store_orders_table_name = get_option('aieo_store_orders_table');
                         $store_orders_table_name =  sanitize_text_field($store_orders_table_name);
                        
                         $analytics_eponymous_id_field = get_option('aieo_analytics_eponymous_id_field');
                         $analytics_eponymous_id_field  = sanitize_text_field($analytics_eponymous_id_field); 
                         
                         $instore_product_threshold =  get_option('aieo_erp_product_price_to_ignore');
                         $instore_product_threshold = sanitize_text_field($instore_product_threshold);
     
                         $instore_product_threshold_sql_choice = !empty($instore_product_threshold) ? 1 : 0;

                         
                        $instore_products_list =  get_option('aieo_erp_products_to_ignore');
                        $instore_products_list = sanitize_text_field($instore_products_list);

                        $instore_products_list_sql_choice = !empty($instore_products_list) ? 1 : 0;
                      

                        
                        $wpdb->query($wpdb->prepare(
                            "CALL `{$site_prefix}AIEO_Merge_Store_Orders` (%s, %s, %s, %d, %s, %d, %s)",
                            $store_orders_table_name,
                            $temp_orders_table_name,
                            $analytics_eponymous_id_field,
                            $instore_product_threshold_sql_choice,
                            $instore_product_threshold,
                            $instore_products_list_sql_choice,
                            $instore_products_list
                        ));
                        
                        $script_version = $script_version . 'Integrated the in-store orders. ';
                    }

                    if ((isset($_POST['aieo_include_unsold']) && $_POST['aieo_include_unsold'] == '1') || get_option('aieo_include_unsold', '1') == '1') {

                        
                        if (preg_match('/^[a-zA-Z0-9_]+$/', $site_prefix)) {
                            
                            $wpdb->query("SET @output_message = ''");

                            
                            
                            $wpdb->query($wpdb->prepare("CALL `{$site_prefix}AIEO_UpdateOrdersWithUnsold`(@output_message)"));

                            
                            $output_message_from_sp = $wpdb->get_var("SELECT @output_message AS output_message");
                        } else {
                            
                        }

                        
                        if (strpos($output_message_from_sp, 'Warning') !== false) {
                            $message = 'The operation did not complete! Regenerate the necessary tables! ' . $output_message_from_sp;

                            
                            update_option('aieo_export_orders_message', $message, false);

                            
                            $redirect_url = add_query_arg(
                                array(
                                    'page' => 'ai-eshop-optimizer',
                                    'exported_orders' => '1',
                                    '_wpnonce' => wp_create_nonce('exported_orders_action')
                                ),
                                admin_url('admin.php')
                            );

                            wp_safe_redirect($redirect_url);
                            exit;
                        } else {
                            $script_version = $script_version . $output_message_from_sp;
                        }
                    }

                    

                    if ((isset($_POST['aieo_include_aggregate_stats']) && $_POST['aieo_include_aggregate_stats'] == '1') || get_option('aieo_include_aggregate_stats', '0') == '1') {
                        $result = $wpdb->query($wpdb->prepare("CALL `{$site_prefix}AIEO_UpdateProductCentricStats` ('wp_aieo_temp_orders', 0);"));
                        $script_version = $script_version . ', and the Product stats';
                    }
                    if ((isset($_POST['aieo_include_aggregate_cust_std_stats']) && $_POST['aieo_include_aggregate_cust_std_stats'] == '1') || get_option('aieo_include_aggregate_cust_std_stats', '0') == '1') {
                        $result = $wpdb->query($wpdb->prepare("CALL `{$site_prefix}AIEO_UpdateCustomerCentricStdStats` ('$temp_orders_table_name', 0);"));
                        $script_version = $script_version . ', and the Customer Standard Statistics were computed';
                    }
                    if ((isset($_POST['aieo_include_aggregate_cust_adv_stats']) && $_POST['aieo_include_aggregate_cust_adv_stats'] == '1') || get_option('aieo_include_aggregate_cust_adv_stats', '0') == '1') {
                        
                        @set_time_limit(300);
                        $result = $wpdb->query($wpdb->prepare("CALL `{$site_prefix}AIEO_UpdateCustomerCentricAdvStats` ('$temp_orders_table_name', 0);"));
                        $script_version = $script_version . ', and the Customer Adv Statistics were computed';
                    }

                    
                    if ((isset($_POST['aieo_create_uuids']) && $_POST['aieo_create_uuids'] == '1') || get_option('aieo_create_uuids', '0') == '1') {
                        $result = $wpdb->query($wpdb->prepare("CALL `{$site_prefix}AIEO_GenerateGraphDBUUIDFreqs` ('$temp_orders_table_name');"));
                        $script_version = $script_version . ', and generated the UUIDs';
                    }

                    
                    if ((isset($_POST['create_need_suggestions']) && $_POST['create_need_suggestions'] == '1') || get_option('aieo_create_need_suggestions', '0') == '1') {
                        require_once plugin_dir_path(__FILE__) . 'class-need-suggestions.php';
                        $need_suggestions = AI_eShop_Need_Suggestions::get_instance();
                        $suggestions_result = $need_suggestions->generate_all_suggestions();

                        if ($suggestions_result['processed'] > 0) {
                            $script_version = $script_version . sprintf(
                                ', and generated need suggestions for %d products (%d suggestions)',
                                $suggestions_result['processed'],
                                $suggestions_result['suggestions_created']
                            );
                        }
                    }

                    
                }

                
                
                if ((isset($_POST['aieo_include_full_text']) && $_POST['aieo_include_full_text'] == '1') || get_option('aieo_include_full_text', '0') == '1') {

                    $wpdb->query($wpdb->prepare(
                        "CALL `{$site_prefix}AIEO_FindDifferences` (%s)",
                        $temp_orders_table_name
                    ));

                    $script_version = $script_version . ', and found text diffrences';
                    
                    $wpdb->query(
                        $wpdb->prepare(
                            "CALL `{$site_prefix}AIEO_UpdateContentOutgoingLinks` (%s)",
                            $temp_orders_table_name
                        )
                    );

                    $script_version = $script_version . ', and counted the links in the text';
                    
                    $wpdb->query(
                        $wpdb->prepare(
                            "CALL `{$site_prefix}AIEO_UpdateContentIntroPlain` (%s)",
                            $temp_orders_table_name
                        )
                    );

                    $script_version = $script_version . ', and created the plain text descriptions';
                    
                    $wpdb->query(
                        $wpdb->prepare(
                            "CALL `{$site_prefix}AIEO_UpdateContentWordCount` (%s)",
                            $temp_orders_table_name
                        )
                    );

                    $script_version = $script_version . ', and having counted the words in the description';
                    
                }

                if ((isset($_POST['aieo_create_export']) && $_POST['aieo_create_export'] == '1') || get_option('aieo_create_export', '0') == '1') {
                    global $wpdb;
                    require_once(ABSPATH . 'wp-admin/includes/file.php');

                    
                    WP_Filesystem();
                    global $wp_filesystem;

                    
                    

                    
                    $wpdb->query(
                        $wpdb->prepare(
                            "CALL `{$site_prefix}AIEO_RenameTable` (%s, %s);",
                            $temp_orders_table_name,
                            $orders_table_name
                        )
                    );
                    aieo_create_temp_orders_table($temp_orders_table_name);

                    
                    $table_columns = $wpdb->get_results("SHOW COLUMNS FROM {$orders_table_name}");
                    $export_columns = array_map(function ($column) {
                        return $column->Field;
                    }, $table_columns);

                    
                    
                    $uuid_columns = array(
                        'OrderIdGraphUUID', 'OrderItemIdGraphUUID', 'PPIdGraphUUID', 'ProdIdGraphUUID',
                        'EpoIdGraphUUID', 'O_PP_GraphUUID', 'O_Prod_GraphUUID', 'O_Epo_GraphUUID',
                        'PP_Epo_GraphUUID', 'Prod_Epo_GraphUUID'
                    );

                    $select_columns = array();
                    foreach ($export_columns as $col) {
                        if (in_array($col, $uuid_columns)) {
                            
                            $select_columns[] = "BIN_TO_UUID({$col}) AS {$col}";
                        } else {
                            $select_columns[] = $col;
                        }
                    }

                    
                    $results = $wpdb->get_results("SELECT " . implode(', ', $select_columns) . " FROM {$orders_table_name}", ARRAY_A);

                    $file_extension = 'csv';
                    $uploads_dir = wp_upload_dir();
                    $parsed_url = wp_parse_url(home_url());
                    $domain = $parsed_url['host'];
                    $file_path = $uploads_dir['basedir'] . '/' . $domain . '_exported_orders_hpos.csv';
                    $file_path = $this->aieo_normalize_path($file_path);

                    
                    $csv_content = '';
                    $csv_content .= implode(',', $export_columns) . "\r\n";
                    foreach ($results as $result) {
                        $row_data = [];
                        foreach ($export_columns as $col_name) {
                            $row_data[] = $result[$col_name] ?? '';
                        }
                        $csv_content .= implode(',', $row_data) . "\r\n";
                    }

                    
                    $wp_filesystem->put_contents($file_path, $csv_content, FS_CHMOD_FILE);

                    
                    $message = $script_version . ': The orders table/file have been created and are ready for transfer/upload!';
                    update_option('aieo_export_orders_message', $message, false);

                    $redirect_url = add_query_arg(
                        array(
                            'page' => 'ai-eshop-optimizer',
                            'exported_orders' => '1',
                            '_wpnonce' => wp_create_nonce('exported_orders_action')
                        ),
                        admin_url('admin.php')
                    );
                    wp_safe_redirect($redirect_url);
                    exit;
                } else {
                    $message = $script_version . ': The orders have been created but you have to confirm that you need to create the export file!';
                    
                    update_option('aieo_export_orders_message', $message, false);
                    
                    $redirect_url = add_query_arg(
                        array(
                            'page' => 'ai-eshop-optimizer',
                            'exported_orders' => '1',
                            '_wpnonce' => wp_create_nonce('exported_orders_action')
                        ),
                        admin_url('admin.php')
                    );

                    wp_safe_redirect($redirect_url);
                    exit;
                }
            } else {
                
                
                wp_die(esc_html__('Security check 2 failed.', 'ai-eshop-optimizer'));
            }
        }

        
        private function aieo_create_csv_from_orders_table($orders_table_name, $file_path)
        {
            global $wpdb;

            aieo_debug_log('AIEO: Starting CSV creation from table: ' . $orders_table_name);

            try {
                
                if (!function_exists('WP_Filesystem')) {
                    require_once(ABSPATH . 'wp-admin/includes/file.php');
                }
                WP_Filesystem();
                global $wp_filesystem;

                if (!$wp_filesystem) {
                    aieo_debug_log('AIEO: WARNING - WP_Filesystem not initialized; falling back to direct file write.');
                }

                
                $columns_result = $wpdb->get_results("SHOW COLUMNS FROM {$orders_table_name}", ARRAY_A);

                if (!$columns_result) {
                    aieo_debug_log('AIEO: ERROR - Could not get table structure for: ' . $orders_table_name);
                    return false;
                }

                $export_columns = array();
                $uuid_columns = array();
                $select_columns = array();

                foreach ($columns_result as $column) {
                    $col_name = $column['Field'];
                    $col_type = $column['Type'];

                    $export_columns[] = $col_name;

                    
                    if (stripos($col_type, 'binary(16)') !== false || stripos($col_name, 'UUID') !== false) {
                        $uuid_columns[] = $col_name;
                        
                        
                        $select_columns[] = "CONCAT(SUBSTR(HEX({$col_name}), 1, 8), '-', SUBSTR(HEX({$col_name}), 9, 4), '-', SUBSTR(HEX({$col_name}), 13, 4), '-', SUBSTR(HEX({$col_name}), 17, 4), '-', SUBSTR(HEX({$col_name}), 21)) AS {$col_name}";
                    } else {
                        $select_columns[] = $col_name;
                    }
                }

                aieo_debug_log('AIEO: Found ' . count($export_columns) . ' columns in table, ' . count($uuid_columns) . ' UUID columns');

                $select_query = "SELECT " . implode(', ', $select_columns) . " FROM {$orders_table_name}";
                aieo_debug_log('AIEO: Executing query to fetch data from table');

                $file_path = $this->aieo_normalize_path($file_path);

                aieo_debug_log('AIEO: Target file path: ' . $file_path);

                
                if (!function_exists('wp_mkdir_p')) {
                    require_once ABSPATH . 'wp-admin/includes/file.php';
                }
                if (!wp_mkdir_p(dirname($file_path))) {
                    aieo_debug_log('AIEO: ERROR - Failed to create directory for CSV: ' . dirname($file_path));
                    return false;
                }

                
                
                $handle = @fopen($file_path, 'w');
                if (!$handle) {
                    aieo_debug_log('AIEO: ERROR - Unable to open file handle for CSV: ' . $file_path);
                    return false;
                }

                
                fputcsv($handle, $export_columns);

                $batch_size = 1000;
                $offset = 0;
                $total_written = 0;

                while (true) {
                    
                    
                    $rows = $wpdb->get_results(
                        $select_query . $wpdb->prepare(" LIMIT %d OFFSET %d", $batch_size, $offset),
                        ARRAY_A
                    );
                    

                    if ($wpdb->last_error) {
                        aieo_debug_log('AIEO: ERROR - Database query failed: ' . $wpdb->last_error);
                        
                        fclose($handle);
                        wp_delete_file($file_path);
                        return false;
                    }

                    if (empty($rows)) {
                        break;
                    }

                    foreach ($rows as $row) {
                        $line = array();
                        foreach ($export_columns as $col_name) {
                            $line[] = $row[$col_name] ?? '';
                        }
                        fputcsv($handle, $line);
                    }

                    $total_written += count($rows);
                    $offset += $batch_size;
                }

                
                fclose($handle);
                aieo_debug_log('AIEO: CSV file created successfully at: ' . $file_path . ' with ' . $total_written . ' rows');
                return $file_path;

            } catch (Exception $e) {
                aieo_debug_log('AIEO: EXCEPTION in CSV creation: ' . $e->getMessage());
                return false;
            }
        }

        public function aieo_delete_exported_file()
        {
            
            if (!current_user_can(AIEO_CAPABILITY)) {
                wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'ai-eshop-optimizer'));
            }

            
            if (!isset($_GET['_wpnonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['_wpnonce'])), 'delete_exported_file')) {
                wp_die(esc_html__('Security check failed.', 'ai-eshop-optimizer'));
            }

            $csv_info = get_option('aieo_last_export_csv', array());
            $file_path = isset($csv_info['path']) ? $this->aieo_normalize_path($csv_info['path']) : '';

            if ($file_path && file_exists($file_path)) {
                wp_delete_file($file_path);
                delete_option('aieo_last_export_csv');

                
                update_option('aieo_file_deletion_message', __('Export file has been successfully deleted from your server.', 'ai-eshop-optimizer'));
            } else {
                
                update_option('aieo_file_deletion_message', 'Error: ' . __('Export file not found.', 'ai-eshop-optimizer'));
            }

            
            wp_safe_redirect(admin_url('admin.php?page=ai-eshop-optimizer'));
            exit;
        }

        public function aieo_handle_recommendations_upload()
        {
            
            if (
                isset($_POST['eshop_optimizer_process_params_nonce_6']) &&
                wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['eshop_optimizer_process_params_nonce_6'])), 'eshop_optimizer_handle_upload_action')
            ) {
                

                global $wpdb; 
                $monitor_performance = isset($_POST['aieo_monitor_performance']) && $_POST['aieo_monitor_performance'] === '1';

                
                if (current_user_can(AIEO_CAPABILITY)) {
                    
                    update_option('aieo_monitor_performance', (isset($_POST['aieo_monitor_performance']) && $_POST['aieo_monitor_performance'] == '1') ? '1' : '0');
                    update_option('aieo_batch_size', (isset($_POST['aieo_batch_size']) && $_POST['aieo_batch_size'] == '1') ? '1' : '0');
                    update_option('aieo_batch_sleep', (isset($_POST['aieo_batch_sleep']) && $_POST['aieo_batch_sleep'] == '1') ? '1' : '0');

                    
                    if (isset($_POST['aieo_monitor_performance'])) {
                        update_option('aieo_monitor_performance', sanitize_text_field(wp_unslash($_POST['aieo_monitor_performance'])));
                    }

                    if (isset($_POST['aieo_batch_size'])) {
                        update_option('aieo_batch_size', sanitize_text_field(wp_unslash($_POST['aieo_batch_size'])));
                    }

                    if (isset($_POST['aieo_batch_sleep'])) {
                        update_option('aieo_batch_sleep', sanitize_text_field(wp_unslash($_POST['aieo_batch_sleep'])));
                    }
                }

                $new_recommendations_table_name = $wpdb->prefix . "aieo_" . gmdate('Y_m') . "_new_recommendations";
                $wpdb->query("DROP TABLE IF EXISTS `{$new_recommendations_table_name}`");

                
                $wpdb->query("CREATE TABLE `{$new_recommendations_table_name}` (
                    original_product_id INT NOT NULL,
                    related_upsells_list TEXT,
                    related_crossells_list TEXT,
                    aieo_neo4j_params TEXT,
                    PRIMARY KEY (original_product_id)
                )");

                if (isset($_FILES['csv_file'])) {
                    
                    $uploaded_file = $_FILES['csv_file'];
                    if (!function_exists('wp_handle_upload')) {
                        require_once ABSPATH . 'wp-admin/includes/file.php';
                    }
                    $uploaded_file['name'] = sanitize_file_name($uploaded_file['name']);
                    $movefile = wp_handle_upload($uploaded_file, array('test_form' => false));

                    if ($movefile && !isset($movefile['error'])) {
                        $csv_data = array_map('str_getcsv', file($movefile['file']));
                        array_shift($csv_data); 

                        if (!empty($csv_data)) {
                            foreach ($csv_data as $row) {
                                
                                $exists = $wpdb->get_var($wpdb->prepare(
                                    "SELECT COUNT(*) FROM `{$new_recommendations_table_name}` WHERE `original_product_id` = %d",
                                    intval($row[0])
                                ));

                                if ($exists == 0) {
                                    
                                    $wpdb->insert(
                                        $new_recommendations_table_name,
                                        array(
                                            'original_product_id' => intval($row[0]),
                                            'related_upsells_list' => sanitize_text_field($row[1]),
                                            'related_crossells_list' => sanitize_text_field($row[2]),
                                            'aieo_neo4j_params' => sanitize_text_field($row[3])
                                        ),
                                        array('%d', '%s', '%s', '%s') 
                                    );
                                }
                            }
                        }

                        $total_products_impacted = $this->assign_upsells_cross_sells_from_db($new_recommendations_table_name);

                        
                        set_transient('aieo_products_updated_count', $total_products_impacted, 60); 

                        
                        $redirect_url = admin_url('admin.php?page=ai-eshop-optimizer');
                    } else {
                        
                        $redirect_url = add_query_arg('upsell_cross_sell_error', 1, admin_url('admin.php?page=ai-eshop-optimizer'));
                    }
                } else {
                    
                    wp_die(esc_html__('Security check 3 failed.', 'ai-eshop-optimizer'));
                }

                wp_safe_redirect(esc_url_raw($redirect_url));
                exit;
            } else {
                
            }
        }

        public function assign_upsells_cross_sells_from_db($new_recommendations_table_name)
        {
            global $wpdb;

            
            $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}aieo_performance_tuning");

            $wpdb->query("CREATE TABLE {$wpdb->prefix}aieo_performance_tuning (
                        id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
                        batch_size INT(11) UNSIGNED NOT NULL,
                        processing_time FLOAT NOT NULL,
                        total_processing_time FLOAT NOT NULL,
                        date_recorded TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                        PRIMARY KEY (id)
                    )");

            $offset = 0;
            $batch_size = get_option('aieo_batch_size', 300);
            $batch_sleep = get_option('aieo_batch_sleep', 0);

            $products_impacted_count = 0;
            $batch_times = [];

            while (true) {
                $products_data = $wpdb->get_results(
                    $wpdb->prepare(
                        "SELECT * FROM `{$new_recommendations_table_name}` WHERE (related_upsells_list <> '' OR related_crossells_list <> '') LIMIT %d OFFSET %d",
                        $batch_size,
                        $offset
                    ),
                    ARRAY_A
                );

                if (empty($products_data)) {
                    break;
                }

                $start_time = microtime(true);

                foreach ($products_data as $data) {
                    $original_product_id = intval($data['original_product_id']);
                    $related_upsells_list = array_filter(explode(',', $data['related_upsells_list']));
                    $related_crossells_list = array_filter(explode(',', $data['related_crossells_list']));
                    $aieo_neo4j_params = $data['aieo_neo4j_params'];
                    $this->assign_upsells_cross_sells($original_product_id, $related_upsells_list, $related_crossells_list, $aieo_neo4j_params);
                }

                $end_time = microtime(true);
                $time_taken = $end_time - $start_time;
                $batch_times[] = $time_taken;

                if (count($batch_times) == 4) {
                    $avg_first_two = ($batch_times[0] + $batch_times[1]) / 2;
                    $avg_last_two = ($batch_times[2] + $batch_times[3]) / 2;

                    if ($avg_last_two > 2 * $avg_first_two) {
                        $batch_size = intdiv($batch_size, 2);  
                    }

                    $batch_times = [];
                }

                $products_impacted_count += count($products_data);
                $offset += $batch_size;
                sleep($batch_sleep);
            }

            return $products_impacted_count;
        }

        public function assign_upsells_cross_sells($original_product_id, $related_upsells_list, $related_crossells_list, $aieo_neo4j_params)
        {
            global $wpdb;

            $parsed_url = wp_parse_url(home_url());
            $domain = str_replace(['.', '-'], '', $parsed_url['host']);
            $current_user = wp_get_current_user();

            $tablesuffix =   esc_html($current_user->user_login) . '_' . esc_html($current_user->ID) . '_' . esc_html($domain);

            $start_time = microtime(true);

            $original_product = wc_get_product($original_product_id);
            if (!$original_product) {
                return 0;
            }

            $upsell_ids = array_slice($related_upsells_list, 0, 10);
            $cross_sell_ids = array_slice($related_crossells_list, 0, 10);

            if (!empty($upsell_ids)) {
                $original_product->set_upsell_ids($upsell_ids);
            }

            if (!empty($cross_sell_ids)) {
                $original_product->set_cross_sell_ids($cross_sell_ids);
            }

            $original_product->save();

            if ($aieo_neo4j_params === '0' || empty($aieo_neo4j_params)) {
                delete_post_meta($original_product_id, 'aieo_neo4j_params');
            } else {
                update_post_meta($original_product_id, 'aieo_neo4j_params', $aieo_neo4j_params);
            }

            
            $end_time = microtime(true);
            $time_taken = $end_time - $start_time;

            $current_total = $wpdb->get_var("SELECT SUM(processing_time) FROM {$wpdb->prefix}aieo_performance_tuning");
            $new_total = $current_total + $time_taken;

            
            $monitor_performance = get_option('aieo_monitor_performance');
            if ($monitor_performance) {
                $wpdb->insert($wpdb->prefix . 'aieo_performance_tuning', [
                    'batch_size' => count($related_upsells_list) + count($related_crossells_list), 
                    'processing_time' => $time_taken,
                    'total_processing_time' => $new_total
                ]);
            }
            return 1;
        }

        public function aieo_handle_eshop_optimizer_account()
        {
            if (
                isset($_POST['eshop_optimizer_account_nonce_7']) &&
                wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['eshop_optimizer_account_nonce_7'])), 'eshop_optimizer_account_action')
            ) {
                $username = isset($_POST['aieo_account_username']) ? sanitize_text_field(wp_unslash($_POST['aieo_account_username'])) : '';
                $password = isset($_POST['aieo_account_password']) ? sanitize_text_field(wp_unslash($_POST['aieo_account_password'])) : '';

                $erp_store_products_table     = isset($_POST['aieo_erp_store_products_table'])      ? sanitize_text_field(wp_unslash($_POST['aieo_erp_store_products_table']))      : '';
                $erp_store_orders_table       = isset($_POST['aieo_erp_store_orders_table'])        ? sanitize_text_field(wp_unslash($_POST['aieo_erp_store_orders_table']))        : '';
                $erp_store_customers_table    = isset($_POST['aieo_erp_store_customers_table'])     ? sanitize_text_field(wp_unslash($_POST['aieo_erp_store_customers_table']))     : '';
                $analytics_eponymous_id_field = isset($_POST['aieo_analytics_eponymous_id_field'])  ? sanitize_text_field(wp_unslash($_POST['aieo_analytics_eponymous_id_field']))  : '';

                $erp_anonymous_invoice_users = isset($_POST['aieo_erp_store_anonymous_invoice_users']) ? sanitize_text_field(wp_unslash($_POST['aieo_erp_store_anonymous_invoice_users'])) : '';
                $erp_series_to_ignore        = isset($_POST['aieo_erp_series_to_ignore'])             ? sanitize_text_field(wp_unslash($_POST['aieo_erp_series_to_ignore']))             : '';
                $erp_products_to_ignore      = isset($_POST['aieo_erp_products_to_ignore'])           ? sanitize_text_field(wp_unslash($_POST['aieo_erp_products_to_ignore']))           : '';
                $erp_product_price_to_ignore = isset($_POST['aieo_erp_product_price_to_ignore'])      ? sanitize_text_field(wp_unslash($_POST['aieo_erp_product_price_to_ignore']))      : '';

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

                update_option('aieo_erp_store_products_table', $erp_store_products_table);
                update_option('aieo_erp_store_orders_table', $erp_store_orders_table);
                update_option('aieo_erp_store_customers_table', $erp_store_customers_table);
                update_option('aieo_analytics_eponymous_id_field', $analytics_eponymous_id_field);

                update_option('aieo_erp_store_anonymous_invoice_users', $erp_anonymous_invoice_users);
                update_option('aieo_erp_series_to_ignore', $erp_series_to_ignore);
                update_option('aieo_erp_products_to_ignore', $erp_products_to_ignore);
                update_option('aieo_erp_product_price_to_ignore', $erp_product_price_to_ignore);
               
                update_option('aieo_google_user_journey_table', $google_user_journey_table);

                update_option('aieo_activate_account', isset($_POST['aieo_activate_account']) ? 1 : 0);
                update_option('aieo_erp_consolidation', isset($_POST['aieo_erp_consolidation']) ? 1 : 0);

                update_option('aieo_erp_anonymous_consolidation', isset($_POST['aieo_erp_anonymous_consolidation']) ? 1 : 0);

                update_option('aieo_erp_stats_per_channel', isset($_POST['aieo_erp_stats_per_channel']) ? 1 : 0);

                
                $remember_auth = isset($_POST['aieo_remember_auth']) ? 1 : 0;
                update_option('aieo_remember_auth', $remember_auth);

                $table = sanitize_text_field(wp_unslash($_POST['aieo_account_table'] ?? ''));
                $result = $this->remote_user_authenticate_and_check_membership($username, $password);
                
                
                
                
                if ($result === 'You have been successfully authenticated as a Pro User' || $result === 'You have been successfully authenticated as a Free User') {
                    
                    update_option('aieo_account_username', $username);

                    
                    $method = 'aes-256-ctr';
                    $key = AUTH_KEY;
                    $iv = substr(AUTH_SALT, 0, 16);
                    $encrypted_password = openssl_encrypt($password, $method, $key, 0, $iv);
                    update_option('aieo_account_password', $encrypted_password);
                }

                
                
                
                
                
                
                
                
                if ($result !== 'Hello Pro' && $result !== 'Thank you for registering') {
                    $rooster_connected = (
                        get_option('aieo_rooster_enabled')
                        && get_option('aieo_rooster_status') === 'connected'
                    );
                    if ($rooster_connected) {
                        update_option('aieo_account_message', sprintf(
                            
                            __('JWT auth could not complete (%s). Your Pro access remains active via the Rooster Content Connector — no further action needed.', 'ai-eshop-optimizer'),
                            $result
                        ));
                    } else {
                        
                        
                        
                        
                        update_option('aieo_account_message', $result . ' — ' . __('Alternatively, link this site via the "Rooster Content Connector" section below to activate Pro features.', 'ai-eshop-optimizer'));
                    }
                    wp_safe_redirect(wp_get_referer());
                    exit;
                }

                
                $method = 'aes-256-ctr';
                $key = AUTH_KEY;
                $iv = substr(AUTH_SALT, 0, 16);
                $encrypted_password = openssl_encrypt($password, $method, $key, 0, $iv);

                
                update_option('aieo_account_username', $username);
                update_option('aieo_account_password', $encrypted_password);
                update_option('aieo_activate_account', isset($_POST['aieo_activate_account']) ? 1 : 0);

                
                if ($result === 'Hello Pro') {
                    update_option('aieo_account_message', __('Successfully connected as a Pro user and settings saved.', 'ai-eshop-optimizer'));

                    
                    if ($remember_auth) {
                        $expiry_time = time() + (30 * DAY_IN_SECONDS); 
                        update_option('aieo_auth_expiry', $expiry_time);
                    } else {
                        
                        delete_option('aieo_auth_expiry');
                    }
                } elseif ($result === 'Thank you for registering') {
                    update_option('aieo_account_message', __('Successfully connected as a registered user and settings saved.', 'ai-eshop-optimizer'));

                    
                    if ($remember_auth) {
                        $expiry_time = time() + (30 * DAY_IN_SECONDS); 
                        update_option('aieo_auth_expiry', $expiry_time);
                    } else {
                        
                        delete_option('aieo_auth_expiry');
                    }
                }

                wp_safe_redirect(wp_get_referer());
                exit;
            } else {
                
                wp_die(esc_html__('Security check 4 failed.', 'ai-eshop-optimizer'));
            }
        }

        
        public function aieo_handle_logout_account()
        {
            
            if (!isset($_GET['_wpnonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['_wpnonce'])), 'aieo_logout_account')) {
                wp_die(esc_html__('Security check failed.', 'ai-eshop-optimizer'));
            }

            
            delete_option('aieo_auth_expiry');
            delete_option('aieo_remember_auth');
            delete_option('aieo_jwt_token');
            delete_option('aieo_user_membership');
            delete_option('aieo_subscription_expiration');
            delete_option('aieo_activate_account');

            
            delete_option('aieo_account_username');
            delete_option('aieo_account_password');

            
            update_option('aieo_account_message', __('You have been logged out successfully. All authentication data has been cleared.', 'ai-eshop-optimizer'));

            
            wp_safe_redirect(admin_url('admin.php?page=ai-eshop-optimizer'));
            exit;
        }

        
        public function sanitize_url_for_comparison($url)
        {
            
            $url = preg_replace('#^https?://#', '', $url);
            
            $url = str_replace('www.', '', $url);
            
            $url = rtrim($url, '/');

            return $url;
        }

        public function remote_user_authenticate_and_check_membership($username, $password)
        {
            $auth_url = 'https://eshop-optimizer.com/wp-json/jwt-auth/v1/token/';
            $response = wp_remote_post($auth_url, [
                'body' => [
                    'username' => $username,
                    'password' => $password,
                ],
            ]);

            $body = wp_remote_retrieve_body($response);

            
            
            update_option('aieo_jwt_response', $body, false);

            if (is_wp_error($response)) {
                return 'Authentication request error: ' . $response->get_error_message();
            }

            $token_info = json_decode($body, true);
            if (empty($token_info['token'])) {
                
                if (isset($token_info['message'])) {
                    
                    $error_message = wp_strip_all_tags(html_entity_decode($token_info['message'], ENT_QUOTES, 'UTF-8'));
                    return 'Authentication failed: ' . $error_message;
                } elseif (isset($token_info['code'])) {
                    
                    $code = $token_info['code'];
                    if (strpos($code, 'invalid_username') !== false) {
                        return 'Authentication failed: The username you entered is not registered. Please check your username or try your email address.';
                    } elseif (strpos($code, 'incorrect_password') !== false) {
                        return 'Authentication failed: Incorrect password. Please try again.';
                    } else {
                        return 'Authentication failed: ' . $code;
                    }
                }
                return 'Authentication failed: Invalid credentials. Please check your username and password.';
            }
            
            update_option('aieo_jwt_token', $token_info['token']);

            
            $user_info_url = 'https://eshop-optimizer.com/wp-json/wp/v2/users/me/?JWT=' . $token_info['token'];
            $response = wp_remote_get($user_info_url, [
                'headers' => [
                    'Authorization' => 'Bearer ' . $token_info['token'],
                ],
            ]);

            if (is_wp_error($response)) {
                return 'User info request error: ' . $response->get_error_message();
            }

            $user_info_body = wp_remote_retrieve_body($response);
            $user_info = json_decode($user_info_body, true);

            
            update_option('aieo_jwt_debugging', $user_info_body, false);
            update_option('aieo_jwt_user_details', $user_info_body, false);

            
            if (isset($user_info['aieo_subscription_expiration_date'])) {
                update_option('aieo_subscription_expiration', $user_info['aieo_subscription_expiration_date']);
            } else {
                
            }

            
            $current_site_url = $this->sanitize_url_for_comparison(get_site_url());
            $sanitized_remote_url = '';
            $matching_website_db_prefix = null;
            $matching_report_db_suffix = null;

            if (isset($user_info['site_database_prefixes']) && is_array($user_info['site_database_prefixes'])) {
                foreach ($user_info['site_database_prefixes'] as $website) {
                    $sanitized_remote_url = $this->sanitize_url_for_comparison($website['website_url']);
                    if ($sanitized_remote_url === $current_site_url) {
                        $matching_website_db_prefix = $website['website_db_prefix'];

                        
                        if (isset($website['report_db_suffix'])) {
                            $matching_report_db_suffix = $website['report_db_suffix'];
                        }

                        break;
                    }
                }
            }

            if ($matching_website_db_prefix) {
                update_option('aieo_account_table', $matching_website_db_prefix);
                
                if ($matching_report_db_suffix) {
                    update_option('aieo_account_report_table', $matching_report_db_suffix);
                }
            } else {
                $error_message = "There is no registered website in the account that matches this URL. 
                        Current site URL (sanitized): {$current_site_url} | 
                        Remote site URL last checked (sanitized): {$sanitized_remote_url}";
                
                add_action('admin_notices', function () use ($error_message) {
                    echo '<div class="notice notice-error is-dismissible"><p>' . esc_html($error_message)  . '</p></div>';
                });
            }
            
            $messages = [];

            if (isset($user_info['site_database_prefixes']) && !empty($user_info['site_database_prefixes'])) {
                update_option('aieo_first_website_db_prefix', $user_info['site_database_prefixes'][0]['website_db_prefix']);
            }

            if (!isset($user_info['roles']) || !is_array($user_info['roles'])) {
                $messages[] = 'Error fetching user roles or roles not set. Response: ' . $user_info_body;
            }

            if (isset($user_info['roles']) && is_array($user_info['roles'])) {
                if (in_array('pro_users', $user_info['roles'])) {
                    if (current_user_can(AIEO_CAPABILITY)) {
                        update_option('aieo_user_membership', 'Pro');
                        $expiry_date = get_option('aieo_subscription_expiration', '1/1/2025');
                        update_option('aieo_user_expiry', $expiry_date);
                    }
                    $messages[] = 'You have been successfully authenticated as a Pro User';
                } elseif (in_array('free_users', $user_info['roles'])) {
                    if (current_user_can(AIEO_CAPABILITY)) {
                        update_option('aieo_user_membership', 'Free');
                        $expiry_date = get_option('aieo_subscription_expiration', '1/1/2025');
                        update_option('aieo_user_expiry', $expiry_date);
                    }
                    $messages[] = 'You have been successfully authenticated as a Free User';
                } else {
                    
                    $user_roles = implode(', ', $user_info['roles']);
                    $username = isset($user_info['name']) ? $user_info['name'] : 'User';
                    $messages[] = 'Authentication successful, but your account does not have Pro or Free user status. Current roles: ' . $user_roles . '. Please subscribe at <a href="https://rooster.systems/get-aieo/" target="_blank">https://rooster.systems/get-aieo/</a> to access Pro features.';
                }
            }
            return implode(' | ', $messages);
        }

        public function authenticate_with_stored_token()
        {
            $token = get_option('aieo_jwt_token');

            if (!$token) {
                return 'No token found.';
            }

            $user_info_url = 'https://eshop-optimizer.com/wp-json/wp/v2/users/me/?nowprocket';
            $response = wp_remote_get($user_info_url, [
                'headers' => [
                    'Authorization' => 'Bearer ' . $token,
                ],
            ]);

            if (is_wp_error($response)) {
                return 'User info request error: ' . $response->get_error_message();
            }
            $user_info = json_decode(wp_remote_retrieve_body($response), true);

            if (!isset($user_info['roles']) || !is_array($user_info['roles'])) {
                return 'Error fetching user roles or roles not set. Response: ' . wp_remote_retrieve_body($response);
            }
            if (isset($user_info['roles']) && is_array($user_info['roles'])) {
                if (in_array('pro_users', $user_info['roles'])) {

                    if (current_user_can(AIEO_CAPABILITY)) {
                        
                        update_option('aieo_user_membership', 'Pro');
                        update_option('aieo_user_membership', '1/1/2025');
                    }
                    return 'You have been successfully authenticated as a Pro User';
                }
            }
            if (in_array('free_users', $user_info['roles'])) {
                if (current_user_can(AIEO_CAPABILITY)) {
                    
                    update_option('aieo_user_membership', 'Free');
                }
                return 'You have been successfully authenticated as a Free User';
            }
            return 'Unknown role. User info: ' . wp_remote_retrieve_body($response);
        }

        function aieo_handle_eshop_optimizer_transfer_to_remote()
        {
            if (
                isset($_POST['eshop_optimizer_transfer_to_remote_nonce_8']) &&
                wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['eshop_optimizer_transfer_to_remote_nonce_8'])), 'eshop_optimizer_transfer_to_remote_action')
            ) {
                
                set_transient('aieo_upload_notice', 'Soon with you', 60 * 5); 

                wp_safe_redirect(esc_url(admin_url('admin.php?page=ai-eshop-optimizer')));
                exit;
            } else {
                
                wp_die(esc_html__('Security check 5 failed.', 'ai-eshop-optimizer'));
            }
        }

        
        public function aieo_init_export()
        {
            check_ajax_referer('aieo_export_nonce', 'nonce');

            if (!current_user_can(AIEO_CAPABILITY)) {
                wp_send_json_error(array('message' => __('Insufficient permissions', 'ai-eshop-optimizer')));
                return;
            }

            
            $settings = array(
                'create_attributes' => (isset($_POST['create_attributes']) && $_POST['create_attributes'] == '1') ? '1' : '0',
                'create_needs' => (isset($_POST['create_needs']) && $_POST['create_needs'] == '1') ? '1' : '0',
                'create_catalogue' => (isset($_POST['create_catalogue']) && $_POST['create_catalogue'] == '1') ? '1' : '0',
                'process_eshop_orders' => (isset($_POST['process_eshop_orders']) && $_POST['process_eshop_orders'] == '1') ? '1' : '0',
                'process_instore_orders' => (isset($_POST['process_instore_orders']) && $_POST['process_instore_orders'] == '1') ? '1' : '0',
                'merge_orders' => (isset($_POST['merge_orders']) && $_POST['merge_orders'] == '1') ? '1' : '0',
                'include_unsold' => (isset($_POST['include_unsold']) && $_POST['include_unsold'] == '1') ? '1' : '0',
                'aggregate_product_stats' => (isset($_POST['aggregate_product_stats']) && $_POST['aggregate_product_stats'] == '1') ? '1' : '0',
                'aggregate_category_brand_stats' => (isset($_POST['aggregate_category_brand_stats']) && $_POST['aggregate_category_brand_stats'] == '1') ? '1' : '0',
                'aggregate_customer_std_stats' => (isset($_POST['aggregate_customer_std_stats']) && $_POST['aggregate_customer_std_stats'] == '1') ? '1' : '0',
                'aggregate_customer_adv_stats' => (isset($_POST['aggregate_customer_adv_stats']) && $_POST['aggregate_customer_adv_stats'] == '1') ? '1' : '0',
                'create_uuids' => (isset($_POST['create_uuids']) && $_POST['create_uuids'] == '1') ? '1' : '0',
                'create_need_suggestions' => (isset($_POST['create_need_suggestions']) && $_POST['create_need_suggestions'] == '1') ? '1' : '0',
                'create_export' => (isset($_POST['create_export']) && $_POST['create_export'] == '1') ? '1' : '0',
                'export_product_titles' => (isset($_POST['export_product_titles']) && $_POST['export_product_titles'] == '1') ? '1' : '0',
                'export_prices' => (isset($_POST['export_prices']) && $_POST['export_prices'] == '1') ? '1' : '0',
                'export_customer_ids' => (isset($_POST['export_customer_ids']) && $_POST['export_customer_ids'] == '1') ? '1' : '0',
                'seasonal_option'  => isset($_POST['seasonal_option'])  ? sanitize_text_field(wp_unslash($_POST['seasonal_option']))  : '',
                'vendor_taxonomy'  => isset($_POST['vendor_taxonomy'])  ? sanitize_text_field(wp_unslash($_POST['vendor_taxonomy']))  : '',
                'brand_taxonomy'   => isset($_POST['brand_taxonomy'])   ? sanitize_text_field(wp_unslash($_POST['brand_taxonomy']))   : '',
                'size_taxonomies'  => isset($_POST['size_taxonomies'])  ? sanitize_text_field(wp_unslash($_POST['size_taxonomies']))  : '',
                'color_taxonomies' => isset($_POST['color_taxonomies']) ? sanitize_text_field(wp_unslash($_POST['color_taxonomies'])) : '',
            );

            
            delete_transient('aieo_export_lock');
            delete_transient('aieo_product_stats_lock');
            delete_transient('aieo_customer_std_stats_lock');
            delete_transient('aieo_customer_adv_stats_lock');
            delete_transient('aieo_need_suggestions_progress');

            
            
            global $wpdb;
            $temp_orders_table_name = get_option('aieo_site_orders_table', $wpdb->prefix . 'aieo_temp_orders');
            $temp_products_table_name = get_option('aieo_site_products_table', $wpdb->prefix . 'aieo_temp_product_catalogue');

            $reset_orders_table = ($settings['process_eshop_orders'] === '1' || $settings['process_instore_orders'] === '1' || $settings['merge_orders'] === '1');
            if ($reset_orders_table) {
                $wpdb->query("DROP TABLE IF EXISTS {$temp_orders_table_name}");
                aieo_create_temp_orders_table($temp_orders_table_name);
                $this->aieo_log('Temp orders table reset for fresh order processing.', array(
                    'table' => $temp_orders_table_name,
                ));
            } else {
                $this->aieo_ensure_temp_orders_schema($temp_orders_table_name);
            }

            $reset_products_table = ($settings['create_catalogue'] === '1');
            if ($reset_products_table) {
                $wpdb->query("DROP TABLE IF EXISTS {$temp_products_table_name}");
                aieo_create_temp_products_table($temp_products_table_name);
                $this->aieo_log('Temp products table reset for catalogue build.', array(
                    'table' => $temp_products_table_name,
                ));
            } elseif (!$this->aieo_table_exists($temp_products_table_name)) {
                aieo_create_temp_products_table($temp_products_table_name);
            }

            
            $export_id = uniqid('export_', true);

            
            set_transient('aieo_export_settings', $settings, 7200);
            set_transient('aieo_export_id', $export_id, 7200);
            delete_transient('aieo_export_progress');

            
            update_option('aieo_create_attributes', $settings['create_attributes']);
            update_option('aieo_create_catalogue', $settings['create_catalogue']);
            update_option('aieo_create_orders', $settings['process_eshop_orders']);
            update_option('aieo_erp_consolidation', $settings['process_instore_orders']);
            update_option('aieo_erp_merge_orders', $settings['merge_orders']);
            update_option('aieo_include_unsold', $settings['include_unsold']);
            update_option('aieo_include_aggregate_stats', $settings['aggregate_product_stats']);
            update_option('aieo_include_aggregate_category_brand_stats', $settings['aggregate_category_brand_stats']);
            update_option('aieo_include_aggregate_cust_std_stats', $settings['aggregate_customer_std_stats']);
            update_option('aieo_include_aggregate_cust_adv_stats', $settings['aggregate_customer_adv_stats']);
            update_option('aieo_create_uuids', $settings['create_uuids']);
            update_option('aieo_create_need_suggestions', $settings['create_need_suggestions']);
            update_option('aieo_create_export', $settings['create_export']);
            update_option('aieo_core_attribute_vendor', $settings['vendor_taxonomy']);
            update_option('aieo_core_attribute_brands', $settings['brand_taxonomy']);
            update_option('aieo_core_attribute_size', $settings['size_taxonomies']);
            update_option('aieo_core_attribute_color', $settings['color_taxonomies']);

            wp_send_json_success(array(
                'message' => __('Export initialized', 'ai-eshop-optimizer'),
                'export_id' => $export_id
            ));
        }

        
        
        public function aieo_get_download_section()
        {
            check_ajax_referer('aieo_export_nonce', 'nonce');

            if (!current_user_can(AIEO_CAPABILITY)) {
                wp_send_json_error(array('message' => __('Insufficient permissions', 'ai-eshop-optimizer')));
                return;
            }

            $csv_info = get_option('aieo_last_export_csv', array());
            $file_path = isset($csv_info['path']) ? $csv_info['path'] : '';
            $download_url = isset($csv_info['url']) ? $csv_info['url'] : '';
            $filename = isset($csv_info['filename']) ? $csv_info['filename'] : basename($file_path);

            aieo_debug_log('AIEO: Download section - CSV info: ' . wp_json_encode($csv_info));
            aieo_debug_log('AIEO: Download section - File path: ' . $file_path);
            aieo_debug_log('AIEO: Download section - Download URL: ' . $download_url);
            aieo_debug_log('AIEO: Download section - File exists: ' . (file_exists($file_path) ? 'yes' : 'no'));

            if (empty($file_path) || empty($download_url) || !file_exists($file_path)) {
                $error_details = array();
                if (empty($file_path)) $error_details[] = 'file path is empty';
                if (empty($download_url)) $error_details[] = 'download URL is empty';
                if (!empty($file_path) && !file_exists($file_path)) $error_details[] = 'file does not exist at: ' . $file_path;

                aieo_debug_log('AIEO: Download section - Export file missing or metadata unavailable. Details: ' . implode(', ', $error_details));
                wp_send_json_error(array(
                    'message' => __('Export file not found yet. Details:', 'ai-eshop-optimizer') . ' ' . implode(', ', $error_details)
                ));
                return;
            }

            aieo_debug_log('AIEO: Download section - File found at: ' . $file_path);

            
            $downloadfilemessage = sprintf(
                
                __('The orders file has been created!!!</br>Download: <a href="%1$s">%2$s</a>', 'ai-eshop-optimizer'),
                esc_url($download_url),
                esc_html($filename)
            );

            
            ob_start();
            ?>
            <div class="aieo-modules-list-item-support">
                <div class="aieo-modules-list-item-icon-support">
                    <svg id="glipy_copy_4" data-name="glipy copy 4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
                        <title>1</title>
                        <path d="M32,2A30,30,0,1,0,62,32,30.03657,30.03657,0,0,0,32,2ZM38.45,48.13a.717.717,0,0,1-.72.72H26.28a.71492.71492,0,0,1-.71-.72V45.27a.7151.7151,0,0,1,1.43,0v2.15H37.02V45.27a.715.715,0,1,1,1.43,0Zm-4.8-5.51a.695.695,0,0,1,1.01,0,.71226.71226,0,0,1,0,1.01l-2.14,2.15a.74336.74336,0,0,1-1.02,0l-2.15-2.15a.71773.71773,0,0,1,1.02-1.01l.92.92V32.39a.715.715,0,0,1,1.43,0V43.54Zm9.48-4.44-8.97-.04V32.39a2.15013,2.15013,0,0,0-4.3,0v5.74L18.3,38.08a6.361,6.361,0,0,1-1.41-12.55.86162.86162,0,0,0,.26-.34A6.70364,6.70364,0,0,1,28.67,23.1a.71653.71653,0,0,0,1.01.11c1.13-1.05-2.07-2.93-2.9-3.29a6.69654,6.69654,0,0,1,13.11,1.92.715.715,0,0,0,1.43,0,7.83085,7.83085,0,0,0-.12-1.29,8.9141,8.9141,0,0,1,1.93-.21C54.96,20.83,54.95,37.69,43.13,38.18Z"/>
                    </svg>
                </div>
                <div class="aieo-modules-list-item-content">
                    <div class="aieo-modules-list-item-title">Download orders file & clean up!
                        <i class="aieo-modules-indicator-support"></i>
                    </div>
                    <div class="aieo-modules-list-item-desc">
                        <div class="aieo-file-download"><?php echo wp_kses_post($downloadfilemessage); ?></div>
                        <?php if ((int) get_option('aieo_activate_remote_connection') === 1): ?>
                            <div class="aieo-pro">As a pro user you can upload the file directly from this plugin via the upload data in your server tab</div>
                        <?php else: ?>
                            <div class="aieo-promo">Why do we save your file on your server?</br>Our pro users on annual contracts are able to transfer their data directly into our server for optimization calculations and fully automate the process</div>
                        <?php endif; ?>
                        <div class="aieo-cellsubmit">
                            <a href="<?php echo esc_url(wp_nonce_url(admin_url('admin-post.php?action=delete_exported_file'), 'delete_exported_file')); ?>"
                               class="aieo-button button-primary aieo-button-alarm aieo-buttonsubmit">
                                Important! Click to remove the file from your server
                            </a>
                        </div>
                    </div>
                </div>
            </div>
            <?php
            $html = ob_get_clean();

            wp_send_json_success(array(
                'html' => $html,
                'message' => __('Download section loaded successfully', 'ai-eshop-optimizer'),
                'filename' => $filename,
                'url' => $download_url
            ));
        }

        
        public function aieo_check_vitals_data()
        {
            check_ajax_referer('aieo_export_nonce', 'nonce');

            if (!current_user_can(AIEO_CAPABILITY)) {
                wp_send_json_error(array('message' => __('Insufficient permissions', 'ai-eshop-optimizer')));
                return;
            }

            global $wpdb;
            $vitals_table = $wpdb->prefix . 'aieo_core_product_vitals';

            
            $table_exists = $wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $vitals_table)) === $vitals_table;

            $has_data = false;
            if ($table_exists) {
                $count = $wpdb->get_var("SELECT COUNT(*) FROM {$vitals_table}");
                $has_data = ($count > 0);
            }

            wp_send_json_success(array(
                'has_data' => $has_data,
                'count' => isset($count) ? (int)$count : 0
            ));
        }

        public function aieo_get_statistics_section()
        {
            try {
                check_ajax_referer('aieo_export_nonce', 'nonce');

                if (!current_user_can(AIEO_CAPABILITY)) {
                    wp_send_json_error(array('message' => __('Insufficient permissions', 'ai-eshop-optimizer')));
                    return;
                }

                aieo_debug_log('AIEO: Statistics section - Starting request');

                
                if (!function_exists('aieo_get_temp_orders_table_for_insights')) {
                    $helper_file = plugin_dir_path(__FILE__) . 'ai-eshop-optimizer-functions.php';
                    if (file_exists($helper_file)) {
                        require_once $helper_file;
                        aieo_debug_log('AIEO: Statistics section - Loaded helper functions from separate file');
                    } else {
                        
                        aieo_debug_log('AIEO: Statistics section - Helper file not found, functions should already be loaded');
                    }
                }

                
                global $wpdb;

                
                if (!function_exists('aieo_get_temp_orders_table_for_insights')) {
                    aieo_debug_log('AIEO: Statistics section - Helper functions not available');
                    wp_send_json_error(array(
                        'message' => __('Helper functions not loaded. Please refresh the page and try again.', 'ai-eshop-optimizer')
                    ));
                    return;
                }

                $aieo_orders_table = aieo_get_temp_orders_table_for_insights();
                aieo_debug_log('AIEO: Statistics section - Orders table: ' . ($aieo_orders_table ? $aieo_orders_table : 'NOT FOUND'));

            if (!$aieo_orders_table) {
                wp_send_json_error(array(
                    'message' => __('Statistics not ready yet. Please wait for the advanced statistics processing to complete.', 'ai-eshop-optimizer')
                ));
                return;
            }

            $has_product_stats = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$aieo_orders_table} WHERE TotalItemSales IS NOT NULL AND TotalItemSales > 0 LIMIT 1");
            $has_adv_stats = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$aieo_orders_table} WHERE AvgOrderSize IS NOT NULL AND AvgOrderSize > 0 LIMIT 1");

            if (!$has_product_stats || !$has_adv_stats) {
                wp_send_json_error(array(
                    'message' => __('Statistics not ready yet. Please wait for the advanced statistics processing to complete.', 'ai-eshop-optimizer')
                ));
                return;
            }

            
            $aieo_insight_data = array(
                'available' => false,
                'single_products' => array(),
                'favourite_products' => array(),
                'brands' => array(),
            );

            $aieo_insight_data['single_products'] = aieo_fetch_single_product_focus($aieo_orders_table);
            $aieo_insight_data['favourite_products'] = aieo_fetch_favourite_products($aieo_orders_table);
            $aieo_insight_data['brands'] = aieo_fetch_brand_focus($aieo_orders_table);

            if (empty($aieo_insight_data['single_products']) && empty($aieo_insight_data['favourite_products']) && empty($aieo_insight_data['brands'])) {
                wp_send_json_error(array(
                    'message' => __('No statistics data available yet.', 'ai-eshop-optimizer')
                ));
                return;
            }

            $aieo_insight_data['available'] = true;

            
            ob_start();
            ?>
            <div class="aieo-modules-box">
                <div class="aieo-modules-box-heading">Indicative Statistics</div>
                <div class="aieo-modules-list">
                    <div class="aieo-modules-list-item-action">
                        <div class="aieo-modules-list-item-icon-action">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">
                                <path
                                    d="M32 6C17.664 6 6 17.664 6 32s11.664 26 26 26 26-11.664 26-26S46.336 6 32 6zm0 48C19.215 54 10 44.785 10 32S19.215 10 32 10s22 9.215 22 22-9.215 22-22 22z" />
                                <path
                                    d="M44 32c0-6.627-5.373-12-12-12s-12 5.373-12 12 5.373 12 12 12 12-5.373 12-12zm-20 0c0-4.411 3.589-8 8-8s8 3.589 8 8-3.589 8-8 8-8-3.589-8-8z" />
                            </svg>
                        </div>
                        <div class="aieo-modules-list-item-content">
                            <div class="aieo-modules-list-item-title">Your customers' favourite products</div>
                            <div class="aieo-modules-list-item-desc">
                                <p><?php esc_html_e('Frequently the first or last items added to multi-product carts—perfect candidates for prominent placement.', 'ai-eshop-optimizer'); ?>
                                </p>
                                <ul class="aieo-insight-list">
                                    <?php foreach ($aieo_insight_data['favourite_products'] as $item): ?>
                                        <li>
                                            <a href="<?php echo esc_url($item['permalink']); ?>"
                                                target="_blank"><?php echo esc_html($item['title']); ?></a>
                                            <span><?php
                                            
                                            printf(esc_html__('%1$s first-in-cart units · %2$s last-in-cart units', 'ai-eshop-optimizer'), esc_html(number_format_i18n($item['first_units'])), esc_html(number_format_i18n($item['last_units']))); ?></span>
                                        </li>
                                    <?php endforeach; ?>
                                </ul>
                            </div>
                        </div>
                    </div>
                    <div class="aieo-modules-list-item-action">
                        <div class="aieo-modules-list-item-icon-action">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">
                                <path
                                    d="M32 6C17.641 6 6 17.641 6 32s11.641 26 26 26 26-11.641 26-26S46.359 6 32 6zm0 48C19.215 54 10 44.785 10 32S19.215 10 32 10s22 9.215 22 22-9.215 22-22 22z" />
                                <path
                                    d="M42.707 29.293a1 1 0 0 0-1.414 0L33 37.586V20a1 1 0 0 0-2 0v17.586l-8.293-8.293a1 1 0 1 0-1.414 1.414l10 10a1 1 0 0 0 1.414 0l10-10a1 1 0 0 0 0-1.414z" />
                            </svg>
                        </div>
                        <div class="aieo-modules-list-item-content">
                            <div class="aieo-modules-list-item-title">The 10 products you MUST focus</div>
                            <div class="aieo-modules-list-item-desc">
                                <p><?php esc_html_e('These products drive the highest number of single-item orders. Enhancing their recommendations can have an immediate impact.', 'ai-eshop-optimizer'); ?>
                                </p>
                                <ul class="aieo-insight-list">
                                    <?php foreach ($aieo_insight_data['single_products'] as $item): ?>
                                        <li>
                                            <a href="<?php echo esc_url($item['permalink']); ?>"
                                                target="_blank"><?php echo esc_html($item['title']); ?></a>
                                            <span><?php
                                            
                                            printf(esc_html__('%1$s units across %2$s single-product orders', 'ai-eshop-optimizer'), esc_html(number_format_i18n($item['units'])), esc_html(number_format_i18n($item['orders']))); ?></span>
                                        </li>
                                    <?php endforeach; ?>
                                </ul>
                            </div>
                        </div>
                    </div>
                    <div class="aieo-modules-list-item-action">
                        <div class="aieo-modules-list-item-icon-action">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">
                                <path
                                    d="M12 8h40a2 2 0 0 1 2 2v44a2 2 0 0 1-2 2H12a2 2 0 0 1-2-2V10a2 2 0 0 1 2-2zm0 4v40h40V12H12z" />
                                <path d="M22 20h8v24h-8zm12 12h8v12h-8zm12-18h8v30h-8z" />
                            </svg>
                        </div>
                        <div class="aieo-modules-list-item-content">
                            <div class="aieo-modules-list-item-title">Brands that dominate single-entry carts</div>
                            <div class="aieo-modules-list-item-desc">
                                <p><?php esc_html_e('These brands excel in single-item purchases or taking the prime positions in multi-item orders.', 'ai-eshop-optimizer'); ?>
                                </p>
                                <ul class="aieo-insight-list">
                                    <?php foreach ($aieo_insight_data['brands'] as $item): ?>
                                        <li>
                                            <span
                                                class="aieo-insight-brand-name"><?php echo esc_html($item['brand']); ?></span>
                                            <span><?php
                                            
                                            printf(esc_html__('%1$s single-order units · %2$s first-in-cart units · %3$s last-in-cart units', 'ai-eshop-optimizer'), esc_html(number_format_i18n($item['single_units'])), esc_html(number_format_i18n($item['first_units'])), esc_html(number_format_i18n($item['last_units']))); ?></span>
                                        </li>
                                    <?php endforeach; ?>
                                </ul>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <?php
            $html = ob_get_clean();

                wp_send_json_success(array(
                    'html' => $html,
                    'message' => __('Statistics section loaded successfully', 'ai-eshop-optimizer')
                ));
            } catch (Exception $e) {
                aieo_debug_log('AIEO: Statistics section - Exception: ' . $e->getMessage());
                aieo_debug_log('AIEO: Statistics section - Stack trace: ' . $e->getTraceAsString());
                wp_send_json_error(array(
                    'message' => __('Error loading statistics:', 'ai-eshop-optimizer') . ' ' . $e->getMessage()
                ));
            }
        }

        public function aieo_save_settings()
        {
            check_ajax_referer('aieo_export_nonce', 'nonce');

            if (!current_user_can(AIEO_CAPABILITY)) {
                wp_send_json_error(array('message' => __('Insufficient permissions', 'ai-eshop-optimizer')));
                return;
            }

            
            $settings = array(
                
                'create_attributes' => (isset($_POST['create_attributes']) && $_POST['create_attributes'] == '1') ? '1' : '0',
                'create_needs' => (isset($_POST['create_needs']) && $_POST['create_needs'] == '1') ? '1' : '0',
                'create_need_suggestions' => (isset($_POST['create_need_suggestions']) && $_POST['create_need_suggestions'] == '1') ? '1' : '0',
                'create_catalogue' => (isset($_POST['create_catalogue']) && $_POST['create_catalogue'] == '1') ? '1' : '0',
                'process_eshop_orders' => (isset($_POST['process_eshop_orders']) && $_POST['process_eshop_orders'] == '1') ? '1' : '0',
                'process_instore_orders' => (isset($_POST['process_instore_orders']) && $_POST['process_instore_orders'] == '1') ? '1' : '0',
                'merge_orders' => (isset($_POST['merge_orders']) && $_POST['merge_orders'] == '1') ? '1' : '0',
                'include_unsold' => (isset($_POST['include_unsold']) && $_POST['include_unsold'] == '1') ? '1' : '0',
                'aggregate_product_stats' => (isset($_POST['aggregate_product_stats']) && $_POST['aggregate_product_stats'] == '1') ? '1' : '0',
                'aggregate_category_brand_stats' => (isset($_POST['aggregate_category_brand_stats']) && $_POST['aggregate_category_brand_stats'] == '1') ? '1' : '0',
                'aggregate_customer_std_stats' => (isset($_POST['aggregate_customer_std_stats']) && $_POST['aggregate_customer_std_stats'] == '1') ? '1' : '0',
                'aggregate_customer_adv_stats' => (isset($_POST['aggregate_customer_adv_stats']) && $_POST['aggregate_customer_adv_stats'] == '1') ? '1' : '0',
                'create_uuids' => (isset($_POST['create_uuids']) && $_POST['create_uuids'] == '1') ? '1' : '0',
                'create_export' => (isset($_POST['create_export']) && $_POST['create_export'] == '1') ? '1' : '0',
                
                'include_text' => (isset($_POST['include_text']) && $_POST['include_text'] == '1') ? '1' : '0',
                'include_attributes' => (isset($_POST['include_attributes']) && $_POST['include_attributes'] == '1') ? '1' : '0',
                'include_full_text' => (isset($_POST['include_full_text']) && $_POST['include_full_text'] == '1') ? '1' : '0',
                'include_price' => (isset($_POST['include_price']) && $_POST['include_price'] == '1') ? '1' : '0',
                'variations_choice' => (isset($_POST['variations_choice']) && $_POST['variations_choice'] == '1') ? '1' : '0',
                'include_eponymous' => (isset($_POST['include_eponymous']) && $_POST['include_eponymous'] == '1') ? '1' : '0',
                
                'include_reciprocity' => (isset($_POST['include_reciprocity']) && $_POST['include_reciprocity'] == '1') ? '1' : '0',
                'include_seasonality' => (isset($_POST['include_seasonality']) && $_POST['include_seasonality'] == '1') ? '1' : '0',
                'include_restricted_seasonality' => (isset($_POST['include_restricted_seasonality']) && $_POST['include_restricted_seasonality'] == '1') ? '1' : '0',
                'instore_anonymous' => (isset($_POST['instore_anonymous']) && $_POST['instore_anonymous'] == '1') ? '1' : '0',
                
                'vendor_taxonomy' => isset($_POST['vendor_taxonomy']) ? sanitize_text_field(wp_unslash($_POST['vendor_taxonomy'])) : '',
                'brand_taxonomy' => isset($_POST['brand_taxonomy']) ? sanitize_text_field(wp_unslash($_POST['brand_taxonomy'])) : '',
                'size_taxonomies' => isset($_POST['size_taxonomies']) ? sanitize_text_field(wp_unslash($_POST['size_taxonomies'])) : '',
                'color_taxonomies' => isset($_POST['color_taxonomies']) ? sanitize_text_field(wp_unslash($_POST['color_taxonomies'])) : '',
                'need_taxonomy' => isset($_POST['need_taxonomy']) ? sanitize_text_field(wp_unslash($_POST['need_taxonomy'])) : '',
                
                'season_days_past' => isset($_POST['season_days_past']) ? intval($_POST['season_days_past']) : '',
                'season_days_after' => isset($_POST['season_days_after']) ? intval($_POST['season_days_after']) : ''
            );

            
            
            update_option('aieo_create_attributes', $settings['create_attributes']);
            update_option('aieo_create_needs', $settings['create_needs']);
            update_option('aieo_create_need_suggestions', $settings['create_need_suggestions']);
            update_option('aieo_create_catalogue', $settings['create_catalogue']);
            update_option('aieo_create_orders', $settings['process_eshop_orders']);
            update_option('aieo_erp_consolidation', $settings['process_instore_orders']);
            update_option('aieo_erp_merge_orders', $settings['merge_orders']);
            update_option('aieo_include_unsold', $settings['include_unsold']);
            update_option('aieo_include_aggregate_stats', $settings['aggregate_product_stats']);
            update_option('aieo_include_aggregate_category_brand_stats', $settings['aggregate_category_brand_stats']);
            update_option('aieo_include_aggregate_cust_std_stats', $settings['aggregate_customer_std_stats']);
            update_option('aieo_include_aggregate_cust_adv_stats', $settings['aggregate_customer_adv_stats']);
            update_option('aieo_create_uuids', $settings['create_uuids']);
            update_option('aieo_create_export', $settings['create_export']);
            
            update_option('aieo_include_text', $settings['include_text']);
            update_option('aieo_include_attributes', $settings['include_attributes']);
            update_option('aieo_include_full_text', $settings['include_full_text']);
            update_option('aieo_include_price', $settings['include_price']);
            update_option('aieo_variations_choice', $settings['variations_choice']);
            update_option('aieo_include_eponymous', $settings['include_eponymous']);
            
            update_option('aieo_include_reciprocity', $settings['include_reciprocity']);
            update_option('aieo_include_seasonality', $settings['include_seasonality']);
            update_option('aieo_include_restricted_seasonality', $settings['include_restricted_seasonality']);
            update_option('aieo_instore_anonymous', $settings['instore_anonymous']);
            
            update_option('aieo_core_attribute_vendor', $settings['vendor_taxonomy']);
            update_option('aieo_core_attribute_brands', $settings['brand_taxonomy']);
            update_option('aieo_core_attribute_size', $settings['size_taxonomies']);
            update_option('aieo_core_attribute_color', $settings['color_taxonomies']);
            update_option('aieo_core_attribute_need', $settings['need_taxonomy']);
            
            update_option('aieo_season_days_past', $settings['season_days_past']);
            update_option('aieo_season_days_after', $settings['season_days_after']);

            
            wp_cache_delete('aieo_create_attributes', 'options');
            wp_cache_delete('aieo_create_needs', 'options');
            wp_cache_delete('aieo_create_need_suggestions', 'options');
            wp_cache_delete('aieo_create_catalogue', 'options');
            wp_cache_delete('aieo_create_orders', 'options');
            wp_cache_delete('aieo_erp_consolidation', 'options');
            wp_cache_delete('aieo_erp_merge_orders', 'options');
            wp_cache_delete('aieo_include_unsold', 'options');
            wp_cache_delete('aieo_include_aggregate_stats', 'options');
            wp_cache_delete('aieo_include_aggregate_cust_std_stats', 'options');
            wp_cache_delete('aieo_include_aggregate_cust_adv_stats', 'options');
            wp_cache_delete('aieo_create_uuids', 'options');
            wp_cache_delete('aieo_create_export', 'options');
            wp_cache_delete('aieo_include_text', 'options');
            wp_cache_delete('aieo_include_attributes', 'options');
            wp_cache_delete('aieo_include_full_text', 'options');
            wp_cache_delete('aieo_include_price', 'options');
            wp_cache_delete('aieo_variations_choice', 'options');
            wp_cache_delete('aieo_include_eponymous', 'options');
            wp_cache_delete('aieo_include_reciprocity', 'options');
            wp_cache_delete('aieo_include_seasonality', 'options');
            wp_cache_delete('aieo_include_restricted_seasonality', 'options');
            wp_cache_delete('aieo_instore_anonymous', 'options');
            wp_cache_delete('aieo_season_days_past', 'options');
            wp_cache_delete('aieo_season_days_after', 'options');
            wp_cache_delete('aieo_core_attribute_need', 'options');

            wp_send_json_success(array('message' => __('Settings saved successfully', 'ai-eshop-optimizer')));
        }

        
        private static function aieo_register_export_lock_shutdown($lock_key, $export_id) {
            static $registered = array();
            $sig = $lock_key . '|' . $export_id;
            if (isset($registered[$sig])) { return; }
            $registered[$sig] = true;

            register_shutdown_function(function () use ($lock_key, $export_id) {
                $err = error_get_last();
                $fatal_types = array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR);
                if (!$err || !in_array($err['type'], $fatal_types, true)) {
                    return;
                }
                if (get_transient($lock_key) === $export_id) {
                    delete_transient($lock_key);
                }
            });
        }

        
        public function aieo_process_export_batch()
        {
            check_ajax_referer('aieo_export_nonce', 'nonce');

            if (!current_user_can(AIEO_CAPABILITY)) {
                wp_send_json_error(array('message' => __('Insufficient permissions', 'ai-eshop-optimizer')));
                return;
            }

            global $wpdb;
            $stage = isset($_POST['stage']) ? sanitize_text_field(wp_unslash($_POST['stage'])) : '';

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

            
            if (empty($export_id)) {
                $export_id = get_transient('aieo_export_id');
            }

            
            $source = isset($_POST['export_id']) ? 'POST' : 'transient';
            aieo_debug_log("AIEO Export Batch - Stage: {$stage}, Export ID: " . ($export_id ? $export_id : 'NULL') . " (source: {$source})");

            if (!$export_id) {
                
                $all_transients = $wpdb->get_results(
                    "SELECT option_name, option_value FROM {$wpdb->options}
                     WHERE option_name LIKE '_transient_aieo_%'
                     ORDER BY option_name",
                    ARRAY_A
                );
                aieo_debug_log("AIEO Export - Transients found: " . wp_json_encode($all_transients));

                wp_send_json_error(array('message' => __('Export session expired. Please start a new export.', 'ai-eshop-optimizer')));
                return;
            }

            
            
            
            set_transient('aieo_export_id', $export_id, 7200);

            $settings = get_transient('aieo_export_settings');
            if ($settings) {
                set_transient('aieo_export_settings', $settings, 7200);
            }

            
            $export_lock = get_transient('aieo_export_lock');
            if ($export_lock && $export_lock !== $export_id) {
                wp_send_json_error(array(
                    'message' => __('An export is already running. Please wait for it to complete or refresh the page.', 'ai-eshop-optimizer')
                ));
                return;
            }

            
            set_transient('aieo_export_lock', $export_id, 1800);

            $settings = get_transient('aieo_export_settings');

            
            if (!$settings) {
                $settings = array(
                    'create_attributes' => get_option('aieo_create_attributes', '0'),
                    'create_needs' => get_option('aieo_create_needs', '0'),
                    'create_catalogue' => get_option('aieo_create_catalogue', '0'),
                    'process_eshop_orders' => get_option('aieo_create_orders', '0'),
                    'process_instore_orders' => get_option('aieo_erp_consolidation', '0'),
                    'merge_orders' => get_option('aieo_erp_merge_orders', '0'),
                    'include_unsold' => get_option('aieo_include_unsold', '0'),
                    'aggregate_product_stats' => get_option('aieo_include_aggregate_stats', '0'),
                    'aggregate_category_brand_stats' => get_option('aieo_include_aggregate_category_brand_stats', '0'),
                    'aggregate_customer_std_stats' => get_option('aieo_include_aggregate_cust_std_stats', '0'),
                    'aggregate_customer_adv_stats' => get_option('aieo_include_aggregate_cust_adv_stats', '0'),
                    'create_uuids' => get_option('aieo_create_uuids', '0'),
                    'create_need_suggestions' => get_option('aieo_create_need_suggestions', '0'),
                    'create_export' => get_option('aieo_create_export', '0'),
                    'export_product_titles' => get_option('aieo_export_product_titles', '0'),
                    'export_prices' => get_option('aieo_export_prices', '0'),
                    'export_customer_ids' => get_option('aieo_export_customer_ids', '0'),
                    'seasonal_option' => get_option('aieo_seasonal_option', '0'),
                    'vendor_taxonomy' => get_option('aieo_vendor_taxonomy', ''),
                    'brand_taxonomy' => get_option('aieo_brand_taxonomy', ''),
                    'size_taxonomies' => get_option('aieo_size_taxonomies', ''),
                    'color_taxonomies' => get_option('aieo_color_taxonomies', '')
                );

                
                set_transient('aieo_export_settings', $settings, 7200);
            }

            $site_prefix = $wpdb->prefix;

            
            
            $time_limit = 600; 
            if ($stage === 'create_attributes') {
                $time_limit = 900; 
            } elseif ($stage === 'process_eshop_orders' || $stage === 'process_instore_orders') {
                $time_limit = 900; 
            } elseif ($stage === 'aggregate_customer_std_stats' || $stage === 'aggregate_customer_adv_stats') {
                $time_limit = 1800; 
            }

            set_time_limit($time_limit);

            try {
                switch ($stage) {
                    case 'create_attributes':
                        if ($settings['create_attributes'] == '1') {
                            
                            $sub_step = isset($_POST['sub_step']) ? intval($_POST['sub_step']) : 0;
                            $total_sub_steps = 6; 

                            aieo_debug_log("AIEO: create_attributes - Sub-step: {$sub_step}");

                            switch ($sub_step) {
                                case 0:
                                    
                                    aieo_debug_log("AIEO: Executing InsertCoreProductAttributes");
                                    $wpdb->query($wpdb->prepare(
                                        "CALL `{$site_prefix}AIEO_InsertCoreProductAttributes` (%s, %s, %s, %s)",
                                        $settings['vendor_taxonomy'],
                                        $settings['brand_taxonomy'],
                                        $settings['size_taxonomies'],
                                        $settings['color_taxonomies']
                                    ));
                                    $count_attributes = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}aieo_core_product_attributes");
                                    aieo_debug_log("AIEO: Brands created: {$count_attributes} records");

                                    wp_send_json_success(array(
                                        'complete' => false,
                                        
                                        'message' => sprintf(__('Step 1/6: ✓ Brands: %d records', 'ai-eshop-optimizer'), $count_attributes),
                                        'current' => 1,
                                        'total' => $total_sub_steps,
                                        'sub_step' => 1
                                    ));
                                    break;

                                case 1:
                                    
                                    aieo_debug_log("AIEO: Executing InsertProductCategoryHierarchy");
                                    $wpdb->query("CALL `{$site_prefix}AIEO_InsertProductCategoryHierarchy` ()");
                                    $count_hierarchy = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}aieo_core_product_category_hierarchy");
                                    aieo_debug_log("AIEO: Category Hierarchy created: {$count_hierarchy} records");

                                    wp_send_json_success(array(
                                        'complete' => false,
                                        
                                        'message' => sprintf(__('Step 2/6: ✓ Category Hierarchy: %d records', 'ai-eshop-optimizer'), $count_hierarchy),
                                        'current' => 2,
                                        'total' => $total_sub_steps,
                                        'sub_step' => 2
                                    ));
                                    break;

                                case 2:
                                    
                                    aieo_debug_log("AIEO: Executing InsertProductVitals");
                                    $wpdb->query("CALL `{$site_prefix}AIEO_InsertProductVitals` ()");
                                    $count_product_vitals = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}aieo_core_product_vitals WHERE parent_id = product_id");
                                    aieo_debug_log("AIEO: Product Vitals (Parents) created: {$count_product_vitals} records");

                                    wp_send_json_success(array(
                                        'complete' => false,
                                        
                                        'message' => sprintf(__('Step 3/6: ✓ Product Vitals (Parents): %d records', 'ai-eshop-optimizer'), $count_product_vitals),
                                        'current' => 3,
                                        'total' => $total_sub_steps,
                                        'sub_step' => 3
                                    ));
                                    break;

                                case 3:
                                    
                                    aieo_debug_log("AIEO: Executing InsertVariationVitals");
                                    aieo_debug_log("AIEO: Settings - Vendor: {$settings['vendor_taxonomy']}, Brand: {$settings['brand_taxonomy']}, Size: {$settings['size_taxonomies']}, Color: {$settings['color_taxonomies']}");

                                    
                                    $variation_vitals_table = $wpdb->prefix . 'aieo_core_variation_vitals';
                                    $table_exists = $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $variation_vitals_table));
                                    if (!$table_exists) {
                                        aieo_debug_log("AIEO: ERROR - Variation vitals table does not exist: {$variation_vitals_table}");
                                        wp_send_json_error(array('message' => __('Variation vitals table does not exist. Please check database setup.', 'ai-eshop-optimizer')));
                                        break;
                                    }

                                    
                                    $products_with_variations = $wpdb->get_var("
                                        SELECT COUNT(DISTINCT p.ID)
                                        FROM {$wpdb->prefix}posts p
                                        INNER JOIN {$wpdb->prefix}posts v ON p.ID = v.post_parent
                                        WHERE p.post_type = 'product'
                                        AND p.post_status = 'publish'
                                        AND v.post_type = 'product_variation'
                                        AND v.post_status = 'publish'
                                    ");
                                    aieo_debug_log("AIEO: Found {$products_with_variations} products with variations");

                                    
                                    $result = $wpdb->query("CALL `{$site_prefix}AIEO_InsertVariationVitals` ()");

                                    
                                    if ($wpdb->last_error) {
                                        aieo_debug_log("AIEO: ERROR in InsertVariationVitals - Database error: " . $wpdb->last_error);
                                        wp_send_json_error(array(
                                            'message' => __('Database error:', 'ai-eshop-optimizer') . ' ' . $wpdb->last_error
                                        ));
                                        break;
                                    }

                                    if ($result === false) {
                                        aieo_debug_log("AIEO: ERROR - InsertVariationVitals returned false");
                                        wp_send_json_error(array('message' => __('Failed to execute Variation Vitals procedure. Check WordPress debug log for details.', 'ai-eshop-optimizer')));
                                        break;
                                    }

                                    
                                    $count_variation_vitals = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}aieo_core_variation_vitals");
                                    aieo_debug_log("AIEO: Variation Vitals created: {$count_variation_vitals} records");

                                    
                                    $sample_variations = $wpdb->get_results("SELECT product_id, parent_id, size, color FROM {$wpdb->prefix}aieo_core_variation_vitals LIMIT 5", ARRAY_A);
                                    aieo_debug_log("AIEO: Sample variation vitals: " . wp_json_encode($sample_variations));

                                    wp_send_json_success(array(
                                        'complete' => false,
                                        
                                        'message' => sprintf(__('Step 4/6: ✓ Variation Vitals: %d records', 'ai-eshop-optimizer'), $count_variation_vitals),
                                        'current' => 4,
                                        'total' => $total_sub_steps,
                                        'sub_step' => 4
                                    ));
                                    break;

                                case 4:
                                    
                                    aieo_debug_log("AIEO: Executing CombineVariationVitalsInProductVitals");
                                    $wpdb->query("CALL `{$site_prefix}AIEO_CombineVariationVitalsInProductVitals` ()");
                                    $count_variations_combined = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}aieo_core_product_vitals WHERE parent_id != product_id");
                                    aieo_debug_log("AIEO: Variations combined: {$count_variations_combined} records");

                                    
                                    
                                    
                                    
                                    
                                    if (!class_exists('AI_eShop_Product_Needs')) {
                                        require_once plugin_dir_path(__FILE__) . 'class-product-needs.php';
                                    }
                                    AI_eShop_Product_Needs::get_instance()->populate_product_needs();
                                    $count_with_needs = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}aieo_core_product_vitals WHERE primary_need_id IS NOT NULL");
                                    aieo_debug_log("AIEO: Needs populated for {$count_with_needs} vitals rows");

                                    
                                    delete_transient('aieo_chat_sellable_breakdown');
                                    delete_transient('aieo_chat_count_sellable_units_0');
                                    delete_transient('aieo_chat_count_sellable_units_1');

                                    wp_send_json_success(array(
                                        'complete' => false,
                                        
                                        'message' => sprintf(__('Step 5/6: ✓ Variations Added to Product Vitals: %1$d records (needs populated for %2$d)', 'ai-eshop-optimizer'), $count_variations_combined, $count_with_needs),
                                        'current' => 5,
                                        'total' => $total_sub_steps,
                                        'sub_step' => 5
                                    ));
                                    break;

                                case 5:
                                    
                                    $total_vitals = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}aieo_core_product_vitals");
                                    aieo_debug_log("AIEO: Total Product Vitals: {$total_vitals} records");

                                    wp_send_json_success(array(
                                        'complete' => true,
                                        
                                        'message' => sprintf(__('Step 6/6: ✓ Product attributes and vitals created! Total: %d records', 'ai-eshop-optimizer'), $total_vitals),
                                        'current' => $total_sub_steps,
                                        'total' => $total_sub_steps
                                    ));
                                    break;

                                default:
                                    wp_send_json_error(array('message' => __('Invalid sub-step:', 'ai-eshop-optimizer') . ' ' . $sub_step));
                                    break;
                            }
                        } else {
                            wp_send_json_success(array(
                                'complete' => true,
                                'message' => __('Create attributes skipped', 'ai-eshop-optimizer'),
                                'current' => 0,
                                'total' => 0
                            ));
                        }
                        break;

                    case 'create_needs':
                        if ($settings['create_needs'] == '1') {
                            
                            require_once plugin_dir_path(__FILE__) . 'class-product-needs.php';
                            $needs_handler = AI_eShop_Product_Needs::get_instance();

                            
                            if ($needs_handler->populate_product_needs()) {
                                
                                $count = $wpdb->get_var("
                                    SELECT COUNT(DISTINCT product_id)
                                    FROM {$wpdb->prefix}aieo_core_product_vitals
                                    WHERE primary_need_id IS NOT NULL
                                ");

                                wp_send_json_success(array(
                                    'complete' => true,
                                    
                                    'message' => sprintf(__('✓ Successfully populated needs for %d products', 'ai-eshop-optimizer'), $count),
                                    'current' => $count,
                                    'total' => $count
                                ));
                            } else {
                                wp_send_json_error(array('message' => __('Failed to populate product needs', 'ai-eshop-optimizer')));
                            }
                        } else {
                            wp_send_json_success(array(
                                'complete' => true,
                                'message' => __('Create needs skipped', 'ai-eshop-optimizer'),
                                'current' => 0,
                                'total' => 0
                            ));
                        }
                        break;

                    case 'create_catalogue':
                        if ($settings['create_catalogue'] == '1') {
                            $price_sql_choice = $settings['export_prices'] == '1' ? 1 : 0;
                            $text_sql_choice = $settings['export_product_titles'] == '1' ? 1 : 0;
                            $full_text_sql_choice = 0; 
                            $catalogue_table = get_option('aieo_site_products_table', $wpdb->prefix . 'aieo_temp_product_catalogue');

                            
                            $batch_offset = isset($_POST['batch_offset']) ? intval($_POST['batch_offset']) : 0;
                            $batch_size = 2000; 

                            
                            if ($batch_offset === 0) {
                                $total_vitals = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}aieo_core_product_vitals");
                                set_transient('aieo_catalogue_total', $total_vitals, 3600); 

                                
                                $wpdb->query("TRUNCATE TABLE {$catalogue_table}");
                            } else {
                                $total_vitals = get_transient('aieo_catalogue_total');
                            }

                            
                            $wpdb->query($wpdb->prepare("
                                INSERT INTO {$catalogue_table} (OrderId, OrderStatus, SKU, ParentSKU, ProductId, ParentProductId, CategoryId, TagId, Stock, OnSale, RoleBasedSpecialPricing, CurrentPrice, CurrentRegularPrice, ItemName, ParentItemName, ProfitabilityIndex, VendorId, Vendor, BrandId, Brand, BrandSlug, MenuId,
                                MenuCategory, HeadId, HeadCategory, SubcatId, SubCategory, Weight, Length, Width, Height, Size, Color, ImageUrl, ImageGalleryUrl, ContentIntro, ContentIntroPlain, ProductUrl, ERPId, CategoryName, TagName, Seasonality, ContentCreated, ContentLastUpdated, ProdIdGraphUUID, PPIdGraphUUID)
                                SELECT
                                    0 AS OrderId,
                                    'unsold' AS OrderStatus,
                                    pv.sku AS SKU,
                                    pv.parent_sku AS ParentSKU,
                                    pv.product_id AS ProductId,
                                    pv.parent_product_id AS ParentProductId,
                                    pv.category_ids AS CategoryId,
                                    pv.tag_ids AS TagId,
                                    pv.stock AS Stock,
                                    pv.onsale AS OnSale,
                                    pv.role_special_pricing AS RoleBasedSpecialPricing,
                                    CASE WHEN %d = 0 THEN '' ELSE pv.price END AS CurrentPrice,
                                    CASE WHEN %d = 0 THEN '' ELSE pv.regular_price END AS CurrentRegularPrice,
                                    CASE WHEN %d = 0 THEN '' ELSE pv.product_name END AS ItemName,
                                    CASE WHEN %d = 0 THEN '' ELSE pv.parent_product_name END AS ParentItemName,
                                    '1' AS ProfitabilityIndex,
                                    pv.vendor_id AS VendorId,
                                    CASE WHEN %d = 0 THEN '' ELSE pv.vendor END AS Vendor,
                                    pv.brand_id AS BrandId,
                                    CASE WHEN %d = 0 THEN '' ELSE pv.brand END AS Brand,
                                    CASE WHEN %d = 0 THEN '' ELSE pv.brand_slug END AS BrandSlug,
                                    pv.menu_id AS MenuId,
                                    CASE WHEN %d = 0 THEN '' ELSE pv.menu_category END AS MenuCategory,
                                    pv.head_id AS HeadId,
                                    CASE WHEN %d = 0 THEN '' ELSE pv.head_category END AS HeadCategory,
                                    pv.subcat_id AS SubcatId,
                                    CASE WHEN %d = 0 THEN '' ELSE pv.sub_category END AS SubCategory,
                                    pv.weight AS Weight,
                                    pv.length AS Length,
                                    pv.width AS Width,
                                    pv.height AS Height,
                                    pv.size AS Size,
                                    pv.color AS Color,
                                    pv.image_url AS ImageUrl,
                                    pv.image_gallery_urls AS ImageGalleryUrl,
                                    CASE WHEN %d = 0 THEN '' ELSE pv.product_description END AS ContentIntro,
                                    CASE WHEN %d = 0 THEN '' ELSE pv.product_description END AS ContentIntroPlain,
                                    pv.product_url AS ProductUrl,
                                    pv.erp_id AS ERPId,
                                    CASE WHEN %d = 0 THEN '' ELSE pv.category_names END AS CategoryName,
                                    CASE WHEN %d = 0 THEN '' ELSE pv.tag_names END AS TagName,
                                    '0' AS Seasonality,
                                    pv.content_created AS ContentCreated,
                                    pv.content_last_updated AS ContentLastUpdated,
                                    pv.ProdIdGraphUUID AS ProdIdGraphUUID,
                                    pvp.PPIdGraphUUID AS PPIdGraphUUID
                                FROM {$wpdb->prefix}aieo_core_product_vitals pv
                                INNER JOIN {$wpdb->prefix}aieo_core_product_vitals pvp ON pv.parent_product_id = pvp.product_id
                                LIMIT %d OFFSET %d
                            ",
                            $price_sql_choice, $price_sql_choice, 
                            $text_sql_choice, $text_sql_choice,   
                            $text_sql_choice, $text_sql_choice, $text_sql_choice, 
                            $text_sql_choice, $text_sql_choice, $text_sql_choice, 
                            $text_sql_choice, $text_sql_choice, 
                            $text_sql_choice, $text_sql_choice, 
                            $batch_size, $batch_offset));

                            if ($wpdb->last_error) {
                                wp_send_json_error(array(
                                    'message' => __('Catalogue creation failed:', 'ai-eshop-optimizer') . ' ' . $wpdb->last_error
                                ));
                                return;
                            }

                            
                            $count_total = $wpdb->get_var("SELECT COUNT(*) FROM {$catalogue_table}");

                            
                            if ($count_total >= $total_vitals || $batch_offset + $batch_size >= $total_vitals) {
                                
                                $count_parents = $wpdb->get_var("SELECT COUNT(*) FROM {$catalogue_table} WHERE ParentProductId = ProductId");
                                $count_variations = $wpdb->get_var("SELECT COUNT(*) FROM {$catalogue_table} WHERE ParentProductId != ProductId");

                                delete_transient('aieo_catalogue_total');

                                wp_send_json_success(array(
                                    'complete' => true,
                                    
                                    'message' => sprintf(__('✓ Product Catalogue: %1$d total (%2$d parents, %3$d variations)', 'ai-eshop-optimizer'), $count_total, $count_parents, $count_variations),
                                    'current' => $count_total,
                                    'total' => $total_vitals
                                ));
                            } else {
                                
                                wp_send_json_success(array(
                                    'complete' => false,
                                    
                                    'message' => sprintf(__('Processing catalogue: %1$d of %2$d products...', 'ai-eshop-optimizer'), $count_total, $total_vitals),
                                    'current' => $count_total,
                                    'total' => $total_vitals,
                                    'batch_offset' => $batch_offset + $batch_size
                                ));
                            }
                        } else {
                            wp_send_json_success(array(
                                'complete' => true,
                                'message' => __('Create catalogue skipped', 'ai-eshop-optimizer'),
                                'current' => 0,
                                'total' => 0
                            ));
                        }
                        break;

                    case 'process_eshop_orders':
                        if ($settings['process_eshop_orders'] == '1') {
                            $progress_step = isset($_POST['progress_step']) ? intval($_POST['progress_step']) : 0;
                            $temp_orders_table = get_option('aieo_site_orders_table', $wpdb->prefix . 'aieo_temp_orders');

                            
                            if ($progress_step === 0) {
                                
                                $is_hpos = class_exists('Automattic\WooCommerce\Utilities\OrderUtil') &&
                                    \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled();

                                if ($is_hpos) {
                                    $total_orders = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}wc_orders WHERE type = 'shop_order' AND status IN ('wc-processing', 'wc-completed')");
                                } else {
                                    $total_orders = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}posts WHERE post_type = 'shop_order' AND post_status IN ('wc-processing', 'wc-completed')");
                                }

                                set_transient('aieo_orders_total', $total_orders, 3600);
                                set_transient('aieo_orders_hpos', $is_hpos ? 1 : 0, 3600);

                                
                                $wpdb->query("TRUNCATE TABLE {$temp_orders_table}");

                                wp_send_json_success(array(
                                    'complete' => false,
                                    
                                    'message' => sprintf(__('Processing %1$s orders: 0 of %2$d orders...', 'ai-eshop-optimizer'), ($is_hpos ? __('HPOS', 'ai-eshop-optimizer') : __('Legacy', 'ai-eshop-optimizer')), $total_orders),
                                    'current' => 0,
                                    'total' => $total_orders,
                                    'progress_step' => 1
                                ));
                            }
                            
                            else if ($progress_step === 1) {
                                $total_orders = get_transient('aieo_orders_total');
                                $is_hpos = get_transient('aieo_orders_hpos');

                                $price_sql_choice = $settings['export_prices'] == '1' ? 1 : 0;
                                $text_sql_choice = $settings['export_product_titles'] == '1' ? 1 : 0;
                                $full_text_sql_choice = 0;
                                $eponymous_sql_choice = $settings['export_customer_ids'] == '1' ? 1 : 0;
                                $seasonality_sql_choice = $settings['seasonal_option'] == '1' ? 1 : 0;
                                $order_id = get_option('aieo_order_id', 0);
                                $max_records = get_option('aieo_max_records', 999999);

                                
                                @set_time_limit(300); 

                                if ($is_hpos) {
                                    
                                    $wpdb->query($wpdb->prepare(
                                        "CALL `{$site_prefix}AIEO_Export_Orders_HPOS` (%d, %d, %d, %d, %d, %d, %d)",
                                        $price_sql_choice,
                                        $text_sql_choice,
                                        $full_text_sql_choice,
                                        $eponymous_sql_choice,
                                        $seasonality_sql_choice,
                                        $order_id,
                                        $max_records
                                    ));
                                } else {
                                    
                                    $wpdb->query($wpdb->prepare(
                                        "CALL `{$site_prefix}AIEO_Export_Orders_non_HPOS` (%d, %d, %d, %d, %d, %d, %d)",
                                        $price_sql_choice,
                                        $text_sql_choice,
                                        $full_text_sql_choice,
                                        $eponymous_sql_choice,
                                        $seasonality_sql_choice,
                                        $order_id,
                                        $max_records
                                    ));
                                }

                                
                                if ($wpdb->last_error) {
                                    delete_transient('aieo_orders_total');
                                    delete_transient('aieo_orders_hpos');
                                    wp_send_json_error(array(
                                        'message' => __('Order processing failed:', 'ai-eshop-optimizer') . ' ' . $wpdb->last_error
                                    ));
                                    return;
                                }

                                $count_total = $wpdb->get_var("SELECT COUNT(*) FROM {$temp_orders_table}");
                                $count_orders = $wpdb->get_var("SELECT COUNT(DISTINCT OrderId) FROM {$temp_orders_table}");
                                $count_products = $wpdb->get_var("SELECT COUNT(DISTINCT ProductId) FROM {$temp_orders_table}");

                                delete_transient('aieo_orders_total');
                                delete_transient('aieo_orders_hpos');

                                $hpos_status = $is_hpos ? __('HPOS', 'ai-eshop-optimizer') : __('Legacy', 'ai-eshop-optimizer');

                                wp_send_json_success(array(
                                    'complete' => true,
                                    
                                    'message' => sprintf(__('✓ Eshop Orders (%1$s): %2$d order items from %3$d orders (%4$d unique products)', 'ai-eshop-optimizer'), $hpos_status, $count_total, $count_orders, $count_products),
                                    'current' => $count_total,
                                    'total' => $count_total
                                ));
                            }
                        } else {
                            wp_send_json_success(array(
                                'complete' => true,
                                'message' => __('Process eshop orders skipped', 'ai-eshop-optimizer'),
                                'current' => 0,
                                'total' => 0
                            ));
                        }
                        break;

                    case 'process_instore_orders':
                        if ($settings['process_instore_orders'] == '1') {
                            
                            $table_exists = $wpdb->get_var("SHOW TABLES LIKE '{$wpdb->prefix}s1erp_orders'");

                            if ($table_exists) {
                                $price_sql_choice = $settings['export_prices'] == '1' ? 1 : 0;
                                $eponymous_sql_choice = $settings['export_customer_ids'] == '1' ? 1 : 0;
                                $seasonality_sql_choice = $settings['seasonal_option'] == '1' ? 1 : 0;
                                $season_days_past = get_option('aieo_season_days_past', 15);
                                $season_days_after = get_option('aieo_season_days_after', 60);

                                $instore_invoices_list = get_option('aieo_erp_series_to_ignore', '');
                                $instore_invoices_list_sql_choice = !empty($instore_invoices_list) ? 1 : 0;

                                $instore_anonymous_sql_choice = get_option('aieo_instore_anonymous', 0);
                                $instore_anonymous_list = get_option('aieo_erp_store_anonymous_invoice_users', '');

                                $wpdb->query($wpdb->prepare(
                                    "CALL `{$site_prefix}AIEO_Export_Store_Orders` (%d, %d, %d, %d, %d, %d, %s, %d, %s)",
                                    $price_sql_choice,
                                    $eponymous_sql_choice,
                                    $seasonality_sql_choice,
                                    $season_days_past,
                                    $season_days_after,
                                    $instore_invoices_list_sql_choice,
                                    $instore_invoices_list,
                                    $instore_anonymous_sql_choice,
                                    $instore_anonymous_list
                                ));

                                $store_orders_table = get_option('aieo_store_orders_table', $wpdb->prefix . 'aieo_temp_store_orders');
                                $count_total = $wpdb->get_var("SELECT COUNT(*) FROM {$store_orders_table}");
                                $count_orders = $wpdb->get_var("SELECT COUNT(DISTINCT OrderId) FROM {$store_orders_table}");
                                $count_products = $wpdb->get_var("SELECT COUNT(DISTINCT ProductId) FROM {$store_orders_table}");

                                wp_send_json_success(array(
                                    'complete' => true,
                                    
                                    'message' => sprintf(__('✓ In-Store Orders: %1$d order items from %2$d invoices (%3$d unique products)', 'ai-eshop-optimizer'), $count_total, $count_orders, $count_products),
                                    'current' => $count_total,
                                    'total' => $count_total
                                ));
                            } else {
                                wp_send_json_success(array(
                                    'complete' => true,
                                    'message' => __('In-store orders skipped (meta-connector not active)', 'ai-eshop-optimizer'),
                                    'current' => 0,
                                    'total' => 0
                                ));
                            }
                        } else {
                            wp_send_json_success(array(
                                'complete' => true,
                                'message' => __('Process in-store orders skipped', 'ai-eshop-optimizer'),
                                'current' => 0,
                                'total' => 0
                            ));
                        }
                        break;

                    case 'merge_orders':
                        if ($settings['merge_orders'] == '1') {
                            $store_orders_table_name = get_option('aieo_store_orders_table', $wpdb->prefix . 'aieo_temp_store_orders');
                            $temp_orders_table_name = get_option('aieo_site_orders_table', $wpdb->prefix . 'aieo_temp_orders');
                            $analytics_eponymous_id_field = get_option('aieo_analytics_eponymous_id_field', 'customer_id');

                            $instore_product_threshold = get_option('aieo_erp_product_price_to_ignore', '');
                            $instore_product_threshold_sql_choice = !empty($instore_product_threshold) ? 1 : 0;

                            $instore_products_list = get_option('aieo_erp_products_to_ignore', '');
                            $instore_products_list_sql_choice = !empty($instore_products_list) ? 1 : 0;

                            $wpdb->query($wpdb->prepare(
                                "CALL `{$site_prefix}AIEO_Merge_Store_Orders` (%s, %s, %s, %d, %s, %d, %s)",
                                $store_orders_table_name,
                                $temp_orders_table_name,
                                $analytics_eponymous_id_field,
                                $instore_product_threshold_sql_choice,
                                $instore_product_threshold,
                                $instore_products_list_sql_choice,
                                $instore_products_list
                            ));

                            $count_total = $wpdb->get_var("SELECT COUNT(*) FROM {$temp_orders_table_name}");
                            $count_eshop = $wpdb->get_var("SELECT COUNT(*) FROM {$temp_orders_table_name} WHERE OrderId > 0");
                            $count_store = $wpdb->get_var("SELECT COUNT(*) FROM {$temp_orders_table_name} WHERE OrderId < 0");
                            $count_orders = $wpdb->get_var("SELECT COUNT(DISTINCT OrderId) FROM {$temp_orders_table_name}");

                            wp_send_json_success(array(
                                'complete' => true,
                                
                                'message' => sprintf(__('✓ Orders Merged: %1$d total items (%2$d eshop + %3$d in-store) from %4$d orders', 'ai-eshop-optimizer'), $count_total, $count_eshop, $count_store, $count_orders),
                                'current' => $count_total,
                                'total' => $count_total
                            ));
                        } else {
                            wp_send_json_success(array(
                                'complete' => true,
                                'message' => __('Merge orders skipped', 'ai-eshop-optimizer'),
                                'current' => 0,
                                'total' => 0
                            ));
                        }
                        break;

                    case 'include_unsold':
                        if ($settings['include_unsold'] == '1') {
                            $temp_orders_table = $wpdb->prefix . 'aieo_temp_orders';
                            $catalogue_table = get_option('aieo_site_products_table', $wpdb->prefix . 'aieo_temp_product_catalogue');
                            $progress_step = isset($_POST['progress_step']) ? intval($_POST['progress_step']) : 0;

                            
                            if ($progress_step === 0) {
                                $count_orders = $wpdb->get_var("SELECT COUNT(*) FROM {$temp_orders_table}");
                                $count_catalogue = $wpdb->get_var("SELECT COUNT(*) FROM {$catalogue_table}");

                                if ($count_orders == 0) {
                                    wp_send_json_error(array('message' => __('Orders table is empty. Cannot include unsold products.', 'ai-eshop-optimizer')));
                                    return;
                                }

                                set_transient('aieo_unsold_count_before', $count_orders, 3600);
                                set_transient('aieo_unsold_start_time', time(), 3600);

                                wp_send_json_success(array(
                                    'complete' => false,
                                    
                                    'message' => sprintf(__('Analyzing %d products to find unsold items...', 'ai-eshop-optimizer'), $count_catalogue),
                                    'current' => 0,
                                    'total' => 100,
                                    'progress_step' => 1
                                ));
                            }
                            
                            else if ($progress_step === 1) {
                                $start_time = get_transient('aieo_unsold_start_time');
                                $elapsed = time() - $start_time;

                                
                                
                                $result = $wpdb->query("
                                    INSERT INTO {$temp_orders_table}
                                    (OrderStatus, SKU, ProductId, ParentProductId, CategoryId, TagId,
                                     CurrentPrice, CurrentRegularPrice, Stock, ItemName, ParentItemName,
                                     Brand, CategoryName, TagName, ContentIntro, ContentIntroPlain,
                                     ContentCreated, ContentLastUpdated, PPIdGraphUUID, ProdIdGraphUUID)
                                    SELECT
                                        st.OrderStatus, st.SKU, st.ProductId, st.ParentProductId, st.CategoryId, st.TagId,
                                        st.CurrentPrice, st.CurrentRegularPrice, st.Stock, st.ItemName, st.ParentItemName,
                                        st.Brand, st.CategoryName, st.TagName, st.ContentIntro, st.ContentIntroPlain,
                                        st.ContentCreated, st.ContentLastUpdated, st.PPIdGraphUUID, st.ProdIdGraphUUID
                                    FROM {$catalogue_table} st
                                    LEFT JOIN {$temp_orders_table} atot ON atot.ProductId = st.ProductId
                                    WHERE atot.ProductId IS NULL
                                ");

                                if ($wpdb->last_error) {
                                    delete_transient('aieo_unsold_count_before');
                                    delete_transient('aieo_unsold_start_time');
                                    wp_send_json_error(array('message' => __('Error inserting unsold products:', 'ai-eshop-optimizer') . ' ' . $wpdb->last_error));
                                    return;
                                }

                                $unsold_added = $wpdb->rows_affected;

                                wp_send_json_success(array(
                                    'complete' => false,
                                    
                                    'message' => sprintf(__('Added %1$d unsold products. Updating UUIDs... (%2$ds elapsed, 50%% complete)', 'ai-eshop-optimizer'), $unsold_added, $elapsed),
                                    'current' => 50,
                                    'total' => 100,
                                    'progress_step' => 2
                                ));
                            }
                            
                            else if ($progress_step === 2) {
                                $start_time = get_transient('aieo_unsold_start_time');
                                $elapsed = time() - $start_time;

                                
                                $result = $wpdb->query("
                                    UPDATE {$temp_orders_table} atot
                                    INNER JOIN {$catalogue_table} st ON atot.ProductId = st.ProductId
                                    SET
                                        atot.PPIdGraphUUID = st.PPIdGraphUUID,
                                        atot.ProdIdGraphUUID = st.ProdIdGraphUUID
                                    WHERE atot.PPIdGraphUUID IS NULL OR atot.ProdIdGraphUUID IS NULL
                                ");

                                if ($wpdb->last_error) {
                                    delete_transient('aieo_unsold_count_before');
                                    delete_transient('aieo_unsold_start_time');
                                    wp_send_json_error(array('message' => __('Error updating UUIDs:', 'ai-eshop-optimizer') . ' ' . $wpdb->last_error));
                                    return;
                                }

                                $uuids_updated = $wpdb->rows_affected;

                                
                                $count_before = get_transient('aieo_unsold_count_before');
                                $count_after = $wpdb->get_var("SELECT COUNT(*) FROM {$temp_orders_table}");
                                $unsold_added = $count_after - $count_before;

                                
                                delete_transient('aieo_unsold_count_before');
                                delete_transient('aieo_unsold_start_time');

                                
                                $this->aieo_ensure_mysql_completion();

                                wp_send_json_success(array(
                                    'complete' => true,
                                    
                                    'message' => sprintf(__('✓ Unsold products included: Added %1$d unsold products after examining %2$d sold product line items (Total: %3$d records, %4$d UUIDs updated, %5$ds elapsed)', 'ai-eshop-optimizer'), $unsold_added, $count_before, $count_after, $uuids_updated, $elapsed),
                                    'current' => $count_after,
                                    'total' => $count_after
                                ));
                            }
                        } else {
                            wp_send_json_success(array(
                                'complete' => true,
                                'message' => __('Include unsold skipped', 'ai-eshop-optimizer'),
                                'current' => 0,
                                'total' => 0
                            ));
                        }
                        break;

                    case 'aggregate_product_stats':
                        if ($settings['aggregate_product_stats'] == '1') {
                            $temp_orders_table_name = get_option('aieo_site_orders_table', $wpdb->prefix . 'aieo_temp_orders');
                            $progress_step = isset($_POST['progress_step']) ? intval($_POST['progress_step']) : 0;
                            $stats_temp_table = $wpdb->prefix . 'aieo_product_stats_temp';

                            
                            if ($progress_step === 0) {
                                
                                $stats_lock = get_transient('aieo_product_stats_lock');
                                if ($stats_lock && $stats_lock !== $export_id) {
                                    wp_send_json_error(array(
                                        'message' => __('Product statistics are already being calculated by another process.', 'ai-eshop-optimizer')
                                    ));
                                    return;
                                }
                                set_transient('aieo_product_stats_lock', $export_id, 300);
                                self::aieo_register_export_lock_shutdown('aieo_product_stats_lock', $export_id);

                                
                                $total_products = $wpdb->get_var("SELECT COUNT(DISTINCT ParentProductId) FROM {$temp_orders_table_name} WHERE ParentProductId IS NOT NULL");
                                set_transient('aieo_product_stats_total', $total_products, 3600);
                                set_transient('aieo_product_stats_start_time', time(), 3600);

                                wp_send_json_success(array(
                                    'complete' => false,
                                    
                                    'message' => sprintf(__('Initializing product statistics for %d products...', 'ai-eshop-optimizer'), $total_products),
                                    'current' => 0,
                                    'total' => 100,
                                    'progress_step' => 1
                                ));
                            }
                            
                            else if ($progress_step === 1) {
                                $start_time = get_transient('aieo_product_stats_start_time');
                                $elapsed = time() - $start_time;

                                
                                $wpdb->query("DROP TABLE IF EXISTS {$stats_temp_table}");

                                
                                
                                $result = $wpdb->query("
                                    CREATE TABLE {$stats_temp_table} AS
                                    SELECT
                                        ParentProductId,
                                        SUM(PrimaryQty) AS TotalItemSales,
                                        COUNT(DISTINCT OrderId) AS DistinctOrderSales,
                                        SUM(PrimaryQty * Price) AS TotalTurnover,
                                        SUM(CASE WHEN ItemSequence = 1 AND OrderSize = 1 THEN 1 ELSE 0 END) AS UniqueItemSales,
                                        SUM(CASE WHEN ItemSequence = 1 THEN 1 ELSE 0 END) AS FirstItemSales,
                                        SUM(CASE WHEN ItemSequence = OrderSize THEN 1 ELSE 0 END) AS LastItemSales,
                                        AVG(JourneyLinearWeight) AS AvgJLWValue,
                                        AVG(ValueLinearWeight) AS AvgVLWValue
                                    FROM {$temp_orders_table_name}
                                    WHERE ParentProductId IS NOT NULL
                                    AND (OriginId <> 2 OR LoyaltyID IS NOT NULL)
                                    GROUP BY ParentProductId
                                ");

                                if ($wpdb->last_error) {
                                    $wpdb->query("DROP TABLE IF EXISTS {$stats_temp_table}");
                                    delete_transient('aieo_product_stats_total');
                                    delete_transient('aieo_product_stats_start_time');
                                    delete_transient('aieo_product_stats_lock');
                                    wp_send_json_error(array(
                                        'message' => __('Product statistics aggregation failed:', 'ai-eshop-optimizer') . ' ' . $wpdb->last_error
                                    ));
                                    return;
                                }

                                
                                $wpdb->query("ALTER TABLE {$stats_temp_table} ADD INDEX idx_parent_product (ParentProductId)");

                                wp_send_json_success(array(
                                    'complete' => false,
                                    
                                    'message' => sprintf(__('Aggregated statistics for all products. Applying to orders table... (%ds elapsed, 50%% complete)', 'ai-eshop-optimizer'), $elapsed),
                                    'current' => 50,
                                    'total' => 100,
                                    'progress_step' => 2
                                ));
                            }
                            
                            else if ($progress_step === 2) {
                                $total_products = get_transient('aieo_product_stats_total');
                                $start_time = get_transient('aieo_product_stats_start_time');
                                $elapsed = time() - $start_time;

                                
                                $wpdb->query("
                                    UPDATE {$temp_orders_table_name} AS t1
                                    INNER JOIN {$stats_temp_table} AS t2 ON t1.ParentProductId = t2.ParentProductId
                                    SET
                                        t1.TotalItemSales = t2.TotalItemSales,
                                        t1.DistinctOrderSales = t2.DistinctOrderSales,
                                        t1.TotalTurnover = t2.TotalTurnover,
                                        t1.UniqueItemSales = t2.UniqueItemSales,
                                        t1.FirstItemSales = t2.FirstItemSales,
                                        t1.LastItemSales = t2.LastItemSales,
                                        t1.AvgJLW = t2.AvgJLWValue,
                                        t1.AvgVLW = t2.AvgVLWValue
                                ");

                                if ($wpdb->last_error) {
                                    $wpdb->query("DROP TABLE IF EXISTS {$stats_temp_table}");
                                    delete_transient('aieo_product_stats_total');
                                    delete_transient('aieo_product_stats_start_time');
                                    delete_transient('aieo_product_stats_lock');
                                    wp_send_json_error(array(
                                        'message' => __('Product statistics update failed:', 'ai-eshop-optimizer') . ' ' . $wpdb->last_error
                                    ));
                                    return;
                                }

                                
                                $wpdb->query("DROP TABLE IF EXISTS {$stats_temp_table}");

                                
                                $count_with_stats = $wpdb->get_var("SELECT COUNT(DISTINCT ParentProductId) FROM {$temp_orders_table_name} WHERE TotalItemSales IS NOT NULL AND TotalItemSales > 0");

                                delete_transient('aieo_product_stats_total');
                                delete_transient('aieo_product_stats_start_time');
                                delete_transient('aieo_product_stats_lock');

                                
                                $this->aieo_ensure_mysql_completion();

                                wp_send_json_success(array(
                                    'complete' => true,
                                    
                                    'message' => sprintf(__('✓ Product statistics: %1$d products with sales data (out of %2$d total products, completed in %3$ds)', 'ai-eshop-optimizer'), $count_with_stats, $total_products, $elapsed),
                                    'current' => $total_products,
                                    'total' => $total_products
                                ));
                            }
                        } else {
                            wp_send_json_success(array(
                                'complete' => true,
                                'message' => __('Aggregate product stats skipped', 'ai-eshop-optimizer'),
                                'current' => 0,
                                'total' => 0
                            ));
                        }
                        break;

                    case 'aggregate_category_brand_stats':
                        if ($settings['aggregate_category_brand_stats'] == '1') {
                            $temp_orders_table_name = get_option('aieo_site_orders_table', $wpdb->prefix . 'aieo_temp_orders');
                            $popularity_table = get_option('aieo_core_category_brand_popularity_table', $wpdb->prefix . 'aieo_core_category_brand_popularity');
                            $progress_step = isset($_POST['progress_step']) ? intval($_POST['progress_step']) : 0;

                            
                            $sales_period = get_option('aieo_category_sales_period', 'all_time');
                            $date_filter = '';
                            $period_label = __('All time', 'ai-eshop-optimizer');

                            switch ($sales_period) {
                                case 'last_30_days':
                                    $date_filter = " AND t.OrderDate >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)";
                                    $period_label = __('Last 30 days', 'ai-eshop-optimizer');
                                    break;
                                case 'last_3_months':
                                    $date_filter = " AND t.OrderDate >= DATE_SUB(CURDATE(), INTERVAL 3 MONTH)";
                                    $period_label = __('Last 3 months', 'ai-eshop-optimizer');
                                    break;
                                case 'last_6_months':
                                    $date_filter = " AND t.OrderDate >= DATE_SUB(CURDATE(), INTERVAL 6 MONTH)";
                                    $period_label = __('Last 6 months', 'ai-eshop-optimizer');
                                    break;
                                case 'last_12_months':
                                    $date_filter = " AND t.OrderDate >= DATE_SUB(CURDATE(), INTERVAL 12 MONTH)";
                                    $period_label = __('Last 12 months', 'ai-eshop-optimizer');
                                    break;
                                default: 
                                    $date_filter = '';
                                    break;
                            }

                            
                            if ($progress_step === 0) {
                                
                                $stats_lock = get_transient('aieo_category_brand_stats_lock');
                                if ($stats_lock && $stats_lock !== $export_id) {
                                    wp_send_json_error(array(
                                        'message' => __('Category/brand statistics are already being calculated by another process.', 'ai-eshop-optimizer')
                                    ));
                                    return;
                                }
                                set_transient('aieo_category_brand_stats_lock', $export_id, 300);
                                self::aieo_register_export_lock_shutdown('aieo_category_brand_stats_lock', $export_id);
                                set_transient('aieo_category_brand_stats_start_time', time(), 3600);

                                
                                $wpdb->query("TRUNCATE TABLE {$popularity_table}");

                                wp_send_json_success(array(
                                    'complete' => false,
                                    
                                    'message' => sprintf(__('Initializing category/brand popularity analysis (%s)...', 'ai-eshop-optimizer'), $period_label),
                                    'current' => 0,
                                    'total' => 100,
                                    'progress_step' => 1
                                ));
                            }
                            
                            else if ($progress_step === 1) {
                                $start_time = get_transient('aieo_category_brand_stats_start_time');
                                $elapsed = time() - $start_time;

                                
                                
                                

                                
                                $wpdb->query("
                                    INSERT INTO {$popularity_table}
                                    (category_id, category_name, category_slug, category_level, parent_category_id, brand_id, total_sales, total_turnover, total_orders, product_count)
                                    SELECT
                                        t.MenuId as category_id,
                                        MAX(t.MenuCategory) as category_name,
                                        NULL as category_slug,
                                        1 as category_level,
                                        NULL as parent_category_id,
                                        NULL as brand_id,
                                        COALESCE(SUM(t.PrimaryQty), 0) as total_sales,
                                        COALESCE(SUM(t.PrimaryQty * t.Price), 0) as total_turnover,
                                        COUNT(DISTINCT t.OrderId) as total_orders,
                                        COUNT(DISTINCT t.ParentProductId) as product_count
                                    FROM {$temp_orders_table_name} t
                                    WHERE t.MenuId IS NOT NULL{$date_filter}
                                    GROUP BY t.MenuId
                                ");

                                
                                $wpdb->query("
                                    INSERT INTO {$popularity_table}
                                    (category_id, category_name, category_slug, category_level, parent_category_id, brand_id, total_sales, total_turnover, total_orders, product_count)
                                    SELECT
                                        t.HeadId as category_id,
                                        MAX(t.HeadCategory) as category_name,
                                        NULL as category_slug,
                                        2 as category_level,
                                        MAX(t.MenuId) as parent_category_id,
                                        NULL as brand_id,
                                        COALESCE(SUM(t.PrimaryQty), 0) as total_sales,
                                        COALESCE(SUM(t.PrimaryQty * t.Price), 0) as total_turnover,
                                        COUNT(DISTINCT t.OrderId) as total_orders,
                                        COUNT(DISTINCT t.ParentProductId) as product_count
                                    FROM {$temp_orders_table_name} t
                                    WHERE t.HeadId IS NOT NULL{$date_filter}
                                    GROUP BY t.HeadId
                                ");

                                
                                $wpdb->query("
                                    INSERT INTO {$popularity_table}
                                    (category_id, category_name, category_slug, category_level, parent_category_id, brand_id, total_sales, total_turnover, total_orders, product_count)
                                    SELECT
                                        t.SubcatId as category_id,
                                        MAX(t.SubCategory) as category_name,
                                        NULL as category_slug,
                                        3 as category_level,
                                        MAX(t.HeadId) as parent_category_id,
                                        NULL as brand_id,
                                        COALESCE(SUM(t.PrimaryQty), 0) as total_sales,
                                        COALESCE(SUM(t.PrimaryQty * t.Price), 0) as total_turnover,
                                        COUNT(DISTINCT t.OrderId) as total_orders,
                                        COUNT(DISTINCT t.ParentProductId) as product_count
                                    FROM {$temp_orders_table_name} t
                                    WHERE t.SubcatId IS NOT NULL{$date_filter}
                                    GROUP BY t.SubcatId
                                ");

                                if ($wpdb->last_error) {
                                    delete_transient('aieo_category_brand_stats_start_time');
                                    delete_transient('aieo_category_brand_stats_lock');
                                    wp_send_json_error(array(
                                        'message' => __('Category statistics aggregation failed:', 'ai-eshop-optimizer') . ' ' . $wpdb->last_error
                                    ));
                                    return;
                                }

                                $category_count = $wpdb->get_var("SELECT COUNT(*) FROM {$popularity_table} WHERE brand_id IS NULL");

                                wp_send_json_success(array(
                                    'complete' => false,
                                    
                                    'message' => sprintf(__('Aggregated %d categories. Now processing brands...', 'ai-eshop-optimizer'), $category_count) . " ({$elapsed}s)",
                                    'current' => 25,
                                    'total' => 100,
                                    'progress_step' => 2
                                ));
                            }
                            
                            else if ($progress_step === 2) {
                                $start_time = get_transient('aieo_category_brand_stats_start_time');
                                $elapsed = time() - $start_time;

                                
                                
                                $wpdb->query("
                                    INSERT INTO {$popularity_table}
                                    (category_id, brand_id, brand_name, brand_slug, total_sales, total_turnover, total_orders, product_count)
                                    SELECT
                                        NULL as category_id,
                                        t.BrandId as brand_id,
                                        MAX(t.Brand) as brand_name,
                                        MAX(t.BrandSlug) as brand_slug,
                                        COALESCE(SUM(t.PrimaryQty), 0) as total_sales,
                                        COALESCE(SUM(t.PrimaryQty * t.Price), 0) as total_turnover,
                                        COUNT(DISTINCT t.OrderId) as total_orders,
                                        COUNT(DISTINCT t.ParentProductId) as product_count
                                    FROM {$temp_orders_table_name} t
                                    WHERE t.BrandId IS NOT NULL{$date_filter}
                                    GROUP BY t.BrandId
                                ");

                                if ($wpdb->last_error) {
                                    delete_transient('aieo_category_brand_stats_start_time');
                                    delete_transient('aieo_category_brand_stats_lock');
                                    wp_send_json_error(array(
                                        'message' => __('Brand statistics aggregation failed:', 'ai-eshop-optimizer') . ' ' . $wpdb->last_error
                                    ));
                                    return;
                                }

                                $brand_count = $wpdb->get_var("SELECT COUNT(*) FROM {$popularity_table} WHERE category_id IS NULL AND brand_id IS NOT NULL");

                                wp_send_json_success(array(
                                    'complete' => false,
                                    
                                    'message' => sprintf(__('Aggregated %d brands. Now processing category+brand combinations...', 'ai-eshop-optimizer'), $brand_count) . " ({$elapsed}s)",
                                    'current' => 50,
                                    'total' => 100,
                                    'progress_step' => 3
                                ));
                            }
                            
                            else if ($progress_step === 3) {
                                $start_time = get_transient('aieo_category_brand_stats_start_time');
                                $elapsed = time() - $start_time;

                                
                                
                                $wpdb->query("
                                    INSERT INTO {$popularity_table}
                                    (category_id, category_name, category_level, parent_category_id, brand_id, brand_name, brand_slug, total_sales, total_turnover, total_orders, product_count)
                                    SELECT
                                        t.SubcatId as category_id,
                                        MAX(t.SubCategory) as category_name,
                                        3 as category_level,
                                        MAX(t.HeadId) as parent_category_id,
                                        t.BrandId as brand_id,
                                        MAX(t.Brand) as brand_name,
                                        MAX(t.BrandSlug) as brand_slug,
                                        COALESCE(SUM(t.PrimaryQty), 0) as total_sales,
                                        COALESCE(SUM(t.PrimaryQty * t.Price), 0) as total_turnover,
                                        COUNT(DISTINCT t.OrderId) as total_orders,
                                        COUNT(DISTINCT t.ParentProductId) as product_count
                                    FROM {$temp_orders_table_name} t
                                    WHERE t.SubcatId IS NOT NULL AND t.BrandId IS NOT NULL{$date_filter}
                                    GROUP BY t.SubcatId, t.BrandId
                                ");

                                if ($wpdb->last_error) {
                                    delete_transient('aieo_category_brand_stats_start_time');
                                    delete_transient('aieo_category_brand_stats_lock');
                                    wp_send_json_error(array(
                                        'message' => __('Category+brand combination aggregation failed:', 'ai-eshop-optimizer') . ' ' . $wpdb->last_error
                                    ));
                                    return;
                                }

                                $combo_count = $wpdb->get_var("SELECT COUNT(*) FROM {$popularity_table} WHERE category_id IS NOT NULL AND brand_id IS NOT NULL");

                                wp_send_json_success(array(
                                    'complete' => false,
                                    
                                    'message' => sprintf(__('Aggregated %d category+brand combinations. Now calculating rankings...', 'ai-eshop-optimizer'), $combo_count) . " ({$elapsed}s)",
                                    'current' => 75,
                                    'total' => 100,
                                    'progress_step' => 4
                                ));
                            }
                            
                            else if ($progress_step === 4) {
                                $start_time = get_transient('aieo_category_brand_stats_start_time');
                                $elapsed = time() - $start_time;

                                
                                $mysql_version = $wpdb->get_var("SELECT VERSION()");
                                $supports_window_functions = false;

                                
                                if (stripos($mysql_version, 'mariadb') !== false) {
                                    
                                    if (preg_match('/(\d+\.\d+)/', $mysql_version, $matches)) {
                                        $supports_window_functions = version_compare($matches[1], '10.2', '>=');
                                    }
                                } else {
                                    
                                    if (preg_match('/^(\d+\.\d+)/', $mysql_version, $matches)) {
                                        $supports_window_functions = version_compare($matches[1], '8.0', '>=');
                                    }
                                }

                                if ($supports_window_functions) {
                                    

                                    
                                    $wpdb->query("
                                        UPDATE {$popularity_table} p
                                        INNER JOIN (
                                            SELECT id,
                                                RANK() OVER (PARTITION BY category_level ORDER BY total_sales DESC) as rank_sales,
                                                RANK() OVER (PARTITION BY category_level ORDER BY total_turnover DESC) as rank_turnover
                                            FROM {$popularity_table}
                                            WHERE brand_id IS NULL AND category_id IS NOT NULL
                                        ) r ON p.id = r.id
                                        SET p.category_rank_by_sales = r.rank_sales,
                                            p.category_rank_by_turnover = r.rank_turnover
                                    ");

                                    
                                    $wpdb->query("
                                        UPDATE {$popularity_table} p
                                        INNER JOIN (
                                            SELECT id,
                                                RANK() OVER (PARTITION BY parent_category_id ORDER BY total_sales DESC) as rank_sales,
                                                RANK() OVER (PARTITION BY parent_category_id ORDER BY total_turnover DESC) as rank_turnover
                                            FROM {$popularity_table}
                                            WHERE brand_id IS NULL AND parent_category_id IS NOT NULL
                                        ) r ON p.id = r.id
                                        SET p.subcategory_rank_in_parent_sales = r.rank_sales,
                                            p.subcategory_rank_in_parent_turnover = r.rank_turnover
                                    ");

                                    
                                    $wpdb->query("
                                        UPDATE {$popularity_table} p
                                        INNER JOIN (
                                            SELECT id,
                                                RANK() OVER (ORDER BY total_sales DESC) as rank_sales,
                                                RANK() OVER (ORDER BY total_turnover DESC) as rank_turnover
                                            FROM {$popularity_table}
                                            WHERE category_id IS NULL AND brand_id IS NOT NULL
                                        ) r ON p.id = r.id
                                        SET p.brand_rank_by_sales = r.rank_sales,
                                            p.brand_rank_by_turnover = r.rank_turnover
                                    ");

                                    
                                    $wpdb->query("
                                        UPDATE {$popularity_table} p
                                        INNER JOIN (
                                            SELECT id,
                                                RANK() OVER (PARTITION BY category_id ORDER BY total_sales DESC) as rank_sales,
                                                RANK() OVER (PARTITION BY category_id ORDER BY total_turnover DESC) as rank_turnover
                                            FROM {$popularity_table}
                                            WHERE category_id IS NOT NULL AND brand_id IS NOT NULL
                                        ) r ON p.id = r.id
                                        SET p.brand_rank_in_category_sales = r.rank_sales,
                                            p.brand_rank_in_category_turnover = r.rank_turnover
                                    ");

                                    
                                    $wpdb->query("
                                        UPDATE {$popularity_table} p
                                        INNER JOIN (
                                            SELECT id,
                                                RANK() OVER (PARTITION BY brand_id ORDER BY total_sales DESC) as rank_sales,
                                                RANK() OVER (PARTITION BY brand_id ORDER BY total_turnover DESC) as rank_turnover
                                            FROM {$popularity_table}
                                            WHERE category_id IS NOT NULL AND brand_id IS NOT NULL
                                        ) r ON p.id = r.id
                                        SET p.category_rank_in_brand_sales = r.rank_sales,
                                            p.category_rank_in_brand_turnover = r.rank_turnover
                                    ");
                                } else {
                                    

                                    
                                    $wpdb->query("
                                        UPDATE {$popularity_table} p
                                        SET p.category_rank_by_sales = (
                                            SELECT COUNT(*) + 1
                                            FROM (SELECT id, category_level, total_sales FROM {$popularity_table} WHERE brand_id IS NULL AND category_id IS NOT NULL) p2
                                            WHERE p2.category_level = p.category_level AND p2.total_sales > p.total_sales
                                        ),
                                        p.category_rank_by_turnover = (
                                            SELECT COUNT(*) + 1
                                            FROM (SELECT id, category_level, total_turnover FROM {$popularity_table} WHERE brand_id IS NULL AND category_id IS NOT NULL) p3
                                            WHERE p3.category_level = p.category_level AND p3.total_turnover > p.total_turnover
                                        )
                                        WHERE p.brand_id IS NULL AND p.category_id IS NOT NULL
                                    ");

                                    
                                    $wpdb->query("
                                        UPDATE {$popularity_table} p
                                        SET p.subcategory_rank_in_parent_sales = (
                                            SELECT COUNT(*) + 1
                                            FROM (SELECT id, parent_category_id, total_sales FROM {$popularity_table} WHERE brand_id IS NULL AND parent_category_id IS NOT NULL) p2
                                            WHERE p2.parent_category_id = p.parent_category_id AND p2.total_sales > p.total_sales
                                        ),
                                        p.subcategory_rank_in_parent_turnover = (
                                            SELECT COUNT(*) + 1
                                            FROM (SELECT id, parent_category_id, total_turnover FROM {$popularity_table} WHERE brand_id IS NULL AND parent_category_id IS NOT NULL) p3
                                            WHERE p3.parent_category_id = p.parent_category_id AND p3.total_turnover > p.total_turnover
                                        )
                                        WHERE p.brand_id IS NULL AND p.parent_category_id IS NOT NULL
                                    ");

                                    
                                    $wpdb->query("
                                        UPDATE {$popularity_table} p
                                        SET p.brand_rank_by_sales = (
                                            SELECT COUNT(*) + 1
                                            FROM (SELECT id, total_sales FROM {$popularity_table} WHERE category_id IS NULL AND brand_id IS NOT NULL) p2
                                            WHERE p2.total_sales > p.total_sales
                                        ),
                                        p.brand_rank_by_turnover = (
                                            SELECT COUNT(*) + 1
                                            FROM (SELECT id, total_turnover FROM {$popularity_table} WHERE category_id IS NULL AND brand_id IS NOT NULL) p3
                                            WHERE p3.total_turnover > p.total_turnover
                                        )
                                        WHERE p.category_id IS NULL AND p.brand_id IS NOT NULL
                                    ");

                                    
                                    $wpdb->query("
                                        UPDATE {$popularity_table} p
                                        SET p.brand_rank_in_category_sales = (
                                            SELECT COUNT(*) + 1
                                            FROM (SELECT id, category_id, total_sales FROM {$popularity_table} WHERE category_id IS NOT NULL AND brand_id IS NOT NULL) p2
                                            WHERE p2.category_id = p.category_id AND p2.total_sales > p.total_sales
                                        ),
                                        p.brand_rank_in_category_turnover = (
                                            SELECT COUNT(*) + 1
                                            FROM (SELECT id, category_id, total_turnover FROM {$popularity_table} WHERE category_id IS NOT NULL AND brand_id IS NOT NULL) p3
                                            WHERE p3.category_id = p.category_id AND p3.total_turnover > p.total_turnover
                                        )
                                        WHERE p.category_id IS NOT NULL AND p.brand_id IS NOT NULL
                                    ");

                                    
                                    $wpdb->query("
                                        UPDATE {$popularity_table} p
                                        SET p.category_rank_in_brand_sales = (
                                            SELECT COUNT(*) + 1
                                            FROM (SELECT id, brand_id, total_sales FROM {$popularity_table} WHERE category_id IS NOT NULL AND brand_id IS NOT NULL) p2
                                            WHERE p2.brand_id = p.brand_id AND p2.total_sales > p.total_sales
                                        ),
                                        p.category_rank_in_brand_turnover = (
                                            SELECT COUNT(*) + 1
                                            FROM (SELECT id, brand_id, total_turnover FROM {$popularity_table} WHERE category_id IS NOT NULL AND brand_id IS NOT NULL) p3
                                            WHERE p3.brand_id = p.brand_id AND p3.total_turnover > p.total_turnover
                                        )
                                        WHERE p.category_id IS NOT NULL AND p.brand_id IS NOT NULL
                                    ");
                                }

                                if ($wpdb->last_error) {
                                    delete_transient('aieo_category_brand_stats_start_time');
                                    delete_transient('aieo_category_brand_stats_lock');
                                    wp_send_json_error(array(
                                        'message' => __('Ranking calculation failed:', 'ai-eshop-optimizer') . ' ' . $wpdb->last_error
                                    ));
                                    return;
                                }

                                
                                $total_rows = $wpdb->get_var("SELECT COUNT(*) FROM {$popularity_table}");
                                $category_count = $wpdb->get_var("SELECT COUNT(*) FROM {$popularity_table} WHERE brand_id IS NULL");
                                $brand_count = $wpdb->get_var("SELECT COUNT(*) FROM {$popularity_table} WHERE category_id IS NULL");
                                $combo_count = $wpdb->get_var("SELECT COUNT(*) FROM {$popularity_table} WHERE category_id IS NOT NULL AND brand_id IS NOT NULL");

                                delete_transient('aieo_category_brand_stats_start_time');
                                delete_transient('aieo_category_brand_stats_lock');

                                
                                $this->aieo_ensure_mysql_completion();

                                wp_send_json_success(array(
                                    'complete' => true,
                                    'message' => sprintf(
                                        
                                        __('✓ Category/brand popularity: %1$d categories, %2$d brands, %3$d combinations (completed in %4$ds)', 'ai-eshop-optimizer'),
                                        $category_count, $brand_count, $combo_count, $elapsed
                                    ),
                                    'current' => 100,
                                    'total' => 100
                                ));
                            }
                        } else {
                            wp_send_json_success(array(
                                'complete' => true,
                                'message' => __('Category/brand statistics skipped', 'ai-eshop-optimizer'),
                                'current' => 0,
                                'total' => 0
                            ));
                        }
                        break;

                    case 'aggregate_customer_std_stats':
                        if ($settings['aggregate_customer_std_stats'] == '1') {
                            $temp_orders_table_name = get_option('aieo_site_orders_table', $wpdb->prefix . 'aieo_temp_orders');
                            $progress_step = isset($_POST['progress_step']) ? intval($_POST['progress_step']) : 0;

                            
                            $batch_size = 5000; 
                            $batch_offset = isset($_POST['batch_offset']) ? intval($_POST['batch_offset']) : 0;

                            
                            if ($progress_step === 0) {
                                
                                $stats_lock = get_transient('aieo_customer_std_stats_lock');
                                if ($stats_lock && $stats_lock !== $export_id) {
                                    wp_send_json_error(array(
                                        'message' => __('Customer standard statistics are already being calculated by another process.', 'ai-eshop-optimizer')
                                    ));
                                    return;
                                }
                                set_transient('aieo_customer_std_stats_lock', $export_id, 300);
                                self::aieo_register_export_lock_shutdown('aieo_customer_std_stats_lock', $export_id);

                                
                                $total_customers = $wpdb->get_var("SELECT COUNT(DISTINCT EponymousID) FROM {$temp_orders_table_name} WHERE EponymousID != ''");
                                set_transient('aieo_customer_std_stats_total', $total_customers, 3600);
                                set_transient('aieo_customer_std_stats_start_time', time(), 3600);
                                set_transient('aieo_customer_std_stats_processed', 0, 3600);

                                
                                
                                $existing_indexes = $wpdb->get_results("SHOW INDEX FROM {$temp_orders_table_name}");
                                $index_names = array();
                                foreach ($existing_indexes as $idx) {
                                    $index_names[] = $idx->Key_name;
                                }

                                if (!in_array('idx_eponymous_id', $index_names)) {
                                    $wpdb->query("CREATE INDEX idx_eponymous_id ON {$temp_orders_table_name} (EponymousId)");
                                }
                                if (!in_array('idx_eponymous_orderid', $index_names)) {
                                    $wpdb->query("CREATE INDEX idx_eponymous_orderid ON {$temp_orders_table_name} (OrderId)");
                                }

                                wp_send_json_success(array(
                                    'complete' => false,
                                    
                                    'message' => sprintf(__('Initializing customer statistics for %d customers...', 'ai-eshop-optimizer'), $total_customers),
                                    'current' => 0,
                                    'total' => $total_customers,
                                    'progress_step' => 1,
                                    'batch_offset' => 0
                                ));
                            }
                            
                            else if ($progress_step >= 1) {
                                $total_customers = get_transient('aieo_customer_std_stats_total');
                                $start_time = get_transient('aieo_customer_std_stats_start_time');

                                
                                @set_time_limit(180); 

                                
                                aieo_debug_log("AIEO: Processing customer stats batch offset={$batch_offset}, size={$batch_size} at " . gmdate('H:i:s'));

                                $result = $wpdb->query($wpdb->prepare(
                                    "CALL `{$site_prefix}AIEO_UpdateCustomerCentricStdStats` (%s, %d, %d, %d)",
                                    $temp_orders_table_name,
                                    0, 
                                    $batch_offset,
                                    $batch_size
                                ));

                                
                                if ($wpdb->last_error) {
                                    aieo_debug_log("AIEO ERROR: " . $wpdb->last_error);
                                    delete_transient('aieo_customer_std_stats_total');
                                    delete_transient('aieo_customer_std_stats_start_time');
                                    delete_transient('aieo_customer_std_stats_processed');
                                    delete_transient('aieo_customer_std_stats_lock');
                                    wp_send_json_error(array(
                                        'message' => __('Customer statistics batch failed:', 'ai-eshop-optimizer') . ' ' . $wpdb->last_error
                                    ));
                                    return;
                                }

                                
                                $processed = min($batch_offset + $batch_size, $total_customers);
                                set_transient('aieo_customer_std_stats_processed', $processed, 3600);

                                $elapsed_time = time() - $start_time;
                                $percent = $total_customers > 0 ? round(($processed / $total_customers) * 100) : 100;

                                
                                if ($processed >= $total_customers) {
                                    
                                    $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}aieo_base_order_stats");

                                    delete_transient('aieo_customer_std_stats_total');
                                    delete_transient('aieo_customer_std_stats_start_time');
                                    delete_transient('aieo_customer_std_stats_processed');
                                    delete_transient('aieo_customer_std_stats_lock');

                                    
                                    $this->aieo_ensure_mysql_completion();

                                    wp_send_json_success(array(
                                        'complete' => true,
                                        
                                        'message' => sprintf(__('✓ Customer standard statistics: %1$d customers analyzed (completed in %2$ds)', 'ai-eshop-optimizer'), $total_customers, $elapsed_time),
                                        'current' => $total_customers,
                                        'total' => $total_customers
                                    ));
                                } else {
                                    
                                    $next_offset = $processed;
                                    wp_send_json_success(array(
                                        'complete' => false,
                                        
                                        'message' => sprintf(__('Processed %1$d / %2$d customers (%3$d%% complete, %4$ds elapsed)', 'ai-eshop-optimizer'), $processed, $total_customers, $percent, $elapsed_time),
                                        'current' => $processed,
                                        'total' => $total_customers,
                                        'progress_step' => $progress_step + 1,
                                        'batch_offset' => $next_offset
                                    ));
                                }
                            }
                        } else {
                            wp_send_json_success(array(
                                'complete' => true,
                                'message' => __('Aggregate customer std stats skipped', 'ai-eshop-optimizer'),
                                'current' => 0,
                                'total' => 0
                            ));
                        }
                        break;

                    case 'aggregate_customer_adv_stats':
                        if ($settings['aggregate_customer_adv_stats'] == '1') {
                            $temp_orders_table_name = get_option('aieo_site_orders_table', $wpdb->prefix . 'aieo_temp_orders');
                            $progress_step = isset($_POST['progress_step']) ? intval($_POST['progress_step']) : 0;

                            
                            $batch_size = 5000; 
                            $batch_offset = isset($_POST['batch_offset']) ? intval($_POST['batch_offset']) : 0;

                            
                            if ($progress_step === 0) {
                                
                                $stats_lock = get_transient('aieo_customer_adv_stats_lock');
                                if ($stats_lock && $stats_lock !== $export_id) {
                                    wp_send_json_error(array(
                                        'message' => __('Customer advanced statistics are already being calculated by another process.', 'ai-eshop-optimizer')
                                    ));
                                    return;
                                }
                                set_transient('aieo_customer_adv_stats_lock', $export_id, 300);
                                self::aieo_register_export_lock_shutdown('aieo_customer_adv_stats_lock', $export_id);

                                $total_customers = $wpdb->get_var("SELECT COUNT(DISTINCT EponymousID) FROM {$temp_orders_table_name} WHERE EponymousID != ''");
                                set_transient('aieo_customer_adv_stats_total', $total_customers, 3600);
                                set_transient('aieo_customer_adv_stats_start_time', time(), 3600);
                                set_transient('aieo_customer_adv_stats_processed', 0, 3600);

                                wp_send_json_success(array(
                                    'complete' => false,
                                    
                                    'message' => sprintf(__('Initializing advanced customer behavior analysis for %d customers...', 'ai-eshop-optimizer'), $total_customers),
                                    'current' => 0,
                                    'total' => $total_customers,
                                    'progress_step' => 1,
                                    'batch_offset' => 0
                                ));
                            }
                            
                            else if ($progress_step >= 1) {
                                $total_customers = get_transient('aieo_customer_adv_stats_total');
                                $start_time = get_transient('aieo_customer_adv_stats_start_time');

                                
                                @set_time_limit(180); 

                                
                                aieo_debug_log("AIEO: Processing customer adv stats batch offset={$batch_offset}, size={$batch_size} at " . gmdate('H:i:s'));

                                $result = $wpdb->query($wpdb->prepare(
                                    "CALL `{$site_prefix}AIEO_UpdateCustomerCentricAdvStats` (%s, %d, %d, %d)",
                                    $temp_orders_table_name,
                                    0, 
                                    $batch_offset,
                                    $batch_size
                                ));

                                
                                if ($wpdb->last_error) {
                                    aieo_debug_log("AIEO ERROR: " . $wpdb->last_error);
                                    delete_transient('aieo_customer_adv_stats_total');
                                    delete_transient('aieo_customer_adv_stats_start_time');
                                    delete_transient('aieo_customer_adv_stats_processed');
                                    delete_transient('aieo_customer_adv_stats_lock');
                                    wp_send_json_error(array(
                                        'message' => __('Advanced customer statistics batch failed:', 'ai-eshop-optimizer') . ' ' . $wpdb->last_error
                                    ));
                                    return;
                                }

                                
                                $processed = min($batch_offset + $batch_size, $total_customers);
                                set_transient('aieo_customer_adv_stats_processed', $processed, 3600);

                                $elapsed_time = time() - $start_time;
                                $percent = $total_customers > 0 ? round(($processed / $total_customers) * 100) : 100;

                                
                                if ($processed >= $total_customers) {
                                    
                                    $wpdb->query("DROP TABLE IF EXISTS wp_aieo_adv_stats_orders_rn");
                                    $wpdb->query("DROP TABLE IF EXISTS wp_aieo_adv_stats_orders_rn_copy");

                                    delete_transient('aieo_customer_adv_stats_total');
                                    delete_transient('aieo_customer_adv_stats_start_time');
                                    delete_transient('aieo_customer_adv_stats_processed');
                                    delete_transient('aieo_customer_adv_stats_lock');

                                    
                                    $this->aieo_ensure_mysql_completion();

                                    wp_send_json_success(array(
                                        'complete' => true,
                                        
                                        'message' => sprintf(__('✓ Advanced customer behavior analysis: %1$d customers analyzed (completed in %2$ds)', 'ai-eshop-optimizer'), $total_customers, $elapsed_time),
                                        'current' => $total_customers,
                                        'total' => $total_customers
                                    ));
                                } else {
                                    
                                    $next_offset = $processed;
                                    wp_send_json_success(array(
                                        'complete' => false,
                                        
                                        'message' => sprintf(__('Analyzed %1$d / %2$d customers (%3$d%% complete, %4$ds elapsed)', 'ai-eshop-optimizer'), $processed, $total_customers, $percent, $elapsed_time),
                                        'current' => $processed,
                                        'total' => $total_customers,
                                        'progress_step' => $progress_step + 1,
                                        'batch_offset' => $next_offset
                                    ));
                                }
                            }
                        } else {
                            wp_send_json_success(array(
                                'complete' => true,
                                'message' => __('Aggregate customer adv stats skipped', 'ai-eshop-optimizer'),
                                'current' => 0,
                                'total' => 0
                            ));
                        }
                        break;

                    case 'create_uuids':
                        if ($settings['create_uuids'] == '1') {
                            $temp_orders_table_name = get_option('aieo_site_orders_table', $wpdb->prefix . 'aieo_temp_orders');
                            $progress_step = isset($_POST['progress_step']) ? intval($_POST['progress_step']) : 0;

                            
                            
                            
                            
                            

                            
                            $uuid_stages = array(
                                array(
                                    'name' => 'O_PP',
                                    'column' => 'O_PP_GraphUUID',
                                    'desc' => 'Order-Parent relationships',
                                    'where' => 'OrderId IS NOT NULL AND ParentProductId IS NOT NULL',
                                    'expr'  => "UNHEX(MD5(CONCAT('opp:', CAST(OrderId AS CHAR), ':', CAST(ParentProductId AS CHAR))))"
                                ),
                                array(
                                    'name' => 'O_Prod',
                                    'column' => 'O_Prod_GraphUUID',
                                    'desc' => 'Order-Product relationships',
                                    'where' => 'OrderId IS NOT NULL AND ProductId IS NOT NULL',
                                    'expr'  => "UNHEX(MD5(CONCAT('oprod:', CAST(OrderId AS CHAR), ':', CAST(ProductId AS CHAR))))"
                                ),
                                array(
                                    'name' => 'ParentProductId',
                                    'column' => 'PPIdGraphUUID',
                                    'desc' => 'Parent Product UUIDs',
                                    'where' => 'ParentProductId IS NOT NULL',
                                    'expr'  => "UNHEX(MD5(CONCAT('pp:', CAST(ParentProductId AS CHAR))))"
                                ),
                                array(
                                    'name' => 'OrderId',
                                    'column' => 'OrderIdGraphUUID',
                                    'desc' => 'Order UUIDs',
                                    'where' => 'OrderId IS NOT NULL',
                                    'expr'  => "UNHEX(MD5(CONCAT('ord:', CAST(OrderId AS CHAR))))"
                                ),
                                array(
                                    'name' => 'ProductId',
                                    'column' => 'ProdIdGraphUUID',
                                    'desc' => 'Product UUIDs',
                                    'where' => 'ProductId IS NOT NULL',
                                    'expr'  => "UNHEX(MD5(CONCAT('prod:', CAST(ProductId AS CHAR))))"
                                ),
                                array(
                                    'name' => 'EponymousId',
                                    'column' => 'EpoIdGraphUUID',
                                    'desc' => 'Customer UUIDs',
                                    'where' => 'EponymousId IS NOT NULL AND EponymousId <> 0',
                                    'expr'  => "UNHEX(MD5(CONCAT('epo:', CAST(EponymousId AS CHAR))))"
                                ),
                                array(
                                    'name' => 'O_Epo',
                                    'column' => 'O_Epo_GraphUUID',
                                    'desc' => 'Order-Customer relationships',
                                    'where' => 'OrderId IS NOT NULL AND EponymousId IS NOT NULL AND EponymousId <> 0',
                                    'expr'  => "UNHEX(MD5(CONCAT('oepo:', CAST(OrderId AS CHAR), ':', CAST(EponymousId AS CHAR))))"
                                ),
                                array(
                                    'name' => 'PP_Epo',
                                    'column' => 'PP_Epo_GraphUUID',
                                    'desc' => 'Product-Customer relationships',
                                    'where' => 'ParentProductId IS NOT NULL AND EponymousId IS NOT NULL AND EponymousId <> 0',
                                    'expr'  => "UNHEX(MD5(CONCAT('ppe:', CAST(ParentProductId AS CHAR), ':', CAST(EponymousId AS CHAR))))"
                                ),
                                array(
                                    'name' => 'Prod_Epo',
                                    'column' => 'Prod_Epo_GraphUUID',
                                    'desc' => 'Variant-Customer relationships',
                                    'where' => 'ProductId IS NOT NULL AND EponymousId IS NOT NULL AND EponymousId <> 0',
                                    'expr'  => "UNHEX(MD5(CONCAT('pe:', CAST(ProductId AS CHAR), ':', CAST(EponymousId AS CHAR))))"
                                )
                            );

                            
                            if ($progress_step === 0) {
                                $count = $wpdb->get_var("SELECT COUNT(*) FROM {$temp_orders_table_name}");
                                if ($count === null) {
                                    $this->aieo_log('Failed to count records before UUID generation.', array(
                                        'table' => $temp_orders_table_name,
                                        'db_error' => $wpdb->last_error,
                                    ));
                                    wp_send_json_error(array(
                                        'message' => __('Unable to initialize UUID generation because record counting failed.', 'ai-eshop-optimizer')
                                    ));
                                    return;
                                }

                                
                                if ((int) $count === 0) {
                                    $stage_count = count($uuid_stages);
                                    $this->aieo_log('UUID stage skipped because temp orders table is empty.', array(
                                        'table' => $temp_orders_table_name,
                                    ));
                                    wp_send_json_success(array(
                                        'complete' => true,
                                        'message' => __('✓ UUID generation skipped: no records detected in temporary orders table.', 'ai-eshop-optimizer'),
                                        'current' => 0,
                                        'total' => 0,
                                        'progress_step' => $stage_count + 1 
                                    ));
                                    return;
                                }

                                set_transient('aieo_uuid_total_records', $count, 7200);
                                set_transient('aieo_uuid_start_time', time(), 7200);
                                set_transient('aieo_uuid_processed', 0, 7200);

                                $stage_count = count($uuid_stages);

                                wp_send_json_success(array(
                                    'complete' => false,
                                    
                                    'message' => sprintf(__('Initializing UUID generation for %1$d records (%2$d entity types)...', 'ai-eshop-optimizer'), $count, $stage_count),
                                    'current' => 0,
                                    'total' => $count * $stage_count,
                                    'progress_step' => 1
                                ));
                            }
                            
                            else if ($progress_step >= 1 && $progress_step <= count($uuid_stages)) {
                                set_time_limit(180); 

                                $stage_index = $progress_step - 1;
                                $stage = $uuid_stages[$stage_index];
                                $stage_count = count($uuid_stages);
                                $total_records = (int) get_transient('aieo_uuid_total_records');
                                $start_time = (int) get_transient('aieo_uuid_start_time');
                                $elapsed = time() - $start_time;

                                $column = $stage['column'];
                                $key_where = isset($stage['where']) ? $stage['where'] : '1=1';
                                $uuid_expression = $stage['expr'];

                                $empty_clause = $this->aieo_uuid_empty_clause($column);

                                $before_null = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$temp_orders_table_name} WHERE {$empty_clause} AND {$key_where}");
                                $non_eligible_missing = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$temp_orders_table_name} WHERE {$empty_clause} AND NOT ({$key_where})");

                                $this->aieo_log('Starting UUID generation stage.', array(
                                    'stage' => $stage['desc'],
                                    'column' => $column,
                                    'records_missing' => $before_null,
                                    'missing_without_required_keys' => $non_eligible_missing,
                                ));

                                $updated = 0;
                                if ($before_null > 0) {
                                    $updated = (int) $wpdb->query("
                                        UPDATE {$temp_orders_table_name}
                                        SET {$column} = {$uuid_expression}
                                        WHERE {$empty_clause} AND {$key_where}
                                    ");
                                }

                                if ($wpdb->last_error) {
                                    delete_transient('aieo_uuid_total_records');
                                    delete_transient('aieo_uuid_start_time');
                                    delete_transient('aieo_uuid_processed');
                                    wp_send_json_error(array(
                                        'message' => __('UUID generation failed at stage', 'ai-eshop-optimizer') . " '{$stage['desc']}': " . $wpdb->last_error
                                    ));
                                    return;
                                }

                                $records_updated = max(0, $updated);
                                $after_null = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$temp_orders_table_name} WHERE {$empty_clause} AND {$key_where}");

                                $cumulative = (int) get_transient('aieo_uuid_processed') + $records_updated;
                                set_transient('aieo_uuid_processed', $cumulative, 7200);

                                $percent = $stage_count > 0 ? round(($progress_step / $stage_count) * 100) : 100;

                                $this->aieo_log('Finished UUID generation stage.', array(
                                    'stage' => $stage['desc'],
                                    'updated' => $records_updated,
                                    'remaining_null' => $after_null,
                                    'elapsed_stage_seconds' => $elapsed,
                                ));

                                
                                $stage_message = sprintf(__('Generated %1$s: %2$d records updated (%3$ds elapsed, %4$d%% complete)', 'ai-eshop-optimizer'), $stage['desc'], $records_updated, $elapsed, $percent);
                                if ($before_null === 0 && $non_eligible_missing > 0 && $records_updated === 0) {
                                    
                                    $stage_message = sprintf(__('%1$s skipped: no rows satisfied required keys (%2$d rows missing source identifiers).', 'ai-eshop-optimizer'), $stage['desc'], $non_eligible_missing);
                                } elseif ($records_updated === 0 && $before_null > 0) {
                                    
                                    $stage_message = sprintf(__('%1$s: Unable to assign UUIDs because %2$d rows are missing required keys.', 'ai-eshop-optimizer'), $stage['desc'], $before_null);
                                }

                                wp_send_json_success(array(
                                    'complete' => false,
                                    'message' => $stage_message,
                                    'current' => $cumulative,
                                    'total' => $total_records * $stage_count,
                                    'progress_step' => $progress_step + 1
                                ));
                            }
                            
                            else if ($progress_step === count($uuid_stages) + 1) {
                                set_time_limit(180);

                                $start_time = get_transient('aieo_uuid_start_time');
                                $elapsed = time() - $start_time;

                                $count = (int) get_transient('aieo_uuid_total_records');

                                if ($count > 0) {
                                    $wpdb->query($wpdb->prepare(
                                        "CALL `{$site_prefix}AIEO_GenerateGraphDBUUIDFreqs` (%s)",
                                        $temp_orders_table_name
                                    ));

                                    if ($wpdb->last_error) {
                                        delete_transient('aieo_uuid_total_records');
                                        delete_transient('aieo_uuid_start_time');
                                        delete_transient('aieo_uuid_processed');
                                        wp_send_json_error(array(
                                            'message' => __('UUID frequency generation failed:', 'ai-eshop-optimizer') . ' ' . $wpdb->last_error
                                        ));
                                        return;
                                    }
                                }

                                $elapsed = time() - $start_time;

                                delete_transient('aieo_uuid_total_records');
                                delete_transient('aieo_uuid_start_time');
                                delete_transient('aieo_uuid_processed');

                                
                                $this->aieo_ensure_mysql_completion();

                                $stage_count = count($uuid_stages);
                                $completion_message = ($count > 0)
                                    
                                    ? sprintf(__('✓ UUIDs created: %1$d records with %2$d UUID types (BINARY(16) format for 2-3x faster performance) and relationship frequencies (completed in %3$ds)', 'ai-eshop-optimizer'), $count, $stage_count, $elapsed)
                                    : __('✓ UUID stage completed: no records required UUID processing.', 'ai-eshop-optimizer');

                                wp_send_json_success(array(
                                    'complete' => true,
                                    'message' => $completion_message,
                                    'current' => $count,
                                    'total' => $count
                                ));
                            }
                        } else {
                            wp_send_json_success(array(
                                'complete' => true,
                                'message' => __('Create UUIDs skipped', 'ai-eshop-optimizer'),
                                'current' => 0,
                                'total' => 0
                            ));
                        }
                        break;

                    case 'create_need_suggestions':
                        if ($settings['create_need_suggestions'] == '1') {
                            
                            require_once AIEO_DIR . 'includes/class-need-suggestions.php';
                            $generator = AI_eShop_Need_Suggestions::get_instance();

                            
                            $progress = get_transient('aieo_need_suggestions_progress');
                            if (!$progress) {
                                
                                $stats = $generator->get_total_products_with_needs(true);
                                $progress = array(
                                    'offset' => 0,
                                    'total' => $stats['parent_count'],
                                    'variation_count' => $stats['variation_count'],
                                    'total_impacted' => $stats['total_impacted'],
                                    'processed' => 0,
                                    'suggestions_created' => 0,
                                    'skipped' => 0,
                                    'failed' => 0,
                                );
                            }

                            
                            $batch_size = 300;
                            $results = $generator->generate_suggestions_batch($progress['offset'], $batch_size);

                            
                            $progress['offset'] = $results['next_offset'];
                            $progress['processed'] += $results['processed'];
                            $progress['suggestions_created'] += $results['suggestions_created'];
                            $progress['skipped'] += $results['skipped'];
                            $progress['failed'] += $results['failed'];

                            if ($results['complete']) {
                                
                                delete_transient('aieo_need_suggestions_progress');

                                
                                $variation_count = isset($progress['variation_count']) ? $progress['variation_count'] : 0;
                                $total_impacted = isset($progress['total_impacted']) ? $progress['total_impacted'] : $progress['processed'];

                                $message = sprintf(
                                    
                                    __('✓ Need suggestions: %1$d products processed, %2$d suggestions created, %3$d skipped, %4$d failed. Total impacted: %5$d products (%6$d variations inherit from parents)', 'ai-eshop-optimizer'),
                                    $progress['processed'],
                                    $progress['suggestions_created'],
                                    $progress['skipped'],
                                    $progress['failed'],
                                    $total_impacted,
                                    $variation_count
                                );

                                wp_send_json_success(array(
                                    'complete' => true,
                                    'message' => $message,
                                    'current' => $progress['processed'],
                                    'total' => $progress['total']
                                ));
                            } else {
                                
                                set_transient('aieo_need_suggestions_progress', $progress, 3600);

                                
                                $total_impacted = isset($progress['total_impacted']) ? $progress['total_impacted'] : $progress['total'];

                                $message = sprintf(
                                    
                                    __('Processing need suggestions: %1$d / %2$d products (%3$d suggestions created) - will impact %4$d total products', 'ai-eshop-optimizer'),
                                    $progress['processed'],
                                    $progress['total'],
                                    $progress['suggestions_created'],
                                    $total_impacted
                                );

                                wp_send_json_success(array(
                                    'complete' => false,
                                    'message' => $message,
                                    'current' => $progress['processed'],
                                    'total' => $progress['total']
                                ));
                            }
                        } else {
                            wp_send_json_success(array(
                                'complete' => true,
                                'message' => __('Need suggestions skipped', 'ai-eshop-optimizer'),
                                'current' => 0,
                                'total' => 0
                            ));
                        }
                        break;

                    case 'create_export':
                        if ($settings['create_export'] == '1') {
                            
                            $orders_table_name = $wpdb->prefix . "aieo_" . gmdate('Y_m') . "_orders";
                            $temp_orders_table = $wpdb->prefix . 'aieo_temp_orders';

                            
                            if (!$this->aieo_table_exists($temp_orders_table)) {
                                wp_send_json_error(array(
                                    'message' => __('Cannot create export: Orders table does not exist yet. Please process orders first.', 'ai-eshop-optimizer')
                                ));
                                return;
                            }

                            $temp_count = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$temp_orders_table}");
                            if ($temp_count === 0) {
                                wp_send_json_error(array(
                                    'message' => __('Cannot create export: No orders found in table. Please process orders first.', 'ai-eshop-optimizer')
                                ));
                                return;
                            }

                            
                            $wpdb->query("DROP TABLE IF EXISTS {$orders_table_name}");

                            
                            $structure_result = $wpdb->query("CREATE TABLE {$orders_table_name} LIKE {$temp_orders_table}");
                            if ($structure_result === false) {
                                $error = $wpdb->last_error;
                                $this->aieo_log('Failed to clone orders table structure for monthly archive.', array(
                                    'source_table' => $temp_orders_table,
                                    'target_table' => $orders_table_name,
                                    'db_error' => $error,
                                ));
                                wp_send_json_error(array(
                                    'message' => __('Export failed while creating monthly table structure:', 'ai-eshop-optimizer') . ' ' . $error
                                ));
                                return;
                            }

                            $insert_result = $wpdb->query("INSERT INTO {$orders_table_name} SELECT * FROM {$temp_orders_table}");
                            if ($insert_result === false) {
                                $error = $wpdb->last_error;
                                $this->aieo_log('Failed to copy order data into monthly archive.', array(
                                    'source_table' => $temp_orders_table,
                                    'target_table' => $orders_table_name,
                                    'db_error' => $error,
                                ));
                                wp_send_json_error(array(
                                    'message' => __('Export failed while copying order data:', 'ai-eshop-optimizer') . ' ' . $error
                                ));
                                return;
                            }

                            $count = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$orders_table_name}");
                            $temp_count = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$temp_orders_table}");

                            $this->aieo_log('Monthly orders table finalized.', array(
                                'table' => $orders_table_name,
                                'rows_copied' => $count,
                                'temp_rows_retained' => $temp_count,
                            ));

                            
                            $uploads_dir = wp_upload_dir();
                            $parsed_url = wp_parse_url(home_url());
                            $domain = isset($parsed_url['host']) ? $parsed_url['host'] : 'site';
                            $timestamp = gmdate('Ymd_His');
                            $export_id_fragment = $export_id ? substr(md5($export_id), 0, 8) : wp_generate_password(8, false);
                            $csv_filename = sprintf('%s_exported_orders_hpos_%s_%s.csv', $domain, $timestamp, $export_id_fragment);
                            $csv_path = trailingslashit($uploads_dir['basedir']) . $csv_filename;

                            
                            $csv_result = $this->aieo_create_csv_from_orders_table($orders_table_name, $csv_path);
                            $csv_created = ($csv_result !== false);
                            if (!$csv_created) {
                                $this->aieo_log('CSV export failed after table duplication.', array(
                                    'table' => $orders_table_name,
                                ));
                            } else {
                                $csv_url = trailingslashit($uploads_dir['baseurl']) . $csv_filename;
                                update_option('aieo_last_export_csv', array(
                                    'filename' => $csv_filename,
                                    'path' => $csv_result,
                                    'url' => $csv_url,
                                    'generated_at' => current_time('mysql', true),
                                ));
                            }

                            
                            delete_transient('aieo_export_lock');
                            delete_transient('aieo_export_settings');
                            delete_transient('aieo_export_id');

                            $export_message = $csv_created
                                
                                ? sprintf(__('Export file created: %d records ready', 'ai-eshop-optimizer'), $count)
                                
                                : sprintf(__('Monthly table finalized with %d records, but CSV creation failed. Check error logs.', 'ai-eshop-optimizer'), $count);

                            wp_send_json_success(array(
                                'complete' => true,
                                'message' => $export_message,
                                'current' => $count,
                                'total' => $count
                            ));
                        } else {
                            
                            delete_transient('aieo_export_lock');
                            delete_transient('aieo_export_settings');
                            delete_transient('aieo_export_id');

                            wp_send_json_success(array(
                                'complete' => true,
                                'message' => __('Create export skipped', 'ai-eshop-optimizer'),
                                'current' => 0,
                                'total' => 0
                            ));
                        }
                        break;

                    default:
                        delete_transient('aieo_export_lock');
                        delete_transient('aieo_export_id');
                        wp_send_json_error(array('message' => __('Unknown stage:', 'ai-eshop-optimizer') . ' ' . $stage));
                        return;
                }

            } catch (Exception $e) {
                delete_transient('aieo_export_lock');
                delete_transient('aieo_export_id');
                wp_send_json_error(array(
                    'message' => __('Error in stage', 'ai-eshop-optimizer') . ' ' . $stage . ': ' . $e->getMessage()
                ));
            }
        }

        
        public function aieo_optimize_database()
        {
            
            check_ajax_referer('aieo_optimize_db', 'nonce');

            
            if (!current_user_can(AIEO_CAPABILITY)) {
                wp_send_json_error(array('message' => __('Insufficient permissions', 'ai-eshop-optimizer')));
                return;
            }

            
            $optimize_lock = get_transient('aieo_optimize_db_lock');
            if ($optimize_lock) {
                wp_send_json_error(array(
                    'message' => __('Database optimization is already running. Please wait for it to complete.', 'ai-eshop-optimizer')
                ));
                return;
            }

            
            $lock_id = uniqid('opt_', true);
            set_transient('aieo_optimize_db_lock', $lock_id, 600);

            try {
                
                require_once AIEO_DIR . 'includes/sql/apply_mariadb114_indexes.php';

                
                $db_check = aieo_check_mariadb_version();

                
                
                
                
                
                
                
                
                $detected_version = isset($db_check['version_number']) ? (string) $db_check['version_number'] : '';
                if (isset($db_check['db_type']) && $db_check['db_type'] === 'mysql8') {
                    require_once AIEO_DIR . 'includes/sql/apply_mysql8_indexes.php';
                    $result               = aieo_apply_mysql8_optimized_indexes();
                    $product_vitals_result= aieo_apply_mysql8_product_vitals_indexes();
                    $db_label             = $detected_version !== '' ? 'MySQL ' . $detected_version : 'MySQL 8';
                } else {
                    $result               = aieo_apply_mariadb114_optimized_indexes();
                    $product_vitals_result= aieo_apply_mariadb114_product_vitals_indexes();
                    $db_label             = $detected_version !== '' ? 'MariaDB ' . $detected_version : 'MariaDB 11.4';
                }

                
                $combined_details = array_merge(
                    isset($result['details']) ? $result['details'] : array(),
                    array('--- Product Vitals Tables ---'),
                    isset($product_vitals_result['details']) ? $product_vitals_result['details'] : array()
                );

                $combined_result = array(
                    'success' => $result['success'] && $product_vitals_result['success'],
                    
                    'message' => sprintf(__('%s optimization completed for both orders and product vitals tables', 'ai-eshop-optimizer'), $db_label),
                    'details' => $combined_details
                );

                
                delete_transient('aieo_optimize_db_lock');

                if ($combined_result['success']) {
                    wp_send_json_success($combined_result);
                } else {
                    wp_send_json_error($combined_result);
                }
            } catch (Exception $e) {
                
                delete_transient('aieo_optimize_db_lock');

                wp_send_json_error(array(
                    'message' => __('Database optimization failed:', 'ai-eshop-optimizer') . ' ' . $e->getMessage(),
                    'details' => array($e->getFile() . ':' . $e->getLine())
                ));
            }
        }

        
        public function aieo_get_index_stats()
        {
            
            check_ajax_referer('aieo_get_indexes', 'nonce');

            
            if (!current_user_can(AIEO_CAPABILITY)) {
                wp_send_json_error(array('message' => __('Insufficient permissions', 'ai-eshop-optimizer')));
                return;
            }

            
            require_once AIEO_DIR . 'includes/sql/apply_mariadb114_indexes.php';

            
            $indexes = aieo_get_index_statistics();

            wp_send_json_success(array('indexes' => $indexes));
        }

        
        public function aieo_fix_collations()
        {
            
            check_ajax_referer('aieo_fix_collation', 'nonce');

            
            if (!current_user_can(AIEO_CAPABILITY)) {
                wp_send_json_error(array('message' => __('Insufficient permissions', 'ai-eshop-optimizer')));
                return;
            }

            
            $collation_lock = get_transient('aieo_fix_collation_lock');
            if ($collation_lock) {
                wp_send_json_error(array(
                    'message' => __('Collation fix is already running. Please wait for it to complete.', 'ai-eshop-optimizer')
                ));
                return;
            }

            
            $lock_id = uniqid('coll_', true);
            set_transient('aieo_fix_collation_lock', $lock_id, 900);

            try {
                
                require_once AIEO_DIR . 'includes/sql/apply_mariadb114_indexes.php';

                
                $result = aieo_standardize_database_collations();

                
                delete_transient('aieo_fix_collation_lock');

                if ($result['success']) {
                    wp_send_json_success($result);
                } else {
                    wp_send_json_error($result);
                }
            } catch (Exception $e) {
                
                delete_transient('aieo_fix_collation_lock');

                wp_send_json_error(array(
                    'message' => __('Collation fix failed:', 'ai-eshop-optimizer') . ' ' . $e->getMessage(),
                    'details' => array($e->getFile() . ':' . $e->getLine())
                ));
            }
        }

        

        public function aieo_handle_rooster_connector() {
            if (!current_user_can(AIEO_CAPABILITY)) {
                wp_die(esc_html__('Unauthorized', 'ai-eshop-optimizer'));
            }
            check_admin_referer('aieo_rooster_connector_action', 'aieo_rooster_connector_nonce');

            
            $selected_client = isset($_POST['aieo_rooster_selected_client']) ? absint($_POST['aieo_rooster_selected_client']) : 0;
            if ($selected_client > 0) {
                $api_key = get_option('aieo_rooster_api_key');
                $hub_url = get_option('aieo_rooster_hub_url', 'https://rooster.systems');

                $response = wp_remote_post(rtrim($hub_url, '/') . '/wp-json/om-hub/v1/content-connector/register-site', [
                    'headers' => [
                        'X-Content-Connector-Key' => $api_key,
                        'Content-Type'            => 'application/json',
                        'Accept'                  => 'application/json',
                    ],
                    'body'      => wp_json_encode([
                        'client_id' => $selected_client,
                        'site_url'  => home_url(),
                    ]),
                    'timeout'   => 15,
                    'sslverify' => false,
                ]);

                if (!is_wp_error($response)) {
                    $code = wp_remote_retrieve_response_code($response);
                    $body = json_decode(wp_remote_retrieve_body($response), true);
                    if ($code >= 200 && $code < 300 && !empty($body['success'])) {
                        update_option('aieo_rooster_status', 'connected');
                        update_option('aieo_rooster_client_id', $selected_client);
                        update_option('aieo_rooster_client_label', $body['label'] ?? '');
                        update_option('aieo_rooster_status_message', '');
                        update_option('aieo_rooster_sites', ''); 
                    } else {
                        update_option('aieo_rooster_status', 'error');
                        update_option('aieo_rooster_status_message', $body['message'] ?? "Registration failed (HTTP {$code})");
                    }
                } else {
                    update_option('aieo_rooster_status', 'error');
                    update_option('aieo_rooster_status_message', $response->get_error_message());
                }

                wp_safe_redirect(wp_get_referer() ?: admin_url('admin.php?page=ai-eshop-optimizer'));
                exit;
            }

            
            $enabled  = isset($_POST['aieo_rooster_enabled']) ? 1 : 0;
            $api_key  = sanitize_text_field(wp_unslash($_POST['aieo_rooster_api_key'] ?? ''));
            $hub_url  = esc_url_raw(wp_unslash($_POST['aieo_rooster_hub_url'] ?? 'https://rooster.systems'));

            update_option('aieo_rooster_enabled', $enabled);
            update_option('aieo_rooster_api_key', $api_key);
            update_option('aieo_rooster_hub_url', rtrim($hub_url, '/'));

            if ($enabled && $api_key) {
                
                $response = wp_remote_get(rtrim($hub_url, '/') . '/wp-json/om-hub/v1/content-connector/sites', [
                    'headers' => [
                        'X-Content-Connector-Key' => $api_key,
                        'Accept'                  => 'application/json',
                    ],
                    'timeout'   => 15,
                    'sslverify' => false,
                ]);

                if (is_wp_error($response)) {
                    update_option('aieo_rooster_status', 'error');
                    update_option('aieo_rooster_status_message', $response->get_error_message());
                    update_option('aieo_rooster_sites', '');
                } else {
                    $code = wp_remote_retrieve_response_code($response);
                    $body = json_decode(wp_remote_retrieve_body($response), true);
                    if ($code >= 200 && $code < 300 && !empty($body['sites'])) {
                        
                        
                        
                        
                        
                        
                        
                        $auto_linked = null;
                        $site_domain = wp_parse_url(home_url(), PHP_URL_HOST);
                        foreach ($body['sites'] as $site) {
                            $s_domain = wp_parse_url($site['site_url'] ?? '', PHP_URL_HOST);
                            if ($s_domain && $site_domain && stripos($s_domain, $site_domain) !== false && !empty($site['has_token'])) {
                                $auto_linked = $site;
                                break;
                            }
                        }

                        if ($auto_linked) {
                            update_option('aieo_rooster_status', 'connected');
                            update_option('aieo_rooster_client_id', $auto_linked['id']);
                            update_option('aieo_rooster_client_label', $auto_linked['label'] ?? '');
                            update_option('aieo_rooster_status_message', '');
                            update_option('aieo_rooster_sites', '');
                        } elseif (count($body['sites']) === 1) {
                            
                            $only = $body['sites'][0];
                            $reg_response = wp_remote_post(rtrim($hub_url, '/') . '/wp-json/om-hub/v1/content-connector/register-site', [
                                'headers' => [
                                    'X-Content-Connector-Key' => $api_key,
                                    'Content-Type'            => 'application/json',
                                    'Accept'                  => 'application/json',
                                ],
                                'body'      => wp_json_encode([
                                    'client_id' => (int) $only['id'],
                                    'site_url'  => home_url(),
                                ]),
                                'timeout'   => 15,
                                'sslverify' => false,
                            ]);
                            if (!is_wp_error($reg_response)) {
                                $reg_code = wp_remote_retrieve_response_code($reg_response);
                                $reg_body = json_decode(wp_remote_retrieve_body($reg_response), true);
                                if ($reg_code >= 200 && $reg_code < 300 && !empty($reg_body['success'])) {
                                    update_option('aieo_rooster_status', 'connected');
                                    update_option('aieo_rooster_client_id', (int) $only['id']);
                                    update_option('aieo_rooster_client_label', $reg_body['label'] ?? ($only['label'] ?? ''));
                                    update_option('aieo_rooster_status_message', '');
                                    update_option('aieo_rooster_sites', '');
                                } else {
                                    update_option('aieo_rooster_status', 'error');
                                    update_option('aieo_rooster_status_message', $reg_body['message'] ?? "Registration failed (HTTP {$reg_code})");
                                    update_option('aieo_rooster_sites', '');
                                }
                            } else {
                                update_option('aieo_rooster_status', 'error');
                                update_option('aieo_rooster_status_message', $reg_response->get_error_message());
                                update_option('aieo_rooster_sites', '');
                            }
                        } else {
                            
                            update_option('aieo_rooster_status', 'select_site');
                            update_option('aieo_rooster_status_message', 'API key valid. Select your site below:');
                            update_option('aieo_rooster_sites', wp_json_encode($body['sites']));
                        }
                    } elseif ($code >= 200 && $code < 300) {
                        update_option('aieo_rooster_status', 'error');
                        update_option('aieo_rooster_status_message', 'API key valid, but no client sites found for this partner.');
                        update_option('aieo_rooster_sites', '');
                    } else {
                        update_option('aieo_rooster_status', 'error');
                        update_option('aieo_rooster_status_message', $body['message'] ?? "Authentication failed (HTTP {$code})");
                        update_option('aieo_rooster_sites', '');
                    }
                }
            } else {
                update_option('aieo_rooster_status', '');
                update_option('aieo_rooster_status_message', '');
                update_option('aieo_rooster_sites', '');
            }

            wp_safe_redirect(wp_get_referer() ?: admin_url('admin.php?page=ai-eshop-optimizer'));
            exit;
        }

        
        public function aieo_check_rooster_credits() {
            if (!current_user_can(AIEO_CAPABILITY)) {
                wp_send_json_error(['message' => 'Unauthorized'], 403);
            }
            check_ajax_referer('aieo_check_rooster_credits', 'nonce');

            $api_key = trim((string) get_option('aieo_rooster_api_key', ''));
            $hub_url = trim((string) get_option('aieo_rooster_hub_url', 'https://rooster.systems'));

            if ($api_key === '') {
                wp_send_json_error([
                    'status'  => 'not_configured',
                    'message' => 'Rooster Content Connector token is not configured. Save your token first in the Pro Panel.',
                ], 200);
            }
            if ($hub_url === '') {
                $hub_url = 'https://rooster.systems';
            }

            $response = wp_remote_get(rtrim($hub_url, '/') . '/wp-json/om-portal/v1/anthropic/status', [
                'headers' => [
                    'X-OM-API-Key' => $api_key,
                    'Accept'       => 'application/json',
                ],
                'timeout'   => 15,
                'sslverify' => false,
            ]);

            if (is_wp_error($response)) {
                wp_send_json_error([
                    'status'  => 'network_error',
                    'message' => $response->get_error_message(),
                ], 200);
            }

            $code = wp_remote_retrieve_response_code($response);
            $body = json_decode(wp_remote_retrieve_body($response), true);
            if (!is_array($body)) {
                $body = [];
            }

            if ($code === 401 || $code === 403) {
                wp_send_json_error([
                    'status'  => 'unauthorized',
                    'message' => $body['message'] ?? 'Rooster token is invalid or expired.',
                ], 200);
            }
            if ($code === 402) {
                wp_send_json_error([
                    'status'  => 'not_subscribed',
                    'message' => $body['message'] ?? 'This Rooster account does not include AI Credits. Subscribe at rooster.systems → AI Eshop Optimizer.',
                ], 200);
            }
            if ($code < 200 || $code >= 300) {
                wp_send_json_error([
                    'status'  => 'error',
                    'message' => $body['message'] ?? "Rooster returned HTTP {$code}",
                    'http'    => $code,
                ], 200);
            }

            wp_send_json_success($body);
        }

        public function aieo_handle_transfer_to_rooster() {
            if (!current_user_can(AIEO_CAPABILITY)) {
                wp_die(esc_html__('Unauthorized', 'ai-eshop-optimizer'));
            }
            check_admin_referer('aieo_transfer_to_rooster_action', 'aieo_transfer_to_rooster_nonce');

            $api_key = get_option('aieo_rooster_api_key');
            $hub_url = get_option('aieo_rooster_hub_url', 'https://rooster.systems');

            if (!$api_key || !get_option('aieo_rooster_enabled')) {
                update_option('aieo_rooster_transfer_message', 'Rooster connection not configured.');
                wp_safe_redirect(wp_get_referer() ?: admin_url('admin.php?page=ai-eshop-optimizer'));
                exit;
            }

            set_time_limit(300);
            global $wpdb;
            $orders_table = $wpdb->prefix . 'aieo_temp_orders';
            $base_url = rtrim($hub_url, '/') . '/wp-json/om-hub/v1';
            $headers = [
                'X-Content-Connector-Key' => $api_key,
                'Content-Type'            => 'application/json',
                'Accept'                  => 'application/json',
            ];

            
            $client_id = get_option('aieo_rooster_client_id', 0);
            $status_resp = wp_remote_get($base_url . '/content-connector/sync-status?client_id=' . (int) $client_id, [
                'headers' => $headers, 'timeout' => 15, 'sslverify' => false,
            ]);

            $orders_cursor = 0;
            if (!is_wp_error($status_resp)) {
                $status = json_decode(wp_remote_retrieve_body($status_resp), true);
                if (!empty($status['registered'])) {
                    $orders_cursor = (int) ($status['orders_cursor'] ?? 0);
                }
            }

            
            $batch_size = 500;
            $total_sent = 0;
            $max_order_id = $orders_cursor;
            $offset = 0;

            $vitals_table = $wpdb->prefix . 'aieo_core_product_vitals';
            $select_cols = "o.OrderId, o.OrderStatus, o.OrderDate, o.OrderSize, o.ItemSequence,
                o.PrimaryQty, o.LineValue, o.OrderItemsTotal, o.Price, o.RegularPrice, o.CurrentPrice, o.OnSale,
                o.ProductId, o.ParentProductId, o.SKU, o.ParentSKU,
                COALESCE(o.ItemName, pv.name) AS ItemName,
                COALESCE(o.ParentItemName, pv.parent_name) AS ParentItemName,
                o.Stock,
                COALESCE(o.ImageUrl, pv.image_url) AS ImageUrl,
                o.ProductUrl,
                o.CategoryName, o.MenuCategory, o.HeadCategory, o.SubCategory,
                o.BrandId, o.Brand, o.BrandSlug, o.Vendor,
                o.EponymousID, o.CustomerName, o.CustomerEmail, o.CustomerLocality,
                o.TotalCustomerOrders, o.TotalCustomerTurnover, o.AvgOrderSize, o.AvgSpend,
                o.LastTransactionDate, o.CurrentDBO, o.AvgDBO, o.CustomerSegment,
                o.TotalItemSales, o.DistinctOrderSales, o.TotalTurnover, o.ProfitabilityIndex,
                o.Fav1Product, o.Fav2Product, o.Fav3Product, o.Fav1Brand, o.Fav2Brand, o.Fav3Brand,
                o.Size, o.Color, o.Discontinued,
                pv.primary_need, pv.secondary_need, pv.other_needs";

            while (true) {
                $rows = $wpdb->get_results($wpdb->prepare(
                    "SELECT {$select_cols} FROM {$orders_table} o
                     LEFT JOIN {$vitals_table} pv ON pv.product_id = o.ProductId
                     WHERE o.OrderId > %d ORDER BY o.OrderId ASC LIMIT %d OFFSET %d",
                    $orders_cursor, $batch_size, $offset
                ), ARRAY_A);

                if (empty($rows)) break;

                foreach ($rows as &$row) {
                    
                    foreach ([] as $col) {
                        if (isset($row[$col]) && $row[$col] !== null) {
                            $row[$col] = bin2hex($row[$col]);
                        }
                    }
                    $oid = (int) $row['OrderId'];
                    if ($oid > $max_order_id) $max_order_id = $oid;
                }
                unset($row);

                $response = wp_remote_post($base_url . '/content-connector/ingest', [
                    'headers'   => $headers,
                    'body'      => wp_json_encode(['client_id' => (int) $client_id, 'rows' => $rows]),
                    'timeout'   => 60,
                    'sslverify' => false,
                ]);

                if (is_wp_error($response)) {
                    update_option('aieo_rooster_transfer_message', "Transfer failed at batch {$offset}: " . $response->get_error_message());
                    wp_safe_redirect(wp_get_referer() ?: admin_url('admin.php?page=ai-eshop-optimizer'));
                    exit;
                }

                $resp_code = wp_remote_retrieve_response_code($response);
                if ($resp_code < 200 || $resp_code >= 300) {
                    $resp_body = json_decode(wp_remote_retrieve_body($response), true);
                    update_option('aieo_rooster_transfer_message', 'Transfer failed: ' . ($resp_body['message'] ?? "HTTP {$resp_code}"));
                    wp_safe_redirect(wp_get_referer() ?: admin_url('admin.php?page=ai-eshop-optimizer'));
                    exit;
                }

                $total_sent += count($rows);
                $offset += $batch_size;

                if (count($rows) < $batch_size) break;
            }

            
            wp_remote_post($base_url . '/content-connector/sync-complete', [
                'headers'   => $headers,
                'body'      => wp_json_encode([
                    'client_id'      => (int) $client_id,
                    'orders_cursor'  => $max_order_id,
                ]),
                'timeout'   => 15,
                'sslverify' => false,
            ]);

            update_option('aieo_rooster_transfer_message', "Transfer complete: {$total_sent} rows synced (delta from OrderId > {$orders_cursor}).");
            update_option('aieo_rooster_last_sync', current_time('mysql', true));

            wp_safe_redirect(wp_get_referer() ?: admin_url('admin.php?page=ai-eshop-optimizer'));
            exit;
        }

        
        public function aieo_rooster_transfer_init() {
            check_ajax_referer('aieo_rooster_transfer_nonce', 'nonce');
            if (!current_user_can(AIEO_CAPABILITY)) wp_send_json_error(__('Unauthorized', 'ai-eshop-optimizer'));

            $api_key = get_option('aieo_rooster_api_key');
            $hub_url = get_option('aieo_rooster_hub_url', 'https://rooster.systems');
            $client_id = (int) get_option('aieo_rooster_client_id', 0);
            $mode = sanitize_text_field(wp_unslash($_POST['mode'] ?? 'delta'));

            if (!$api_key || !get_option('aieo_rooster_enabled') || !$client_id) {
                wp_send_json_error(__('Rooster connection not configured.', 'ai-eshop-optimizer'));
            }

            global $wpdb;
            $table = $wpdb->prefix . 'aieo_temp_orders';
            $base_url = rtrim($hub_url, '/') . '/wp-json/om-hub/v1';
            $headers = ['X-Content-Connector-Key' => $api_key, 'Accept' => 'application/json'];

            $orders_cursor = 0;

            if ($mode === 'full') {
                
                wp_remote_post($base_url . '/content-connector/reset', [
                    'headers' => array_merge($headers, ['Content-Type' => 'application/json']),
                    'body' => wp_json_encode(['client_id' => $client_id]),
                    'timeout' => 15, 'sslverify' => false,
                ]);
                
            } else {
                
                $status_resp = wp_remote_get($base_url . '/content-connector/sync-status?client_id=' . $client_id, [
                    'headers' => $headers, 'timeout' => 15, 'sslverify' => false,
                ]);
                if (!is_wp_error($status_resp)) {
                    $status = json_decode(wp_remote_retrieve_body($status_resp), true);
                    if (!empty($status['registered'])) {
                        $orders_cursor = (int) ($status['orders_cursor'] ?? 0);
                    }
                }
            }

            $total_rows = (int) $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM {$table} WHERE OrderId > %d", $orders_cursor
            ));

            wp_send_json_success([
                'total_rows'     => $total_rows,
                'orders_cursor'  => $orders_cursor,
                'client_id'      => $client_id,
                'batch_size'     => 500,
            ]);
        }

        
        public function aieo_rooster_transfer_batch() {
            check_ajax_referer('aieo_rooster_transfer_nonce', 'nonce');
            if (!current_user_can(AIEO_CAPABILITY)) wp_send_json_error(__('Unauthorized', 'ai-eshop-optimizer'));

            $api_key    = get_option('aieo_rooster_api_key');
            $hub_url    = get_option('aieo_rooster_hub_url', 'https://rooster.systems');
            $client_id  = isset($_POST['client_id'])  ? absint($_POST['client_id'])  : (int) get_option('aieo_rooster_client_id', 0);
            $cursor     = isset($_POST['cursor'])     ? absint($_POST['cursor'])     : 0;
            $batch_size = isset($_POST['batch_size']) ? absint($_POST['batch_size']) : 500;
            $offset     = isset($_POST['offset'])     ? absint($_POST['offset'])     : 0;

            global $wpdb;
            $table = $wpdb->prefix . 'aieo_temp_orders';
            $base_url = rtrim($hub_url, '/') . '/wp-json/om-hub/v1';

            
            
            $vitals_table = $wpdb->prefix . 'aieo_core_product_vitals';
            $select_cols = "o.OrderId, o.OrderStatus, o.OrderDate, o.OrderSize, o.ItemSequence,
                o.PrimaryQty, o.LineValue, o.OrderItemsTotal, o.Price, o.RegularPrice, o.CurrentPrice, o.OnSale,
                o.ProductId, o.ParentProductId, o.SKU, o.ParentSKU,
                COALESCE(o.ItemName, pv.name) AS ItemName,
                COALESCE(o.ParentItemName, pv.parent_name) AS ParentItemName,
                o.Stock,
                COALESCE(o.ImageUrl, pv.image_url) AS ImageUrl,
                o.ProductUrl, o.ERPId,
                o.CategoryId, o.CategoryName, o.MenuId, o.MenuCategory, o.HeadId, o.HeadCategory, o.SubcatId, o.SubCategory,
                o.TagId, o.TagName,
                o.BrandId, o.Brand, o.BrandSlug, o.Vendor, o.VendorId,
                o.EponymousID, o.EshopCustomerID, o.CustomerName, o.CustomerEmail, o.CustomerPhone,
                o.CustomerPostalCode, o.CustomerLocality, o.CustomerEshopSince, o.CustomerStoreSince,
                o.TotalCustomerItems, o.TotalCustomerOrders, o.TotalCustomerTurnover,
                o.AvgOrderSize, o.MaxOrderSize, o.MinOrderSize, o.AvgSpend, o.MaxSpend, o.MinSpend,
                o.LastTransactionDate, o.LastOrderSpend, o.CurrentDBO, o.AvgDBO, o.MaxDBO, o.MinDBO,
                o.CustomerDevice, o.CustomerSegment,
                o.TotalItemSales, o.DistinctOrderSales, o.TotalTurnover, o.UniqueItemSales, o.ProfitabilityIndex,
                o.Fav1Product, o.Fav2Product, o.Fav3Product,
                o.Fav1Brand, o.Fav2Brand, o.Fav3Brand,
                o.Fav1MainCat, o.Fav2MainCat, o.Fav3MainCat,
                o.Fav1Size, o.Fav2Size, o.Fav3Size,
                o.Fav1Color, o.Fav2Color, o.Fav3Color,
                o.Size, o.Color,
                o.GASource, o.GAMedium, o.GACampaign,
                o.Discontinued, o.RoleBasedSpecialPricing, o.HasReciprocal,
                pv.primary_need, pv.secondary_need, pv.other_needs,
                pv.primary_need_id, pv.secondary_need_id";

            $rows = $wpdb->get_results($wpdb->prepare(
                "SELECT {$select_cols}
                 FROM {$table} o
                 LEFT JOIN {$vitals_table} pv ON pv.product_id = o.ProductId
                 WHERE o.OrderId > %d ORDER BY o.OrderId ASC LIMIT %d OFFSET %d",
                $cursor, $batch_size, $offset
            ), ARRAY_A);

            if (empty($rows)) {
                
                wp_remote_post($base_url . '/content-connector/sync-complete', [
                    'headers' => [
                        'X-Content-Connector-Key' => $api_key,
                        'Content-Type' => 'application/json',
                        'Accept' => 'application/json',
                    ],
                    'body' => wp_json_encode(['client_id' => $client_id, 'orders_cursor' => $cursor]),
                    'timeout' => 15, 'sslverify' => false,
                ]);
                update_option('aieo_rooster_last_sync', current_time('mysql', true));
                wp_send_json_success(['done' => true, 'sent' => 0]);
            }

            $max_order_id = $cursor;
            foreach ($rows as &$row) {
                foreach ($uuid_cols as $col) {
                    if (isset($row[$col]) && $row[$col] !== null) {
                        $row[$col] = bin2hex($row[$col]);
                    }
                }
                $oid = (int) $row['OrderId'];
                if ($oid > $max_order_id) $max_order_id = $oid;
            }
            unset($row);

            $response = wp_remote_post($base_url . '/content-connector/ingest', [
                'headers' => [
                    'X-Content-Connector-Key' => $api_key,
                    'Content-Type' => 'application/json',
                    'Accept' => 'application/json',
                ],
                'body' => wp_json_encode(['client_id' => $client_id, 'rows' => $rows]),
                'timeout' => 60, 'sslverify' => false,
            ]);

            if (is_wp_error($response)) {
                
                wp_send_json_error(sprintf(__('Hub error: %s', 'ai-eshop-optimizer'), $response->get_error_message()));
            }

            $resp_code = wp_remote_retrieve_response_code($response);
            if ($resp_code < 200 || $resp_code >= 300) {
                $resp_body = json_decode(wp_remote_retrieve_body($response), true);
                
                wp_send_json_error(sprintf(__('Hub error: %s', 'ai-eshop-optimizer'), $resp_body['message'] ?? sprintf(__('HTTP %d', 'ai-eshop-optimizer'), $resp_code)));
            }

            $is_last = count($rows) < $batch_size;

            if ($is_last) {
                
                wp_remote_post($base_url . '/content-connector/sync-complete', [
                    'headers' => [
                        'X-Content-Connector-Key' => $api_key,
                        'Content-Type' => 'application/json',
                        'Accept' => 'application/json',
                    ],
                    'body' => wp_json_encode(['client_id' => $client_id, 'orders_cursor' => $max_order_id]),
                    'timeout' => 15, 'sslverify' => false,
                ]);
                update_option('aieo_rooster_last_sync', current_time('mysql', true));
            }

            wp_send_json_success([
                'done'       => $is_last,
                'sent'       => count($rows),
                'offset'     => $offset + $batch_size,
                'max_order'  => $max_order_id,
            ]);
        }
    }
}

if (!class_exists('aieo_UTM_appender')) {
    class aieo_UTM_appender
    {

        public function __construct()
        {
            add_filter('post_type_link', array($this, 'aieo_custom_product_title_link'), 10, 2);
            add_filter('woocommerce_product_add_to_cart_url', array($this, 'aieo_modify_add_to_cart_url'), 10, 2);
            add_action('wp_enqueue_scripts', array($this, 'enqueue_gtag_script'));
        }

        public function enqueue_gtag_script()
        {
            
            
            
            
            $aieo_ga_owns = ! class_exists('AIEO_DMM_Conversions')
                || 'aieo' === AIEO_DMM_Conversions::get_config()['ga_source'];
            if (is_product() && get_option('aieo_activate_utm_stats') == 1 && $aieo_ga_owns) {
                
                

               wp_enqueue_script('gtag-event-script', plugin_dir_url(__FILE__) . 'js/ai-eshop-optimizer-googleGTM.js', array(), AIEO_VERSION, true);

                
                $script_data = array(
                    'aieo_google_ga4' => get_option('aieo_google_ga4', 'default_value_if_not_set')
                );
                wp_localize_script('gtag-event-script', 'myLocalizedData', $script_data);
            }
        }

        public function aieo_custom_product_title_link($url, $post)
        {
            
            if ($post->post_type !== 'product' || !is_product() || get_option('aieo_activate_utm_stats') != 1) {
                return $url;
            }

            global $woocommerce_loop;
            $main_product_id = get_queried_object_id();
            $target_product_id = $post->ID;

            if (isset($woocommerce_loop['name']) && $woocommerce_loop['name'] == 'upsells') {
                $utm_parameters = array(
                    'utm_source' => 'AIOUpSell',
                    'utm_campaign' =>  'aieo_internal_' . $woocommerce_loop['loop'] . '_' . $main_product_id . '_' . $target_product_id
                );
            } elseif (isset($woocommerce_loop['name']) && $woocommerce_loop['name'] == 'cross-sells') {
                $utm_parameters = array(
                    'utm_source' => 'AIOCrossSell',
                    'utm_campaign' =>  'aieo_internal_' . $woocommerce_loop['loop'] . '_' . $main_product_id . '_' . $target_product_id
                );
            } elseif (isset($woocommerce_loop['name']) && $woocommerce_loop['name'] == 'related') {
                $utm_parameters = array(
                    'utm_source' => 'AIOWooRANDRelated',
                    'utm_campaign' =>  'aieo_internal_' . $woocommerce_loop['loop'] . '_' . $main_product_id . '_' . $target_product_id
                );
            } elseif (isset($woocommerce_loop['name']) && $woocommerce_loop['name'] == 'recently-viewed') {
                $utm_parameters = array(
                    'utm_source' => 'AIORecentlyViewed',
                    'utm_campaign' =>  'aieo_internal_' . $woocommerce_loop['loop'] . '_' . $main_product_id . '_' . $target_product_id
                );
            } else {
                return $url;
            }
            return add_query_arg($utm_parameters, $url);
        }

        public function aieo_modify_add_to_cart_url($url, $product)
        {
            global $woocommerce_loop;

            if (!is_product() || get_option('aieo_activate_utm_stats') != 1) {
                return $url;
            }

            $main_product_id = get_queried_object_id();
            $target_product_id = $product->get_id();

            $utm_base_parameters = array();

            
            switch ($woocommerce_loop['name']) {
                case 'upsells':
                    $utm_parameters = array_merge($utm_base_parameters, array(
                        'utm_source' => 'AIOCartUpSell',
                        'utm_campaign' =>  'aieo_internal_' . $woocommerce_loop['loop'] . '_' . $main_product_id . '_' . $target_product_id
                    ));
                    break;

                case 'cross-sells':
                    $utm_parameters = array_merge($utm_base_parameters, array(
                        'utm_source' => 'AIOCartCrossSell',
                        'utm_campaign' =>  'aieo_internal_' . $woocommerce_loop['loop'] . '_' . $main_product_id . '_' . $target_product_id
                    ));
                    break;

                case 'related':
                    $utm_parameters = array_merge($utm_base_parameters, array(
                        'utm_source' => 'AIOCartWooRANDRelated',
                        'utm_campaign' =>  'aieo_internal_' . $woocommerce_loop['loop'] . '_' . $main_product_id . '_' . $target_product_id
                    ));
                    break;

                case 'recently-viewed':
                    $utm_parameters = array_merge($utm_base_parameters, array(
                        'utm_source' => 'AIOCartRecentlyViewed',
                        'utm_campaign' =>  'aieo_internal_' . $woocommerce_loop['loop'] . '_' . $main_product_id . '_' . $target_product_id
                    ));
                    break;

                default:
                    return $url;
            }
            return add_query_arg($utm_parameters, $url);
        }
    }

    if (get_option('aieo_activate_utm_stats') == 1) {
        new aieo_UTM_appender();
    }
}

if (!class_exists('aieo_display_recommendations')) {
    class aieo_display_recommendations
    {
        
        private $has_recommendations = false;

        
        private $enabled_types = [];

        
        private $effective_prices_cache = array();

        public function __construct()
        {
            
            add_action('wp_ajax_aieo_get_recommendations', array($this, 'ajax_get_recommendations'));
            add_action('wp_ajax_nopriv_aieo_get_recommendations', array($this, 'ajax_get_recommendations'));

            
            
            
            if ( ! defined( 'AIEO_RUNTIME_OWNS_AJAX' ) ) {
                add_action('wp_ajax_aieo_get_product_bundle', array($this, 'ajax_get_product_bundle'));
                add_action('wp_ajax_nopriv_aieo_get_product_bundle', array($this, 'ajax_get_product_bundle'));
                add_action('wp_ajax_aieo_get_recently_viewed_html', array($this, 'ajax_get_recently_viewed_html_only'));
                add_action('wp_ajax_nopriv_aieo_get_recently_viewed_html', array($this, 'ajax_get_recently_viewed_html_only'));
                add_action('wp_ajax_aieo_get_products_dtos', array($this, 'ajax_get_products_dtos'));
                add_action('wp_ajax_nopriv_aieo_get_products_dtos', array($this, 'ajax_get_products_dtos'));
            }
            add_action('wp_ajax_nopriv_aieo_get_recommendations', array($this, 'ajax_get_recommendations'));

            $display_order = get_option('aieo_recommendations_display_order', 0);
            $display_order = ($display_order == 1) ? 1 : 0;

            if ($display_order == 1) {
                $upsell_priority = 20;
                $cross_sell_priority = 15;
            } else {
                $upsell_priority = 15;
                $cross_sell_priority = 20;
            }

            
            $display_upsells = get_option('aieo_display_upsells', 0);
            $display_upsells = $display_upsells == 1 ? 1 : 0;

            if ($display_upsells == 1) {
                remove_action('woocommerce_after_single_product_summary', 'woocommerce_upsell_display', 15);
                add_action('woocommerce_after_single_product_summary', array($this, 'aieo_show_upsell_placeholder'), $upsell_priority);
                $this->has_recommendations = true;
                $this->enabled_types[] = 'upsells';
            } else {
                remove_action('woocommerce_after_single_product_summary', 'woocommerce_upsell_display', 15);
            }

            
            $display_cross_sells = get_option('aieo_display_cross_sells', 0);
            $display_cross_sells = $display_cross_sells == 1 ? 1 : 0;

            if ($display_cross_sells == 1) {
                add_action('woocommerce_after_single_product_summary', array($this, 'aieo_show_cross_sell_placeholder'), $cross_sell_priority);
                $this->has_recommendations = true;
                $this->enabled_types[] = 'crosssells';
            }

            
            $display_related = get_option('aieo_display_related', 0);
            $display_related = $display_related == 1 ? 1 : 0;

            if ($display_related == 1) {
                remove_action('woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 20);
                add_action('woocommerce_after_single_product_summary', array($this, 'aieo_show_related_placeholder'), 20);
                $this->has_recommendations = true;
                $this->enabled_types[] = 'related';
            } else {
                remove_action('woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 20);
            }

            
            $display_recently_viewed_products = get_option('aieo_display_recently_viewed_products', 0);
            $display_recently_viewed_products = $display_recently_viewed_products == 1 ? 1 : 0;

            if ($display_recently_viewed_products == 1) {
                remove_action('woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 30);
                add_action('woocommerce_after_single_product_summary', array($this, 'aieo_show_recently_viewed_placeholder'), 30);
                $this->has_recommendations = true;
                $this->enabled_types[] = 'recently_viewed';

                
                
                
                
                
                
                
                
                add_action('template_redirect', array($this, 'aieo_track_recently_viewed'), 25);
            } else {
                remove_action('woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 30);
            }

            
            $display_same_needs = get_option('aieo_display_same_needs', 0);
            $display_same_needs = $display_same_needs == 1 ? 1 : 0;

            if ($display_same_needs == 1) {
                add_action('woocommerce_after_single_product_summary', array($this, 'aieo_show_same_needs_placeholder'), 10);
                $this->has_recommendations = true;
                $this->enabled_types[] = 'same_needs';
            }

            
            if ($this->has_recommendations) {
                add_action('wp_enqueue_scripts', array($this, 'enqueue_lazy_loader_script'));
            }
        }

        
        public function enqueue_lazy_loader_script()
        {
            if (!is_singular('product')) {
                return;
            }

            
            
            
            $_aieo_recos_js_path = AIEO_DIR . 'assets/js/lazy-recommendations-v7.js';
            $_aieo_recos_js_ver  = file_exists($_aieo_recos_js_path)
                ? (string) filemtime($_aieo_recos_js_path)
                : AIEO_VERSION;
            wp_enqueue_script(
                'aieo-lazy-recommendations',
                AIEO_URI . 'assets/js/lazy-recommendations-v7.js',
                array('jquery'),
                $_aieo_recos_js_ver,
                true
            );

            
            
            
            $reco_css_path = AIEO_DIR . 'assets/css/aieo-recommendations.css';
            $reco_css_ver  = file_exists($reco_css_path) ? (string) filemtime($reco_css_path) : AIEO_VERSION;
            wp_enqueue_style(
                'aieo-recommendations',
                AIEO_URI . 'assets/css/aieo-recommendations.css',
                array(),
                $reco_css_ver
            );

            global $post;

            
            
            
            
            $bundle_enabled = false;
            $bundle_mode    = 'rec_only';
            if (class_exists('AIEO_DMM_Settings')) {
                $bundle_mode = AIEO_DMM_Settings::get('bundle_mode', 'full');
                $bundle_enabled = in_array($bundle_mode, array('full', 'rec_only'), true);
            }

            wp_localize_script('aieo-lazy-recommendations', 'aieoRecommendationsConfig', array(
                'ajaxUrl'        => admin_url('admin-ajax.php'),
                'nonce'          => wp_create_nonce('aieo_recommendations'),
                'productId'      => $post ? $post->ID : 0,
                'types'          => $this->enabled_types,
                
                
                
                'bundleEnabled'  => $bundle_enabled,
                'bundleMode'     => $bundle_mode,
                'rvLocalTtlMs'   => 30 * 60 * 1000,       
                
                
                'rvLocalKey'     => 'aieo_rv_cache_v4',
                'sectionTitles'  => array(
                    'upsells'         => __('Up-sell Recommendations', 'ai-eshop-optimizer'),
                    'crosssells'      => __('Cross-sell Recommendations', 'ai-eshop-optimizer'),
                    'related'         => __('Related Products Recommendations', 'ai-eshop-optimizer'),
                    'same_needs'      => __('Products for the Same Needs', 'ai-eshop-optimizer'),
                    'recently_viewed' => __('Recently Viewed Products Recommendations', 'ai-eshop-optimizer'),
                ),
                
                
                
                
                
                
                'badgePlacements' => class_exists('AIEO_DMM_Badges')
                    ? AIEO_DMM_Badges::get_settings()['placements']
                    : array(
                        'archive'   => array('location' => 'below_favourite', 'shape' => 'circle'),
                        'pdp'       => array('location' => 'top_left',         'shape' => 'chip'),
                        'recos'     => array('location' => 'inline',           'shape' => 'chip'),
                        'side_cart' => array('location' => 'inline',           'shape' => 'chip'),
                    ),
                
                
                
                
                'badgeSizes' => class_exists('AIEO_DMM_Badges')
                    ? AIEO_DMM_Badges::get_settings()['sizes']
                    : array(),
            ));
        }

        
        public function ajax_get_recommendations()
        {
            check_ajax_referer('aieo_recommendations', 'nonce');

            
            
            
            $site_locale = get_locale();
            $switched_locale = false;
            if ( function_exists( 'switch_to_locale' ) && determine_locale() !== $site_locale ) {
                switch_to_locale( $site_locale );
                $switched_locale = true;
            }

            
            
            if ( is_textdomain_loaded( 'ai-eshop-optimizer' ) ) {
                unload_textdomain( 'ai-eshop-optimizer' );
            }

            $lang_dir = AIEO_DIR . 'languages/';
            $locales_to_try = array( $site_locale );
            if ( strpos( $site_locale, '_' ) !== false ) {
                $locales_to_try[] = substr( $site_locale, 0, strpos( $site_locale, '_' ) );
            }

            foreach ( $locales_to_try as $try_locale ) {
                $mofile = $lang_dir . 'ai-eshop-optimizer-' . $try_locale . '.mo';
                if ( file_exists( $mofile ) ) {
                    load_textdomain( 'ai-eshop-optimizer', $mofile );
                    break;
                }
            }

            $type = isset($_POST['type']) ? sanitize_text_field(wp_unslash($_POST['type'])) : '';
            $product_id = isset($_POST['product_id']) ? absint(wp_unslash($_POST['product_id'])) : 0;

            if (empty($type) || empty($product_id)) {
                wp_send_json_error(array('message' => __('Invalid parameters', 'ai-eshop-optimizer')));
            }

            
            $cacheable_types = array('upsells', 'crosssells', 'related', 'same_needs');

            
            if (in_array($type, $cacheable_types, true) && class_exists('AIEO_Recommendations_Cache')) {
                $cached = AIEO_Recommendations_Cache::get($product_id, $type);
                if ($cached !== false && isset($cached['html'])) {
                    wp_send_json_success(array(
                        'html' => $cached['html'],
                        'cached' => true,
                    ));
                }
            }

            
            global $product, $post;
            $post = get_post($product_id);
            if (!$post || $post->post_type !== 'product') {
                wp_send_json_error(array('message' => __('Product not found', 'ai-eshop-optimizer')));
            }
            setup_postdata($post);
            $product = wc_get_product($product_id);

            $html = '';
            switch ($type) {
                case 'upsells':
                    $html = $this->get_upsell_html();
                    break;
                case 'crosssells':
                    $html = $this->get_cross_sell_html();
                    break;
                case 'related':
                    $html = $this->get_related_html();
                    break;
                case 'recently_viewed':
                    
                    $html = $this->get_recently_viewed_html();
                    break;
                case 'same_needs':
                    $html = $this->get_same_needs_html();
                    break;
            }

            wp_reset_postdata();

            
            if (in_array($type, $cacheable_types, true) && class_exists('AIEO_Recommendations_Cache') && !empty($html)) {
                AIEO_Recommendations_Cache::set($product_id, $type, array('html' => $html));
            }

            
            if ( $switched_locale && function_exists( 'restore_previous_locale' ) ) {
                restore_previous_locale();
            }

            wp_send_json_success(array('html' => $html));
        }

        
        public function ajax_get_product_bundle()
        {
            check_ajax_referer('aieo_recommendations', 'nonce');

            $product_id = isset($_POST['product_id']) ? absint(wp_unslash($_POST['product_id'])) : 0;
            if ($product_id <= 0) {
                wp_send_json_error(array('message' => __('Invalid product id', 'ai-eshop-optimizer')));
            }

            
            
            $mode = 'full';
            if (class_exists('AIEO_DMM_Settings')) {
                $stored = AIEO_DMM_Settings::get('bundle_mode', 'full');
                if ($stored === 'rec_only' || $stored === 'full') {
                    $mode = $stored;
                }
            }
            
            
            
            
            
            
            
            
            
            $relation_type = $mode === 'rec_only' ? 'bundle_rec_only_v9' : 'bundle_full_v9';

            
            
            
            
            $role_hash = $this->aieo_bundle_role_hash();
            $site_locale = function_exists('get_locale') ? get_locale() : 'en_US';

            
            
            if (class_exists('AIEO_Recommendations_Cache')) {
                $cached = AIEO_Recommendations_Cache::get($product_id, $relation_type);
                if ($cached !== false && is_array($cached)
                    && isset($cached['role_hash']) && $cached['role_hash'] === $role_hash
                    && isset($cached['locale']) && $cached['locale'] === $site_locale) {
                    $cached['cached'] = true;
                    $cached['rv_hint'] = $this->aieo_bundle_rv_hint();
                    wp_send_json_success($cached);
                }
            }

            
            
            
            $switched_locale = false;
            if (function_exists('switch_to_locale') && determine_locale() !== $site_locale) {
                switch_to_locale($site_locale);
                $switched_locale = true;
            }
            if (is_textdomain_loaded('ai-eshop-optimizer')) {
                unload_textdomain('ai-eshop-optimizer');
            }
            $lang_dir = AIEO_DIR . 'languages/';
            $locales_to_try = array($site_locale);
            if (strpos($site_locale, '_') !== false) {
                $locales_to_try[] = substr($site_locale, 0, strpos($site_locale, '_'));
            }
            foreach ($locales_to_try as $try_locale) {
                $mofile = $lang_dir . 'ai-eshop-optimizer-' . $try_locale . '.mo';
                if (file_exists($mofile)) {
                    load_textdomain('ai-eshop-optimizer', $mofile);
                    break;
                }
            }

            
            
            global $product, $post;
            $post = get_post($product_id);
            if (!$post || $post->post_type !== 'product') {
                wp_send_json_error(array('message' => __('Product not found', 'ai-eshop-optimizer')));
            }
            setup_postdata($post);
            $product = wc_get_product($product_id);
            if (!$product) {
                wp_send_json_error(array('message' => __('Product not loaded', 'ai-eshop-optimizer')));
            }

            
            
            
            $this->aieo_bundle_preload_related_prices($product, $mode);

            
            
            
            
            $upsells    = $this->get_upsell_dtos();
            $crosssells = $this->get_cross_sell_dtos();
            $needs      = $this->get_same_needs_dtos();
            $related    = $this->get_related_dtos();

            $variations = null;
            if ($mode === 'full') {
                $variations = $this->aieo_bundle_variations_payload($product);
            }

            wp_reset_postdata();

            
            
            
            
            
            
            $seed_dto = $this->build_product_dto($product);
            if (is_array($seed_dto)) {
                $seed_dto['short_description'] = (string) $product->get_short_description();
            }

            
            
            
            
            $attribute_labels          = $this->aieo_bundle_attribute_labels($product);
            
            
            
            
            $attribute_taxonomy_labels = $this->aieo_bundle_attribute_taxonomy_labels($product);

            $blob = array(
                'product_id'                => $product_id,
                'mode'                      => $mode,
                'role_hash'                 => $role_hash,
                'locale'                    => $site_locale,
                'seed'                      => $seed_dto,
                'upsells'                   => $upsells,
                'crosssells'                => $crosssells,
                'needs'                     => $needs,
                'related'                   => $related,
                'variations'                => $variations,
                'attribute_labels'          => $attribute_labels,
                'attribute_taxonomy_labels' => $attribute_taxonomy_labels,
                'built_at'                  => time(),
            );

            if (class_exists('AIEO_Recommendations_Cache')) {
                AIEO_Recommendations_Cache::set($product_id, $relation_type, $blob);
            }

            if ($switched_locale && function_exists('restore_previous_locale')) {
                restore_previous_locale();
            }

            $blob['cached'] = false;
            $blob['rv_hint'] = $this->aieo_bundle_rv_hint();
            wp_send_json_success($blob);
        }

        
        public function ajax_get_recently_viewed_html_only()
        {
            check_ajax_referer('aieo_recommendations', 'nonce');

            
            
            
            $products = $this->get_recently_viewed_dtos();

            wp_send_json_success(array(
                'products' => $products,
                'ids'      => $this->aieo_bundle_rv_hint(),
                'built_at' => time(),
            ));
        }

        
        public function ajax_get_products_dtos()
        {
            check_ajax_referer('aieo_recommendations', 'nonce');

            $ids = array();
            if (isset($_POST['ids'])) {
                $raw = is_array($_POST['ids']) ? array_map('absint', wp_unslash($_POST['ids'])) : sanitize_text_field(wp_unslash($_POST['ids']));
                if (is_string($raw)) {
                    $raw = array_map('trim', explode(',', $raw));
                }
                if (is_array($raw)) {
                    foreach ($raw as $id) {
                        $id = (int) $id;
                        if ($id > 0) { $ids[] = $id; }
                    }
                }
            }
            $ids = array_values(array_unique($ids));
            if (count($ids) > 50) {
                $ids = array_slice($ids, 0, 50);
            }
            $products = $this->build_product_dtos($ids);

            wp_send_json_success(array(
                'products' => $products,
                'built_at' => time(),
            ));
        }

        
        private function aieo_bundle_role_hash()
        {
            $user_id = get_current_user_id();
            $roles = array('guest');
            if ($user_id > 0) {
                $u = get_userdata($user_id);
                if ($u && !empty($u->roles) && is_array($u->roles)) {
                    $roles = $u->roles;
                }
            }
            sort($roles);

            $loyalty = array();
            if ($user_id > 0 && class_exists('AIEO_DMM_Pricing_Engine')) {
                $loyalty = AIEO_DMM_Pricing_Engine::instance()->get_loyalty_class_ids_for_user($user_id);
                sort($loyalty);
            }

            return substr(md5(implode(',', $roles) . '|' . implode(',', $loyalty)), 0, 12);
        }

        
        private function aieo_bundle_rv_hint()
        {
            $cookie = isset($_COOKIE['woocommerce_recently_viewed']) ? sanitize_text_field(wp_unslash($_COOKIE['woocommerce_recently_viewed'])) : '';
            if ($cookie === '') {
                return array();
            }
            $ids = array_filter(array_map('absint', explode('|', $cookie)));
            
            
            
            
            return array_slice(array_values(array_reverse($ids)), 0, 15);
        }

        
        private function aieo_bundle_preload_related_prices($product, $mode)
        {
            if (!class_exists('AIEO_DMM_Pricing_Engine') || !is_a($product, 'WC_Product')) {
                return;
            }
            $ids = array();
            $collect = function ($arr) use (&$ids) {
                if (is_array($arr)) { $ids = array_merge($ids, $arr); }
            };
            $collect($product->get_upsell_ids());
            $collect($product->get_cross_sell_ids());
            if (function_exists('wc_get_related_products')) {
                $collect(wc_get_related_products($product->get_id(), 12));
            }
            if ($mode === 'full' && $product->is_type('variable')) {
                $collect($product->get_children());
            }
            $ids = array_filter(array_map('intval', array_unique($ids)));
            if (!empty($ids)) {
                AIEO_DMM_Pricing_Engine::instance()->preload_role_prices($ids);
            }
        }

        
        private function aieo_bundle_variations_payload($product)
        {
            if (!is_a($product, 'WC_Product') || !$product->is_type('variable')) {
                return null;
            }
            if (!is_callable(array($product, 'get_available_variations'))) {
                return null;
            }
            $data = $product->get_available_variations();
            
            
            
            return apply_filters('aieo_bundle_variations_payload', $data, $product);
        }

        
        private function aieo_bundle_attribute_labels($product)
        {
            $out = array();
            if (!is_a($product, 'WC_Product') || !$product->is_type('variable')) {
                return $out;
            }
            $attributes = $product->get_variation_attributes();
            if (empty($attributes) || !is_array($attributes)) {
                return $out;
            }
            foreach ($attributes as $attribute_name => $values) {
                
                
                
                $key = 'attribute_' . sanitize_title($attribute_name);
                $map = array();
                if (taxonomy_exists($attribute_name)) {
                    foreach ((array) $values as $slug) {
                        $term = get_term_by('slug', $slug, $attribute_name);
                        $raw  = ($term && !is_wp_error($term)) ? $term->name : $slug;
                        
                        
                        
                        
                        
                        
                        
                        $map[$slug] = html_entity_decode((string) $raw, ENT_QUOTES | ENT_HTML5, 'UTF-8');
                    }
                } else {
                    
                    foreach ((array) $values as $val) {
                        $map[$val] = html_entity_decode((string) $val, ENT_QUOTES | ENT_HTML5, 'UTF-8');
                    }
                }
                $out[$key] = $map;
            }
            return $out;
        }

        
        private function aieo_bundle_attribute_taxonomy_labels($product)
        {
            $out = array();
            if (!is_a($product, 'WC_Product') || !$product->is_type('variable')) {
                return $out;
            }
            $attributes = $product->get_variation_attributes();
            if (empty($attributes) || !is_array($attributes)) {
                return $out;
            }
            foreach ($attributes as $attribute_name => $values) {
                $key      = 'attribute_' . sanitize_title($attribute_name);
                $out[$key] = (string) wc_attribute_label((string) $attribute_name);
            }
            return $out;
        }

        
        private function has_instock_products($product_ids)
        {
            if (empty($product_ids) || !is_array($product_ids)) {
                return false;
            }

            foreach ($product_ids as $product_id) {
                $product = wc_get_product($product_id);
                if ($product && $product->is_in_stock()) {
                    return true;
                }
            }

            return false;
        }

        
        private function filter_instock_products($product_ids)
        {
            if (empty($product_ids) || !is_array($product_ids)) {
                return array();
            }

            $instock_ids = array();
            foreach ($product_ids as $product_id) {
                $product = wc_get_product($product_id);
                if ($product && $product->is_in_stock()) {
                    $instock_ids[] = $product_id;
                }
            }

            
            
            
            
            return (array) apply_filters('aieo_reco_filter_candidates', $instock_ids, $product_ids);
        }

        
        private function output_placeholder($id, $type, $title)
        {
            $placeholder_img = function_exists('wc_placeholder_img_src') ? wc_placeholder_img_src('woocommerce_thumbnail') : '';
            ?>
            <section id="<?php echo esc_attr($id); ?>" class="related products aieo-recommendation-placeholder" data-type="<?php echo esc_attr($type); ?>">
                <h2><?php echo esc_html($title); ?></h2>
                <ul class="products columns-4">
                    <?php for ($i = 0; $i < 4; $i++) : ?>
                    <li class="product aieo-skeleton-item">
                        <div class="aieo-skeleton-image">
                            <?php if ($placeholder_img) : ?>
                                <img src="<?php echo esc_url($placeholder_img); ?>" alt="" loading="lazy">
                            <?php endif; ?>
                        </div>
                        <div class="aieo-skeleton-title"></div>
                        <div class="aieo-skeleton-price"></div>
                    </li>
                    <?php endfor; ?>
                </ul>
            </section>
            <style>
            .aieo-skeleton-item { background: #f5f5f5; padding: 10px; }
            .aieo-skeleton-image { background: #f0f0f0; }
            .aieo-skeleton-image img { width: 100%; height: auto; display: block; opacity: 0.6; }
            .aieo-skeleton-title { height: 20px; margin: 10px 0 5px; width: 80%; background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%); background-size: 200% 100%; animation: aieo-shimmer 1.5s infinite; }
            .aieo-skeleton-price { height: 16px; width: 40%; background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%); background-size: 200% 100%; animation: aieo-shimmer 1.5s infinite; }
            @keyframes aieo-shimmer { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } }
            </style>
            <?php
        }

        
        public function aieo_show_upsell_placeholder()
        {
            global $post;

            if (!$post || $post->post_type !== 'product') {
                return;
            }

            $upsells = get_post_meta($post->ID, '_upsell_ids', true);
            if (empty($upsells) || !is_array($upsells)) {
                return;
            }

            
            if (!$this->has_instock_products($upsells)) {
                return;
            }

            $this->output_placeholder('aieo-up-sells-placeholder', 'upsells', __('Up-sell Recommendations ', 'ai-eshop-optimizer'));
        }

        
        public function aieo_show_cross_sell_placeholder()
        {
            global $post;

            if (!$post || $post->post_type !== 'product') {
                return;
            }

            $crosssells = get_post_meta($post->ID, '_crosssell_ids', true);
            if (empty($crosssells) || !is_array($crosssells)) {
                return;
            }

            
            if (!$this->has_instock_products($crosssells)) {
                return;
            }

            $this->output_placeholder('aieo-cross-sells-placeholder', 'crosssells', __('Cross-sell Recommendations ', 'ai-eshop-optimizer'));
        }

        
        public function aieo_show_related_placeholder()
        {
            global $product;

            if (!$product || !is_a($product, 'WC_Product')) {
                return;
            }

            $related_ids = wc_get_related_products($product->get_id(), 6);
            if (empty($related_ids)) {
                return;
            }

            
            if (!$this->has_instock_products($related_ids)) {
                return;
            }

            $this->output_placeholder('aieo-related-placeholder', 'related', __('Related Products Recommendations ', 'ai-eshop-optimizer'));
        }

        
        public function aieo_show_recently_viewed_placeholder()
        {
            $this->output_placeholder('aieo-recently-viewed-placeholder', 'recently_viewed', __('Recently Viewed Products Recommendations', 'ai-eshop-optimizer'));
        }

        
        public function aieo_track_recently_viewed()
        {
            if (!is_singular('product')) {
                return;
            }
            global $post;
            if (!$post || $post->post_type !== 'product') {
                return;
            }

            $viewed = array();
            if (!empty($_COOKIE['woocommerce_recently_viewed'])) {
                $raw = wp_unslash($_COOKIE['woocommerce_recently_viewed']); 
                $viewed = wp_parse_id_list(explode('|', (string) $raw));
            }

            
            
            $viewed = array_values(array_diff($viewed, array($post->ID)));
            array_unshift($viewed, (int) $post->ID);
            $viewed = array_slice(array_unique(array_map('absint', $viewed)), 0, 15);

            if (function_exists('wc_setcookie')) {
                wc_setcookie('woocommerce_recently_viewed', implode('|', $viewed));
            }
        }

        
        public function aieo_show_same_needs_placeholder()
        {
            global $post, $wpdb;

            if (!$post || $post->post_type !== 'product') {
                return;
            }

            $product_id = $post->ID;

            
            $parent_id = wp_get_post_parent_id($product_id);
            if ($parent_id) {
                $product_id = $parent_id;
            }

            
            $suggestions_table = $wpdb->prefix . 'aieo_product_need_suggestions';
            $suggestions_json = $wpdb->get_var($wpdb->prepare(
                "SELECT suggested_products FROM {$suggestions_table}
                 WHERE product_id = %d
                 LIMIT 1",
                $product_id
            ));

            
            if (!$suggestions_json) {
                return;
            }

            $suggested_ids = json_decode($suggestions_json, true);
            if (empty($suggested_ids) || !is_array($suggested_ids)) {
                return;
            }

            
            if (!$this->has_instock_products($suggested_ids)) {
                return;
            }

            $this->output_placeholder('aieo-same-needs-placeholder', 'same_needs', __('Products for the Same Needs', 'ai-eshop-optimizer'));
        }

        
        private function get_recently_viewed_html()
        {
            
            $viewed_products = array();
            if (!empty($_COOKIE['woocommerce_recently_viewed'])) {
                $recently_viewed = sanitize_text_field(wp_unslash($_COOKIE['woocommerce_recently_viewed']));
                $viewed_products = array_reverse(array_filter(array_map('absint', explode('|', $recently_viewed))));
            }

            if (empty($viewed_products)) {
                return '';
            }

            $args = array(
                'post_type'      => 'product',
                'posts_per_page' => 5,
                'no_found_rows'  => 1,
                'post_status'    => 'publish',
                'post__in'       => $viewed_products,
                'orderby'        => 'post__in',
            );

            $products = new WP_Query($args);

            if (!$products->have_posts()) {
                wp_reset_postdata();
                return '';
            }

            ob_start();
            echo '<section id="aieo-recently-viewed" class="related recently-viewed products"><h2>' . esc_html__('Recently Viewed Products Recommendations', 'ai-eshop-optimizer') . '</h2>';
            woocommerce_product_loop_start();
            while ($products->have_posts()) : $products->the_post();
                global $woocommerce_loop;
                $woocommerce_loop['name'] = 'recently-viewed';
                wc_get_template_part('content', 'product');
            endwhile;
            woocommerce_product_loop_end();
            echo '</section>';
            wp_reset_postdata();

            return ob_get_clean();
        }

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        

        
        private function build_product_dto($product)
        {
            if (!$product || !is_a($product, 'WC_Product')) {
                return null;
            }

            $image_id = (int) $product->get_image_id();
            if ($image_id <= 0) {
                $parent_id = (int) $product->get_parent_id();
                if ($parent_id > 0) {
                    $parent = wc_get_product($parent_id);
                    if ($parent) {
                        $image_id = (int) $parent->get_image_id();
                    }
                }
            }

            $image = array(
                'src'    => '',
                'srcset' => '',
                'sizes'  => '',
                'width'  => 0,
                'height' => 0,
                'alt'    => $product->get_name(),
            );
            if ($image_id > 0) {
                $src = wp_get_attachment_image_src($image_id, 'woocommerce_thumbnail');
                if ($src) {
                    $image['src']    = (string) $src[0];
                    $image['width']  = (int) $src[1];
                    $image['height'] = (int) $src[2];
                }
                $srcset = wp_get_attachment_image_srcset($image_id, 'woocommerce_thumbnail');
                if ($srcset) { $image['srcset'] = (string) $srcset; }
                $sizes = wp_get_attachment_image_sizes($image_id, 'woocommerce_thumbnail');
                if ($sizes) { $image['sizes'] = (string) $sizes; }
                $alt = (string) get_post_meta($image_id, '_wp_attachment_image_alt', true);
                if ($alt !== '') { $image['alt'] = $alt; }
            } elseif (function_exists('wc_placeholder_img_src')) {
                $image['src'] = (string) wc_placeholder_img_src('woocommerce_thumbnail');
            }

            
            
            
            
            
            
            $price_html = $this->build_clean_price_html($product);

            
            
            
            
            
            $role_badge = $this->build_role_badge_dto($product);

            
            
            
            
            $on_sale = (bool) $product->is_on_sale();
            if ($role_badge !== null) { $on_sale = false; }

            
            
            
            
            
            
            
            
            $badge_dtos = array();
            if (class_exists('AIEO_DMM_Badge_Renderer')) {
                $badge_dtos = AIEO_DMM_Badge_Renderer::dto_for_product($product, 'recos');
            }

            
            
            
            $short_desc  = wp_trim_words(wp_strip_all_tags((string) $product->get_short_description()), 25, '…');
            $rating_html = '';
            if (class_exists('AIEO_Ratings')) {
                $ratings = AIEO_Ratings::instance();
                if ($ratings && method_exists($ratings, 'render_aggregate_html')) {
                    $rating_html = (string) $ratings->render_aggregate_html((int) $product->get_id());
                }
            }

            return array(
                'id'         => (int) $product->get_id(),
                'name'       => $product->get_name(),
                
                
                
                
                
                'permalink'  => $product->get_permalink(),
                'sku'        => (string) $product->get_sku(),
                'type'       => (string) $product->get_type(),
                'on_sale'    => $on_sale,
                'in_stock'   => (bool) $product->is_in_stock(),
                'image'      => $image,
                'price_html' => $price_html,
                'role_badge' => $role_badge,
                'badges'     => $badge_dtos,
                'short_description' => $short_desc,
                'rating_html'       => $rating_html,
            );
        }

        
        private function build_clean_price_html($product)
        {
            if (!$product || !is_a($product, 'WC_Product')) { return ''; }
            
            
            
            
            if ($product->is_type('variable') && method_exists($product, 'get_variation_price')) {
                $min = (float) $product->get_variation_price('min');
                $max = (float) $product->get_variation_price('max');
                if ($min > 0 && $max > 0 && $min !== $max && function_exists('wc_format_price_range')) {
                    return (string) wc_format_price_range($min, $max);
                }
                return (string) wc_price($min);
            }

            
            
            
            
            $pid = (int) $product->get_id();
            if (isset($this->effective_prices_cache[$pid])) {
                $row  = $this->effective_prices_cache[$pid];
                $base = (float) ($row['base_price'] ?? 0);
                $sale = isset($row['sale_price']) ? (float) $row['sale_price'] : null;
                if ($base > 0) {
                    if ($sale !== null && $sale > 0 && $sale < $base) {
                        return (string) wc_format_sale_price(wc_price($base), wc_price($sale));
                    }
                    return (string) wc_price($base);
                }
            }

            
            
            
            if ($product->is_on_sale() && function_exists('wc_format_sale_price')) {
                $regular = $product->get_regular_price();
                $sale    = $product->get_sale_price();
                if ($regular !== '' && $sale !== '' && $regular !== $sale) {
                    return (string) wc_format_sale_price(wc_price($regular), wc_price($sale));
                }
            }
            return (string) wc_price($product->get_price());
        }

        
        private function build_role_badge_dto($product)
        {
            if (!$product || !is_a($product, 'WC_Product')) { return null; }
            if (!class_exists('AIEO_DMM_Settings')) { return null; }
            if (!class_exists('OM_Role_Price_Handler')) { return null; }

            $parent_id = $product->is_type('variation') ? (int) $product->get_parent_id() : (int) $product->get_id();
            if ($parent_id <= 0) { return null; }
            $handler = OM_Role_Price_Handler::instance();
            if (!method_exists($handler, 'parent_has_role_pricing')) { return null; }
            if (!$handler->parent_has_role_pricing($parent_id)) { return null; }

            $is_anon = function_exists('is_user_logged_in') ? !is_user_logged_in() : false;
            
            
            
            
            $show_tip = $is_anon && (bool) AIEO_DMM_Settings::get('show_login_message', false);

            $icon = (string) AIEO_DMM_Settings::get('mini_cart_badge_icon', '');
            $text = (string) AIEO_DMM_Settings::get('mini_cart_badge_text', '');
            
            
            
            
            if ($icon === '' && $text === '') { $text = 'PRO'; }

            $alt = '';
            if ($show_tip) {
                $alt = (string) AIEO_DMM_Settings::get('mini_cart_badge_alt', '');
                if ($alt === '') { $alt = (string) AIEO_DMM_Settings::get('login_message_text', ''); }
                if ($alt !== '' && function_exists('wc_get_page_permalink')) {
                    $login_url = wc_get_page_permalink('myaccount');
                    if (!$login_url) { $login_url = wp_login_url(); }
                    $alt = str_replace('{login_url}', esc_url($login_url), $alt);
                }
            }

            return array(
                'icon' => $icon,
                'text' => $text,
                'alt'  => $alt,
            );
        }

        
        private function build_product_dtos($product_ids)
        {
            $out = array();
            if (empty($product_ids) || !is_array($product_ids)) {
                return $out;
            }
            
            
            
            
            $this->preload_effective_prices(array_map('intval', $product_ids));

            foreach ($product_ids as $id) {
                $id = (int) $id;
                if ($id <= 0) { continue; }
                $product = wc_get_product($id);
                $dto = $this->build_product_dto($product);
                if ($dto !== null) {
                    $out[] = $dto;
                }
            }
            return $out;
        }

        
        private function preload_effective_prices(array $product_ids)
        {
            if (empty($product_ids)) { return; }
            if (!class_exists('AIEO_Effective_Prices')) { return; }
            if (!AIEO_Effective_Prices::is_enabled()) { return; }

            
            $needed = array();
            foreach ($product_ids as $id) {
                $id = (int) $id;
                if ($id > 0 && !isset($this->effective_prices_cache[$id])) {
                    $needed[] = $id;
                }
            }
            if (empty($needed)) { return; }

            $audience = class_exists('AIEO_Identity_Bridge')
                ? AIEO_Identity_Bridge::audience_key_for_current_user()
                : 'guest';

            $rows = AIEO_Effective_Prices::get_for_batch($needed, $audience);
            if (is_array($rows)) {
                foreach ($rows as $pid => $row) {
                    $this->effective_prices_cache[(int) $pid] = $row;
                }
            }
        }

        
        private function get_upsell_dtos()
        {
            global $post;
            if (!$post) { return array(); }
            $upsells = $this->collect_reco_ids($post->ID, 'upsells', '_upsell_ids');
            if (empty($upsells)) { return array(); }
            $instock = $this->filter_instock_products($upsells);
            return $this->build_product_dtos($instock);
        }

        
        private function get_cross_sell_dtos()
        {
            global $post;
            if (!$post) { return array(); }
            $crosssells = $this->collect_reco_ids($post->ID, 'crosssells', '_crosssell_ids');
            if (empty($crosssells)) { return array(); }
            $instock = $this->filter_instock_products($crosssells);
            return $this->build_product_dtos($instock);
        }

        
        private function get_related_dtos()
        {
            global $product;
            if (!$product || !is_a($product, 'WC_Product')) { return array(); }
            $related_ids = $this->collect_reco_ids((int) $product->get_id(), 'related', null);
            if (empty($related_ids)) { return array(); }
            $instock = $this->filter_instock_products($related_ids);
            if (empty($instock)) { return array(); }
            
            
            shuffle($instock);
            return $this->build_product_dtos($instock);
        }

        
        private function collect_reco_ids($source_pid, $surface, $legacy_meta_key)
        {
            
            
            
            
            
            $limit = 8;
            if (class_exists('AIEO_Effective_Recos') && AIEO_Effective_Recos::is_enabled()) {
                $audience = class_exists('AIEO_Identity_Bridge')
                    ? AIEO_Identity_Bridge::audience_key_for_current_user()
                    : 'guest';
                $ids = AIEO_Effective_Recos::get_top($source_pid, $surface, $audience, $limit);
                if (!empty($ids)) { return $ids; }
                
            }
            if ($legacy_meta_key === null) {
                if (function_exists('wc_get_related_products')) {
                    return (array) wc_get_related_products($source_pid, $limit);
                }
                return array();
            }
            $raw = get_post_meta($source_pid, $legacy_meta_key, true);
            return is_array($raw) ? array_map('intval', $raw) : array();
        }

        
        private function get_same_needs_dtos()
        {
            global $post;
            if (!$post || !$post->ID) { return array(); }
            require_once plugin_dir_path(__FILE__) . 'class-need-suggestions.php';
            $need_suggestions = AI_eShop_Need_Suggestions::get_instance();
            $suggested_ids = $need_suggestions->get_suggestions($post->ID);
            if (empty($suggested_ids)) { return array(); }
            $instock = $this->filter_instock_products($suggested_ids);
            if (empty($instock)) { return array(); }
            $instock = array_slice($instock, 0, 6);
            return $this->build_product_dtos($instock);
        }

        
        private function get_recently_viewed_dtos()
        {
            $viewed = array();
            if (!empty($_COOKIE['woocommerce_recently_viewed'])) {
                $raw = sanitize_text_field(wp_unslash($_COOKIE['woocommerce_recently_viewed']));
                $viewed = array_values(array_reverse(array_filter(array_map('absint', explode('|', $raw)))));
            }
            if (empty($viewed)) { return array(); }
            $viewed = array_slice($viewed, 0, 15);
            return $this->build_product_dtos($viewed);
        }

        
        private function get_related_html()
        {
            global $product;
            if (!$product) {
                return '';
            }

            $related_ids = wc_get_related_products($product->get_id());

            if (empty($related_ids)) {
                return '';
            }

            
            $instock_related = $this->filter_instock_products($related_ids);
            if (empty($instock_related)) {
                return '';
            }

            $args = array(
                'post_type' => 'product',
                'posts_per_page' => -1,
                'post__in' => $instock_related,
                'orderby' => 'rand'
            );
            $products = new WP_Query($args);

            if (!$products->have_posts()) {
                wp_reset_postdata();
                return '';
            }

            ob_start();
            echo '<section id="aieo-related" class="related products"><h2>' . esc_html__('Related Products Recommendations ', 'ai-eshop-optimizer') . '</h2>';
            woocommerce_product_loop_start();
            while ($products->have_posts()) : $products->the_post();
                global $woocommerce_loop;
                $woocommerce_loop['name'] = 'related';
                wc_get_template_part('content', 'product');
            endwhile;
            woocommerce_product_loop_end();
            echo '</section>';
            wp_reset_postdata();

            return ob_get_clean();
        }

        
        private function get_upsell_html()
        {
            global $post;
            $upsells = get_post_meta($post->ID, '_upsell_ids', true);

            if (empty($upsells)) {
                return '';
            }

            
            $instock_upsells = $this->filter_instock_products($upsells);
            if (empty($instock_upsells)) {
                return '';
            }

            $args = array(
                'post_type' => 'product',
                'posts_per_page' => -1,
                'post__in' => $instock_upsells,
                'orderby' => 'post__in',
            );
            $products = new WP_Query($args);

            if (!$products->have_posts()) {
                wp_reset_postdata();
                return '';
            }

            ob_start();
            echo '<section id="aieo-up-sells" class="related up-sells upsells products"><h2>' . esc_html__('Up-sell Recommendations ', 'ai-eshop-optimizer') . '</h2>';
            woocommerce_product_loop_start();
            while ($products->have_posts()) : $products->the_post();
                global $woocommerce_loop;
                $woocommerce_loop['name'] = 'upsells';
                wc_get_template_part('content', 'product');
            endwhile;
            woocommerce_product_loop_end();
            echo '</section>';
            wp_reset_postdata();

            return ob_get_clean();
        }

        
        private function get_cross_sell_html()
        {
            global $post;
            $crosssells = get_post_meta($post->ID, '_crosssell_ids', true);

            if (empty($crosssells)) {
                return '';
            }

            
            $instock_crosssells = $this->filter_instock_products($crosssells);
            if (empty($instock_crosssells)) {
                return '';
            }

            $args = array(
                'post_type' => 'product',
                'posts_per_page' => -1,
                'post__in' => $instock_crosssells,
                'orderby' => 'post__in',
            );
            $products = new WP_Query($args);

            if (!$products->have_posts()) {
                wp_reset_postdata();
                return '';
            }

            ob_start();
            echo '<section id="aieo-cross-sells" class="related cross-sells products"><h2>' . esc_html__('Cross-sell Recommendations ', 'ai-eshop-optimizer') . '</h2>';
            woocommerce_product_loop_start();
            while ($products->have_posts()) : $products->the_post();
                global $woocommerce_loop;
                $woocommerce_loop['name'] = 'cross-sells';
                wc_get_template_part('content', 'product');
            endwhile;
            woocommerce_product_loop_end();
            echo '</section>';
            wp_reset_postdata();

            return ob_get_clean();
        }

        
        private function get_same_needs_html()
        {
            global $post;

            if (!$post || !$post->ID) {
                return '';
            }

            
            require_once plugin_dir_path(__FILE__) . 'class-need-suggestions.php';
            $need_suggestions = AI_eShop_Need_Suggestions::get_instance();

            
            $suggested_ids = $need_suggestions->get_suggestions($post->ID);

            if (empty($suggested_ids)) {
                return '';
            }

            
            $instock_suggested = $this->filter_instock_products($suggested_ids);
            if (empty($instock_suggested)) {
                return '';
            }

            $args = array(
                'post_type'      => 'product',
                'posts_per_page' => 6,
                'post__in'       => $instock_suggested,
                'orderby'        => 'post__in', 
                'post_status'    => 'publish',
            );
            $products = new WP_Query($args);

            if (!$products->have_posts()) {
                wp_reset_postdata();
                return '';
            }

            ob_start();
            echo '<section id="aieo-same-needs" class="related same-needs products"><h2>' . esc_html__('Products for the Same Needs', 'ai-eshop-optimizer') . '</h2>';
            woocommerce_product_loop_start();
            while ($products->have_posts()) : $products->the_post();
                global $woocommerce_loop;
                $woocommerce_loop['name'] = 'same-needs';
                wc_get_template_part('content', 'product');
            endwhile;
            woocommerce_product_loop_end();
            echo '</section>';
            wp_reset_postdata();

            return ob_get_clean();
        }
    }
}
