<?php

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

class AIEO_DMM_User_Vitals extends AIEO_DMM_Module_Base {

    const TABLE  = 'aieo_user_vitals';
    const SRC    = 'pods_user';
    const TR_IDS = 'aieo_uv_migrate_ids';

    
    private static function fields() {
        return array(
            'soft1_customer_name'           => array(__('SOFT1 Customer Name', 'ai-eshop-optimizer'), 'text'),
            'soft1_customer_id'             => array(__('SOFT1 Customer ID', 'ai-eshop-optimizer'), 'int'),
            'soft1_customer_ids'            => array(__('SOFT1 Customer IDs (all locations)', 'ai-eshop-optimizer'), 'text'),
            'soft1_loyalty_id'              => array(__('SOFT1 Loyalty ID', 'ai-eshop-optimizer'), 'int'),
            'soft1_turnover'                => array(__('SOFT1 Turnover', 'ai-eshop-optimizer'), 'decimal'),
            'soft1_loyalty_points'          => array(__('SOFT1 Loyalty Points', 'ai-eshop-optimizer'), 'int'),
            'soft1_loyalty_points_total'    => array(__('SOFT1 Loyalty Points Total', 'ai-eshop-optimizer'), 'int'),
            'eshop_loyalty_points'          => array(__('Eshop Loyalty Points', 'ai-eshop-optimizer'), 'int'),
            'soft1_customer_locations'      => array(__('SOFT1 Customer Locations', 'ai-eshop-optimizer'), 'text'),
            'soft1_latest_location'         => array(__('SOFT1 Latest Location', 'ai-eshop-optimizer'), 'text'),
            'soft1_recorded_speciality'     => array(__('SOFT1 Recorded Speciality', 'ai-eshop-optimizer'), 'text'),
            'soft1_latest_transaction_date' => array(__('SOFT1 Latest Transaction Date', 'ai-eshop-optimizer'), 'datetime'),
            'soft1_first_transaction_date'  => array(__('SOFT1 First Transaction Date', 'ai-eshop-optimizer'), 'datetime'),
            'eshop_latest_transaction_date' => array(__('Eshop Latest Transaction Date', 'ai-eshop-optimizer'), 'datetime'),
        );
    }

    public function get_id()       { return 'user_vitals'; }
    public function get_label()    { return __('User Vitals', 'ai-eshop-optimizer'); }
    public function get_priority() { return 10; }
    public function get_group()    { return 'customer_profiling'; }

    public function register_hooks() {
        $schema = AIEO_DIR . 'includes/dmm/sql/user-vitals-schema.php';
        if (file_exists($schema)) { require_once $schema; }
        if (function_exists('aieo_install_user_vitals_schema')) { aieo_install_user_vitals_schema(); }
        add_action('wp_ajax_aieo_user_vitals_scan',    array($this, 'ajax_scan'));
        add_action('wp_ajax_aieo_user_vitals_migrate', array($this, 'ajax_migrate'));
        add_action('wp_ajax_aieo_user_vitals_save_loyalty', array($this, 'ajax_save_loyalty'));
        add_action('wp_ajax_aieo_user_vitals_save_gf',      array($this, 'ajax_save_gf'));
        
        $loyalty = AIEO_DIR . 'includes/class-aieo-loyalty-connection.php';
        if (file_exists($loyalty)) { require_once $loyalty; }
        if (class_exists('AIEO_Loyalty_Connection') && empty($GLOBALS['aieo_loyalty_connection_booted'])) {
            $GLOBALS['aieo_loyalty_connection_booted'] = true;
            new AIEO_Loyalty_Connection();
        }
        
        $repeat_order = AIEO_DIR . 'includes/class-aieo-repeat-order.php';
        if (file_exists($repeat_order)) { require_once $repeat_order; }
        if (class_exists('AIEO_Repeat_Order') && empty($GLOBALS['aieo_repeat_order_booted'])) {
            $GLOBALS['aieo_repeat_order_booted'] = true;
            new AIEO_Repeat_Order();
        }
        
        $pro_tab = AIEO_DIR . 'includes/class-aieo-pro-account-tab.php';
        if (file_exists($pro_tab)) { require_once $pro_tab; }
        if (class_exists('AIEO_Pro_Account_Tab') && empty($GLOBALS['aieo_pro_account_tab_booted'])) {
            $GLOBALS['aieo_pro_account_tab_booted'] = true;
            new AIEO_Pro_Account_Tab();
        }
        
        
        add_action('show_user_profile',        array($this, 'render_profile_fields'));
        add_action('edit_user_profile',        array($this, 'render_profile_fields'));
        add_action('personal_options_update',  array($this, 'save_profile_fields'));
        add_action('edit_user_profile_update', array($this, 'save_profile_fields'));
    }

    private function table()     { global $wpdb; return $wpdb->prefix . self::TABLE; }
    private function src_table() { global $wpdb; return $wpdb->prefix . self::SRC; }

    private function src_exists() {
        global $wpdb;
        return (bool) $wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $this->src_table()));
    }

    
    private function has_data_sql() {
        return "(pu.soft1_customer_id IS NOT NULL OR pu.soft1_loyalty_id IS NOT NULL OR pu.soft1_turnover IS NOT NULL"
            . " OR pu.soft1_loyalty_points IS NOT NULL OR pu.soft1_loyalty_points_total IS NOT NULL OR pu.eshop_loyalty_points IS NOT NULL"
            . " OR NULLIF(pu.soft1_customer_name,'') IS NOT NULL OR NULLIF(pu.soft1_customer_ids,'') IS NOT NULL"
            . " OR NULLIF(pu.soft1_recorded_speciality,'') IS NOT NULL OR NULLIF(pu.soft1_customer_locations,'') IS NOT NULL"
            . " OR NULLIF(pu.soft1_latest_transaction_date,'') IS NOT NULL)";
    }

    
    
    

    public function ajax_scan() {
        AIEO_DMM::verify_ajax_request();
        global $wpdb;
        if (!$this->src_exists()) {
            wp_send_json_error(array('message' => __('Legacy Pods user table (wp_pods_user) was not found — nothing to migrate.', 'ai-eshop-optimizer')));
        }
        $src = $this->src_table();
        $tbl = $this->table();
        
        $eligible = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$src} pu JOIN {$wpdb->users} u ON u.ID = pu.id WHERE " . $this->has_data_sql());
        $orphans  = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$src} pu LEFT JOIN {$wpdb->users} u ON u.ID = pu.id WHERE u.ID IS NULL AND " . $this->has_data_sql());
        $existing = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$tbl}");
        
        wp_send_json_success(array(
            'eligible' => $eligible,
            'orphans'  => $orphans,
            'existing' => $existing,
            'message'  => sprintf(
                
                __('✓ %1$s users with ERP/SOFT1 data ready · %2$s already in the table · %3$s skipped (no matching WP user).', 'ai-eshop-optimizer'),
                number_format_i18n($eligible),
                number_format_i18n($existing),
                number_format_i18n($orphans)
            ),
        ));
    }

    public function ajax_migrate() {
        AIEO_DMM::verify_ajax_request();
        global $wpdb;
        if (!$this->src_exists()) {
            wp_send_json_error(array('message' => __('Legacy Pods user table not found.', 'ai-eshop-optimizer')));
        }
        $src  = $this->src_table();
        $tbl  = $this->table();
        $mode = isset($_POST['mode']) ? sanitize_key((string) wp_unslash($_POST['mode'])) : 'batch';

        if ($mode === 'init') {
            
            $ids = $wpdb->get_col("SELECT pu.id FROM {$src} pu JOIN {$wpdb->users} u ON u.ID = pu.id WHERE " . $this->has_data_sql() . " ORDER BY pu.id ASC");
            $ids = array_values(array_filter(array_map('intval', (array) $ids)));
            set_transient(self::TR_IDS, $ids, 2 * HOUR_IN_SECONDS);
            wp_send_json_success(array('total' => count($ids)));
        }

        $offset = isset($_POST['offset']) ? max(0, (int) $_POST['offset']) : 0;
        $size   = 1000;
        $ids    = get_transient(self::TR_IDS);
        if (!is_array($ids)) {
            wp_send_json_error(array('message' => __('Migration session expired — click Migrate again.', 'ai-eshop-optimizer')));
        }
        $slice = array_slice($ids, $offset, $size);
        if (empty($slice)) {
            wp_send_json_success(array('done' => true, 'processed' => count($ids), 'total' => count($ids), 'batch' => 0, 'total_rows' => (int) $wpdb->get_var("SELECT COUNT(*) FROM {$tbl}"))); 
        }

        $in = implode(',', array_map('intval', $slice));
        
        
        
        $d = static function ($c) { return "(CASE WHEN {$c} REGEXP '^[0-9]{4}-[0-9]{2}-[0-9]{2}' THEN {$c} ELSE NULL END)"; };
        
        $affected = $wpdb->query(
            "REPLACE INTO {$tbl}
                (user_id, soft1_customer_name, soft1_customer_id, soft1_customer_ids, soft1_loyalty_id,
                 soft1_turnover, soft1_loyalty_points, soft1_loyalty_points_total, eshop_loyalty_points,
                 soft1_customer_locations, soft1_latest_location, soft1_recorded_speciality,
                 soft1_latest_transaction_date, soft1_first_transaction_date, eshop_latest_transaction_date, migrated_at)
             SELECT pu.id,
                    NULLIF(pu.soft1_customer_name,''), pu.soft1_customer_id, NULLIF(pu.soft1_customer_ids,''), pu.soft1_loyalty_id,
                    pu.soft1_turnover, pu.soft1_loyalty_points, pu.soft1_loyalty_points_total, pu.eshop_loyalty_points,
                    NULLIF(pu.soft1_customer_locations,''), NULLIF(pu.soft1_latest_location,''), NULLIF(pu.soft1_recorded_speciality,''),
                    {$d('pu.soft1_latest_transaction_date')}, {$d('pu.soft1_first_transaction_date')}, {$d('pu.eshop_latest_transaction_date')}, NOW()
             FROM {$src} pu
             WHERE pu.id IN ({$in})"
        );

        $processed = $offset + count($slice);
        $done      = ($processed >= count($ids));
        $resp = array('done' => $done, 'processed' => $processed, 'total' => count($ids), 'batch' => (int) $affected);
        
        
        if ($done) { $resp['total_rows'] = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$tbl}"); } 
        wp_send_json_success($resp);
    }

    
    
    

    public function render_profile_fields($user) {
        if (!current_user_can('manage_options') || !is_object($user) || empty($user->ID)) { return; }
        global $wpdb;
        $tbl = $this->table();
        if (!$wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $tbl))) { return; }
        $row = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$tbl} WHERE user_id = %d", (int) $user->ID), ARRAY_A); 

        echo '<h2>' . esc_html__('ERP / SOFT1 vitals', 'ai-eshop-optimizer') . '</h2>';
        echo '<p class="description" style="max-width:760px;">' . sprintf(
            
            esc_html__('Synced from the ERP (SOFT1) and stored in %s. Editing here updates that table directly; a future ERP sync may overwrite these values.', 'ai-eshop-optimizer'),
            '<code>' . esc_html($wpdb->prefix . self::TABLE) . '</code>'
        ) . '</p>';
        echo '<table class="form-table" role="presentation"><tbody>';
        foreach (self::fields() as $col => $meta) {
            $val   = ($row && isset($row[$col]) && $row[$col] !== null) ? (string) $row[$col] : '';
            $type  = $meta[1];
            $itype = ($type === 'int' || $type === 'decimal') ? 'number' : 'text';
            $extra = ($type === 'decimal') ? ' step="0.01"' : (($type === 'int') ? ' step="1"' : '');
            $extra .= ($type === 'datetime') ? ' placeholder="YYYY-MM-DD HH:MM:SS"' : '';
            $id    = 'aieo_uv_' . $col;
            echo '<tr>';
            echo '<th><label for="' . esc_attr($id) . '">' . esc_html($meta[0]) . '</label></th>';
            echo '<td><input type="' . esc_attr($itype) . '"' . $extra . ' id="' . esc_attr($id) . '" name="' . esc_attr($id) . '" value="' . esc_attr($val) . '" class="regular-text"> ';
            echo '<code style="font-size:11px;color:#9ca3af;">' . esc_html($col) . '</code></td>';
            echo '</tr>';
        }
        echo '</tbody></table>';
    }

    public function save_profile_fields($user_id) {
        if (!current_user_can('manage_options') || !current_user_can('edit_user', $user_id)) { return; }
        
        if (!isset($_POST['aieo_uv_soft1_customer_id']) && !isset($_POST['aieo_uv_soft1_customer_name'])) { return; }
        global $wpdb;
        $tbl = $this->table();
        if (!$wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $tbl))) { return; }

        $data = array('user_id' => (int) $user_id);
        $fmt  = array('%d');
        foreach (self::fields() as $col => $meta) {
            $key = 'aieo_uv_' . $col;
            $raw = isset($_POST[$key]) ? trim((string) wp_unslash($_POST[$key])) : ''; 
            $type = $meta[1];
            if ($raw === '') {
                $data[$col] = null; $fmt[] = '%s';
            } elseif ($type === 'int') {
                $data[$col] = (int) preg_replace('/[^0-9\-]/', '', $raw); $fmt[] = '%d';
            } elseif ($type === 'decimal') {
                $data[$col] = (float) str_replace(',', '.', preg_replace('/[^0-9,.\-]/', '', $raw)); $fmt[] = '%f';
            } elseif ($type === 'datetime') {
                $data[$col] = preg_match('/^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}(:\d{2})?)?$/', $raw) ? $raw : null; $fmt[] = '%s';
            } else {
                $data[$col] = sanitize_text_field($raw); $fmt[] = '%s';
            }
        }
        
        $data['migrated_at'] = $wpdb->get_var($wpdb->prepare("SELECT migrated_at FROM {$tbl} WHERE user_id = %d", (int) $user_id)); 
        $fmt[] = '%s';
        $wpdb->replace($tbl, $data, $fmt);
    }

    
    
    

    public function ajax_save_loyalty() {
        AIEO_DMM::verify_ajax_request();
        AIEO_DMM_Settings::update(array(
            'loyalty_role'             => isset($_POST['loyalty_role']) ? sanitize_key(wp_unslash($_POST['loyalty_role'])) : '',
            'loyalty_customers_table'  => isset($_POST['loyalty_customers_table']) ? sanitize_key(wp_unslash($_POST['loyalty_customers_table'])) : '',
            'loyalty_my_account'       => !empty($_POST['loyalty_my_account']),
            'loyalty_my_account_label' => isset($_POST['loyalty_my_account_label']) ? sanitize_text_field(wp_unslash($_POST['loyalty_my_account_label'])) : '',
        ));
        
        flush_rewrite_rules(false);
        wp_send_json_success(array('message' => __('✓ Saved.', 'ai-eshop-optimizer')));
    }

    public function render_loyalty_card() {
        global $wpdb;
        $role  = (string) AIEO_DMM_Settings::get('loyalty_role', '');
        if ($role === '')  { $role  = (string) get_option('s1erp_prod_woo_loyalty_role', 'customer_loyalty'); }
        $table = (string) AIEO_DMM_Settings::get('loyalty_customers_table', '');
        if ($table === '') { $table = (string) get_option('s1erp_site_customers_table', ''); }
        $mya   = (bool) AIEO_DMM_Settings::get('loyalty_my_account', false);
        $label = (string) AIEO_DMM_Settings::get('loyalty_my_account_label', '');
        if ($label === '') { $label = __('Bonus Card', 'ai-eshop-optimizer'); }
        $rows  = ($table !== '' && $wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $table))) ? (int) $wpdb->get_var("SELECT COUNT(*) FROM `{$table}`") : -1; 
        $nonce = wp_create_nonce(AIEO_DMM::NONCE_ACTION);
        $ajax  = admin_url('admin-ajax.php');
        ?>
        <div class="aieo-dmm-section" style="margin-top:24px;">
            <h2><?php esc_html_e('Loyalty connection (Bonus Card)', 'ai-eshop-optimizer'); ?></h2>
            <p class="description" style="max-width:880px;">
                <?php esc_html_e('A logged-in customer enters their Bonus-card number + the email/phone they gave in-store; on a match it copies their loyalty fields into the vitals table and grants the loyalty role (immediate access). Drop it in with the “AIEO Loyalty Connection” block or this shortcode:', 'ai-eshop-optimizer'); ?>
                <code>[aieo_loyalty_information]</code>
            </p>
            <table class="form-table" role="presentation"><tbody>
                <tr><th><label for="aieo-loy-role"><?php esc_html_e('Loyalty role slug', 'ai-eshop-optimizer'); ?></label></th>
                    <td><input type="text" id="aieo-loy-role" value="<?php echo esc_attr($role); ?>" class="regular-text"></td></tr>
                <tr><th><label for="aieo-loy-table"><?php esc_html_e('ERP customers table', 'ai-eshop-optimizer'); ?></label></th>
                    <td><input type="text" id="aieo-loy-table" value="<?php echo esc_attr($table); ?>" class="regular-text">
                        <p class="description"><?php echo $rows >= 0
                            ? esc_html(sprintf(__('Found — %s rows.', 'ai-eshop-optimizer'), number_format_i18n($rows)))
                            : esc_html__('Table not found / empty — the meta-connector ERP customer-import populates it.', 'ai-eshop-optimizer'); ?></p></td></tr>
                <tr><th><?php esc_html_e('My Account menu', 'ai-eshop-optimizer'); ?></th>
                    <td><label><input type="checkbox" id="aieo-loy-mya" <?php checked($mya); ?>> <?php esc_html_e('Add a Bonus tab to the WooCommerce My Account page', 'ai-eshop-optimizer'); ?></label></td></tr>
                <tr><th><label for="aieo-loy-label"><?php esc_html_e('My Account tab label', 'ai-eshop-optimizer'); ?></label></th>
                    <td><input type="text" id="aieo-loy-label" value="<?php echo esc_attr($label); ?>" class="regular-text"></td></tr>
            </tbody></table>
            <p><button type="button" class="button button-primary" id="aieo-loy-save"><?php esc_html_e('Save loyalty settings', 'ai-eshop-optimizer'); ?></button>
               <span id="aieo-loy-status" style="margin-left:10px;font-weight:600;"></span></p>
        </div>
        <script>
        (function(){
            var b=document.getElementById('aieo-loy-save'); if(!b) return;
            var ajax=<?php echo wp_json_encode($ajax); ?>, nonce=<?php echo wp_json_encode($nonce); ?>;
            b.addEventListener('click',function(){
                var fd=new FormData(); fd.append('action','aieo_user_vitals_save_loyalty'); fd.append('nonce',nonce);
                fd.append('loyalty_role',(document.getElementById('aieo-loy-role')||{}).value||'');
                fd.append('loyalty_customers_table',(document.getElementById('aieo-loy-table')||{}).value||'');
                fd.append('loyalty_my_account',document.getElementById('aieo-loy-mya').checked?'1':'');
                fd.append('loyalty_my_account_label',(document.getElementById('aieo-loy-label')||{}).value||'');
                var st=document.getElementById('aieo-loy-status'); st.style.color='#6b7280'; st.textContent='…';
                fetch(ajax,{method:'POST',credentials:'same-origin',body:fd}).then(function(r){return r.json();}).then(function(j){
                    st.style.color=(j&&j.success)?'#15803d':'#b91c1c'; st.textContent=(j&&j.data&&j.data.message)?j.data.message:(j&&j.success?'OK':'Error');
                }).catch(function(){st.style.color='#b91c1c';st.textContent='Network error.';});
            });
        })();
        </script>
        <?php
    }

    public function ajax_save_gf() {
        AIEO_DMM::verify_ajax_request();
        $map = array();
        if (isset($_POST['gf_role_map']) && is_array($_POST['gf_role_map'])) {
            foreach (wp_unslash($_POST['gf_role_map']) as $slug => $val) {
                $slug = sanitize_key((string) $slug); $iv = absint($val);
                if ($slug !== '' && $iv > 0) { $map[$slug] = $iv; }
            }
        }
        AIEO_DMM_Settings::update(array(
            'gf_registration_form_id'   => isset($_POST['gf_registration_form_id'])   ? absint(wp_unslash($_POST['gf_registration_form_id']))   : 0,
            'gf_update_form_id'         => isset($_POST['gf_update_form_id'])         ? absint(wp_unslash($_POST['gf_update_form_id']))         : 0,
            'gf_checkbox_field_id'      => isset($_POST['gf_checkbox_field_id'])      ? max(1, absint(wp_unslash($_POST['gf_checkbox_field_id']))) : 11,
            'gf_role_map'               => $map,
            'gf_professionals_page_id'  => isset($_POST['gf_professionals_page_id'])  ? absint(wp_unslash($_POST['gf_professionals_page_id']))  : 0,
            'gf_prompt_form_id'         => isset($_POST['gf_prompt_form_id'])         ? absint(wp_unslash($_POST['gf_prompt_form_id']))         : 0,
            'gf_prompt_pro_field_id'    => isset($_POST['gf_prompt_pro_field_id'])    ? max(1, absint(wp_unslash($_POST['gf_prompt_pro_field_id']))) : 51,
            'gf_prompt_member_field_id' => isset($_POST['gf_prompt_member_field_id']) ? max(1, absint(wp_unslash($_POST['gf_prompt_member_field_id']))) : 48,
            'gf_intro_logged_in'        => isset($_POST['gf_intro_logged_in'])        ? wp_kses_post(wp_unslash($_POST['gf_intro_logged_in']))        : '',
            'gf_intro_logged_out'       => isset($_POST['gf_intro_logged_out'])       ? wp_kses_post(wp_unslash($_POST['gf_intro_logged_out']))       : '',
        ));
        wp_send_json_success(array('message' => __('✓ Saved.', 'ai-eshop-optimizer')));
    }

    public function render_gf_card() {
        $s = class_exists('AIEO_DMM_Settings') ? AIEO_DMM_Settings::get_all() : array();
        $enabled = (isset($s['enabled_roles']) && is_array($s['enabled_roles'])) ? $s['enabled_roles'] : array();
        $map     = (isset($s['gf_role_map']) && is_array($s['gf_role_map'])) ? $s['gf_role_map'] : array();
        if (!function_exists('get_editable_roles')) { require_once ABSPATH . 'wp-admin/includes/user.php'; }
        $all     = function_exists('get_editable_roles') ? get_editable_roles() : array();
        $gf_active = class_exists('GFAPI');
        $forms   = array();
        if ($gf_active) { foreach ((array) GFAPI::get_forms(true, false) as $f) { if (isset($f['id'])) { $forms[] = array('id' => (int) $f['id'], 'title' => isset($f['title']) ? (string) $f['title'] : ('#' . (int) $f['id'])); } } }
        $nonce = wp_create_nonce(AIEO_DMM::NONCE_ACTION); $ajax = admin_url('admin-ajax.php');
        $sel = static function ($id, $cur) use ($forms) {
            $cur = (int) $cur;
            if (empty($forms)) { return '<input type="number" id="' . esc_attr($id) . '" min="0" value="' . esc_attr((string) $cur) . '" class="small-text">'; }
            $h = '<select id="' . esc_attr($id) . '"><option value="0">— ' . esc_html__('disabled', 'ai-eshop-optimizer') . ' —</option>';
            foreach ($forms as $f) { $h .= '<option value="' . (int) $f['id'] . '" ' . selected($cur, (int) $f['id'], false) . '>#' . (int) $f['id'] . ' — ' . esc_html($f['title']) . '</option>'; }
            return $h . '</select>';
        };
        ?>
        <div class="aieo-dmm-section" style="margin-top:24px;">
            <h2><?php esc_html_e('Professional signup (Gravity Forms)', 'ai-eshop-optimizer'); ?></h2>
            <p class="description" style="max-width:880px;">
                <?php esc_html_e('Drives professional / student registration + role assignment from Gravity Forms (runtime lives in the pricing engine). Place it with the “AIEO Professional Signup” block or the shortcode', 'ai-eshop-optimizer'); ?> <code>[membership_gf]</code>.
                <?php if (!$gf_active) { echo ' <span style="color:#b45309;">' . esc_html__('Gravity Forms not active — IDs still save.', 'ai-eshop-optimizer') . '</span>'; } ?>
            </p>
            <table class="form-table" role="presentation"><tbody>
                <tr><th><?php esc_html_e('Registration form', 'ai-eshop-optimizer'); ?></th><td><?php echo $sel('aieo-gf-reg', $s['gf_registration_form_id'] ?? 0); ?></td></tr>
                <tr><th><?php esc_html_e('Update form', 'ai-eshop-optimizer'); ?></th><td><?php echo $sel('aieo-gf-upd', $s['gf_update_form_id'] ?? 0); ?></td></tr>
                <tr><th><?php esc_html_e('Checkbox field ID', 'ai-eshop-optimizer'); ?></th><td><input type="number" id="aieo-gf-cb" min="1" value="<?php echo esc_attr((string) ($s['gf_checkbox_field_id'] ?? 11)); ?>" class="small-text"></td></tr>
                <tr><th><?php esc_html_e('Membership page ID', 'ai-eshop-optimizer'); ?></th><td><input type="number" id="aieo-gf-page" min="0" value="<?php echo esc_attr((string) ($s['gf_professionals_page_id'] ?? 0)); ?>" class="small-text"></td></tr>
                <tr><th><?php esc_html_e('Prompt form', 'ai-eshop-optimizer'); ?></th><td><?php echo $sel('aieo-gf-prompt', $s['gf_prompt_form_id'] ?? 0); ?></td></tr>
                <tr><th><?php esc_html_e('“Is pro?” / “Already enrolled?” field IDs', 'ai-eshop-optimizer'); ?></th><td><input type="number" id="aieo-gf-pro" min="1" value="<?php echo esc_attr((string) ($s['gf_prompt_pro_field_id'] ?? 51)); ?>" class="small-text"> / <input type="number" id="aieo-gf-mem" min="1" value="<?php echo esc_attr((string) ($s['gf_prompt_member_field_id'] ?? 48)); ?>" class="small-text"></td></tr>
            </tbody></table>
            <h4><?php esc_html_e('Role → GF checkbox value', 'ai-eshop-optimizer'); ?></h4>
            <?php if (empty($enabled)) : ?>
                <p class="description" style="color:#b45309;"><?php esc_html_e('Enable roles on the Role Pricing tab first.', 'ai-eshop-optimizer'); ?></p>
            <?php else : ?>
                <table class="widefat striped" style="max-width:560px;"><thead><tr><th><?php esc_html_e('Role', 'ai-eshop-optimizer'); ?></th><th style="width:120px;"><?php esc_html_e('GF value', 'ai-eshop-optimizer'); ?></th></tr></thead><tbody>
                <?php foreach ($enabled as $slug) : $lbl = isset($all[$slug]['name']) ? translate_user_role($all[$slug]['name']) : $slug; ?>
                    <tr><td><code><?php echo esc_html($slug); ?></code> <?php echo esc_html($lbl); ?></td><td><input type="number" class="aieo-gf-map small-text" data-slug="<?php echo esc_attr($slug); ?>" min="0" value="<?php echo esc_attr((string) (int) ($map[$slug] ?? 0)); ?>"></td></tr>
                <?php endforeach; ?>
                </tbody></table>
            <?php endif; ?>
            <p style="margin-top:10px;"><label><strong><?php esc_html_e('Logged-in intro', 'ai-eshop-optimizer'); ?></strong></label><br><textarea id="aieo-gf-intro-in" class="large-text code" rows="2"><?php echo esc_textarea((string) ($s['gf_intro_logged_in'] ?? '')); ?></textarea></p>
            <p><label><strong><?php esc_html_e('Logged-out intro', 'ai-eshop-optimizer'); ?></strong></label><br><textarea id="aieo-gf-intro-out" class="large-text code" rows="2"><?php echo esc_textarea((string) ($s['gf_intro_logged_out'] ?? '')); ?></textarea></p>
            <p><button type="button" class="button button-primary" id="aieo-gf-save"><?php esc_html_e('Save Gravity Forms settings', 'ai-eshop-optimizer'); ?></button> <span id="aieo-gf-status" style="margin-left:10px;font-weight:600;"></span></p>
        </div>
        <script>
        (function(){
            var b=document.getElementById('aieo-gf-save'); if(!b) return;
            var ajax=<?php echo wp_json_encode($ajax); ?>, nonce=<?php echo wp_json_encode($nonce); ?>;
            function v(id){ var e=document.getElementById(id); return e?e.value:''; }
            b.addEventListener('click',function(){
                var fd=new FormData(); fd.append('action','aieo_user_vitals_save_gf'); fd.append('nonce',nonce);
                ['aieo-gf-reg|gf_registration_form_id','aieo-gf-upd|gf_update_form_id','aieo-gf-cb|gf_checkbox_field_id','aieo-gf-page|gf_professionals_page_id','aieo-gf-prompt|gf_prompt_form_id','aieo-gf-pro|gf_prompt_pro_field_id','aieo-gf-mem|gf_prompt_member_field_id','aieo-gf-intro-in|gf_intro_logged_in','aieo-gf-intro-out|gf_intro_logged_out'].forEach(function(p){ var a=p.split('|'); fd.append(a[1], v(a[0])); });
                document.querySelectorAll('.aieo-gf-map').forEach(function(el){ fd.append('gf_role_map['+el.getAttribute('data-slug')+']', el.value); });
                var st=document.getElementById('aieo-gf-status'); st.style.color='#6b7280'; st.textContent='…';
                fetch(ajax,{method:'POST',credentials:'same-origin',body:fd}).then(function(r){return r.json();}).then(function(j){ st.style.color=(j&&j.success)?'#15803d':'#b91c1c'; st.textContent=(j&&j.data&&j.data.message)?j.data.message:(j&&j.success?'OK':'Error'); }).catch(function(){st.style.color='#b91c1c';st.textContent='Network error.';});
            });
        })();
        </script>
        <?php
    }

    
    
    

    public function render_subtab() {
        global $wpdb;
        $tbl    = $this->table();
        $exists = (bool) $wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $tbl));
        $rows   = $exists ? (int) $wpdb->get_var("SELECT COUNT(*) FROM {$tbl}") : 0; 
        $last   = $exists ? $wpdb->get_var("SELECT MAX(migrated_at) FROM {$tbl}") : null; 
        $src_ok = $this->src_exists();
        $nonce  = wp_create_nonce(AIEO_DMM::NONCE_ACTION);
        $ajax   = admin_url('admin-ajax.php');
        ?>
        <div class="aieo-dmm-section">
            <h2><?php esc_html_e('User Vitals', 'ai-eshop-optimizer'); ?></h2>
            <p class="description" style="max-width:880px;">
                <?php printf(
                    
                    esc_html__('The SOFT1 / ERP fields that extended the WordPress user (customer id, loyalty ids + points, turnover, transaction dates, speciality, locations) now live in their own typed, indexed table %s. It replaces the legacy Pods user extension as the source for correlating user + ERP statistics with the order & product analytics (wired in a later stage, the same way the daily order/product vitals are).', 'ai-eshop-optimizer'),
                    '<code>' . esc_html($wpdb->prefix . self::TABLE) . '</code>'
                ); ?>
            </p>

            <table class="widefat striped" style="max-width:680px;margin:10px 0 18px;">
                <thead><tr>
                    <th><?php esc_html_e('Field', 'ai-eshop-optimizer'); ?></th>
                    <th><?php esc_html_e('Column', 'ai-eshop-optimizer'); ?></th>
                    <th><?php esc_html_e('Type', 'ai-eshop-optimizer'); ?></th>
                </tr></thead>
                <tbody>
                <?php foreach (self::fields() as $col => $meta) : ?>
                    <tr>
                        <td><?php echo esc_html($meta[0]); ?></td>
                        <td><code style="font-size:11px;"><?php echo esc_html($col); ?></code></td>
                        <td><?php echo esc_html($meta[1]); ?></td>
                    </tr>
                <?php endforeach; ?>
                </tbody>
            </table>

            <div class="aieo-dmm-card" style="margin:14px 0;padding:16px;border:1px solid #c3c4c7;background:#fff;max-width:880px;">
                <h3 style="margin-top:0;"><?php esc_html_e('Migrate from the Pods user extension', 'ai-eshop-optimizer'); ?></h3>
                <p class="description" style="margin:0 0 10px;">
                    <?php echo $src_ok
                        ? esc_html__('Reads the legacy wp_pods_user table and writes one typed row per user into the vitals table. Idempotent — re-running overwrites each user’s row (keyed on user id), never duplicates. Users with no matching WP account are skipped. Run Scan first to preview the counts.', 'ai-eshop-optimizer')
                        : esc_html__('The legacy wp_pods_user table was not found on this site — there is nothing to migrate here.', 'ai-eshop-optimizer'); ?>
                </p>
                <p>
                    <button type="button" class="button button-secondary" id="aieo-uv-scan" <?php disabled(!$src_ok); ?>><?php esc_html_e('Scan (dry-run)', 'ai-eshop-optimizer'); ?></button>
                    <button type="button" class="button button-primary" id="aieo-uv-migrate" style="margin-left:8px;" <?php disabled(!$src_ok); ?>><?php esc_html_e('Migrate now', 'ai-eshop-optimizer'); ?></button>
                    <span id="aieo-uv-status" style="margin-left:10px;color:#646970;font-size:13px;"></span>
                </p>
                <div id="aieo-uv-bar-wrap" style="display:none;height:18px;background:#e5e7eb;border-radius:9px;overflow:hidden;max-width:600px;margin:6px 0;">
                    <div id="aieo-uv-bar" style="height:100%;width:0;background:#2271b1;transition:width .25s;"></div>
                </div>
                <p id="aieo-uv-result" style="margin:8px 0 0;font-weight:600;color:#15803d;"></p>
                <p style="margin:10px 0 0;font-size:12px;color:#374151;border-top:1px solid #eee;padding-top:8px;">
                    <strong><?php esc_html_e('Vitals table:', 'ai-eshop-optimizer'); ?></strong>
                    <strong id="aieo-uv-rowcount"><?php echo esc_html(number_format_i18n($rows)); ?></strong> <?php esc_html_e('rows', 'ai-eshop-optimizer'); ?>
                    <?php if ($last) { echo ' &middot; ' . esc_html__('last migrated', 'ai-eshop-optimizer') . ' ' . esc_html(get_date_from_gmt($last, 'Y-m-d H:i')); } ?>
                </p>
            </div>
        </div>
        <script>
        (function () {
            var ajax = <?php echo wp_json_encode($ajax); ?>, nonce = <?php echo wp_json_encode($nonce); ?>;
            var st = document.getElementById('aieo-uv-status'),
                bw = document.getElementById('aieo-uv-bar-wrap'),
                bar = document.getElementById('aieo-uv-bar'),
                res = document.getElementById('aieo-uv-result'),
                rc = document.getElementById('aieo-uv-rowcount'),
                scanBtn = document.getElementById('aieo-uv-scan'),
                migBtn = document.getElementById('aieo-uv-migrate');
            function call(action, extra){
                var fd = new FormData(); fd.append('action', action); fd.append('nonce', nonce);
                for (var k in (extra || {})) { fd.append(k, extra[k]); }
                return fetch(ajax, { method:'POST', credentials:'same-origin', body: fd }).then(function(r){ return r.json(); });
            }
            if (scanBtn) scanBtn.addEventListener('click', function(){
                scanBtn.disabled = true; if (res) res.textContent = '';
                if (st) { st.style.color = '#6b7280'; st.textContent = <?php echo wp_json_encode(__('Scanning…', 'ai-eshop-optimizer')); ?>; }
                call('aieo_user_vitals_scan', {}).then(function(j){
                    if (st) { st.style.color = (j && j.success) ? '#15803d' : '#b91c1c'; st.textContent = (j && j.data && j.data.message) ? j.data.message : (j && j.success ? 'OK' : 'Error'); }
                    scanBtn.disabled = false;
                }).catch(function(){ if (st){ st.style.color='#b91c1c'; st.textContent='Network error.'; } scanBtn.disabled = false; });
            });
            if (migBtn) migBtn.addEventListener('click', function(){
                if (!window.confirm(<?php echo wp_json_encode(__('Migrate the SOFT1 / ERP user fields from Pods into the vitals table? Existing rows are overwritten (never duplicated).', 'ai-eshop-optimizer')); ?>)) { return; }
                migBtn.disabled = true; if (scanBtn) scanBtn.disabled = true; if (res) res.textContent = '';
                if (bw) bw.style.display = 'block';
                function fail(j){ if (st){ st.style.color='#b91c1c'; st.textContent = (j && j.data && j.data.message) ? j.data.message : 'Failed'; } migBtn.disabled=false; if (scanBtn) scanBtn.disabled=false; }
                call('aieo_user_vitals_migrate', { mode:'init' }).then(function(j){
                    if (!j || !j.success) { return fail(j); }
                    var total = j.data.total, offset = 0;
                    if (!total) { if (st){ st.style.color='#15803d'; st.textContent = <?php echo wp_json_encode(__('Nothing to migrate.', 'ai-eshop-optimizer')); ?>; } migBtn.disabled=false; if (scanBtn) scanBtn.disabled=false; return; }
                    if (st) st.textContent = total.toLocaleString() + <?php echo wp_json_encode(__(' users to migrate…', 'ai-eshop-optimizer')); ?>;
                    (function step(){
                        call('aieo_user_vitals_migrate', { mode:'batch', offset: offset }).then(function(b){
                            if (!b || !b.success) { return fail(b); }
                            offset = b.data.processed;
                            var pct = total > 0 ? Math.round(offset / total * 100) : 100;
                            if (bar) bar.style.width = pct + '%';
                            if (st) st.textContent = offset.toLocaleString() + ' / ' + total.toLocaleString() + <?php echo wp_json_encode(__(' users migrated', 'ai-eshop-optimizer')); ?>;
                            if (b.data.done) {
                                var rows = (b.data.total_rows != null) ? b.data.total_rows : offset;
                                if (res) { res.style.color = '#15803d'; res.textContent = '✓ ' + offset.toLocaleString() + <?php echo wp_json_encode(__(' users migrated · ', 'ai-eshop-optimizer')); ?> + rows.toLocaleString() + <?php echo wp_json_encode(__(' unique rows in the table (re-runs overwrite, never duplicate).', 'ai-eshop-optimizer')); ?>; }
                                if (rc) rc.textContent = rows.toLocaleString();
                                migBtn.disabled = false; if (scanBtn) scanBtn.disabled = false;
                            } else { step(); }
                        }).catch(function(){ fail(null); });
                    })();
                }).catch(function(){ fail(null); });
            });
        })();
        </script>
        <?php
        $this->render_loyalty_card();
        $this->render_gf_card();
    }
}
