<?php

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

class AIEO_DMM_Variations_Gallery extends AIEO_DMM_Module_Base {

    const OPTION_KEY = 'aieo_dmm_variations_gallery_settings';

    public function get_id()       { return 'variations_gallery'; }
    public function get_label()    { return __('Variations Gallery', 'ai-eshop-optimizer'); }
    public function get_priority() { return 70; }
    public function get_group()    { return 'product_display'; }

    public function register_hooks() {
        add_action('wp_ajax_aieo_dmm_variations_gallery_save', array($this, 'ajax_save'));

        
        
        
        add_action('wp_ajax_aieo_dmm_vg_migration_status',    array($this, 'ajax_migration_status'));
        add_action('wp_ajax_aieo_dmm_vg_migration_run_batch', array($this, 'ajax_migration_run_batch'));
        add_action('wp_ajax_aieo_dmm_vg_migration_reset',     array($this, 'ajax_migration_reset'));
        add_action('wp_ajax_aieo_dmm_vg_migration_clear_as',  array($this, 'ajax_migration_clear_as'));

        $s = $this->get_settings();
        if (empty($s['enabled'])) { return; }

        
        
        add_filter('option_botiga-modules',         array($this, 'disable_botiga_variations_gallery'));
        add_filter('default_option_botiga-modules', array($this, 'disable_botiga_variations_gallery'));

        
        
        add_filter('woocommerce_available_variation', array($this, 'add_variation_gallery_data'), 10, 3);
        add_action('wp_enqueue_scripts',              array($this, 'register_scripts'));

        
        add_action('admin_enqueue_scripts',           array($this, 'admin_enqueue'));
        add_action('woocommerce_product_after_variable_attributes', array($this, 'add_variation_gallery_field'), 10, 3);
        add_action('woocommerce_save_product_variation',  array($this, 'save_variation_gallery'), 10, 2);
        add_action('woocommerce_process_product_meta',    array($this, 'save_variation_galleries_on_product_save'), 10, 2);

        
        
        
        
        
        
        add_action('admin_init', array($this, 'maybe_unhook_wc_classic_variation_gallery'), 50);
    }

    
    public function maybe_unhook_wc_classic_variation_gallery(): void {
        if (!class_exists('\\Automattic\\WooCommerce\\Internal\\VariationGallery\\Package')) {
            return;
        }
        if (!\Automattic\WooCommerce\Internal\VariationGallery\Package::is_enabled()) {
            return;
        }
        if (!function_exists('wc_get_container')) { return; }

        try {
            $picker = wc_get_container()->get(\Automattic\WooCommerce\Internal\VariationGallery\ClassicVariationGalleryAdmin::class);
        } catch (\Throwable $e) {
            return;
        }
        remove_action('woocommerce_variation_after_upload_image', array($picker, 'render_variation_gallery_field'), 10);
        remove_action('woocommerce_admin_process_variation_object', array($picker, 'persist_variation_gallery_field'), 10);
    }

    public function get_settings() {
        $stored = get_option(self::OPTION_KEY, array());
        if (!is_array($stored)) { $stored = array(); }
        return array_merge(array('enabled' => false), $stored);
    }

    public function ajax_save() {
        AIEO_DMM::verify_ajax_request();
        update_option(self::OPTION_KEY, array(
            'enabled' => !empty($_POST['enabled']),
        ), false);
        wp_send_json_success(array('message' => __('Variations Gallery settings saved.', 'ai-eshop-optimizer')));
    }

    public function disable_botiga_variations_gallery($modules) {
        if (is_array($modules)) {
            $modules['variations-gallery'] = false;
        }
        return $modules;
    }

    public function register_scripts() {
        
        
        
        
        $rel_path = 'assets/js/product-display/variations-gallery.js';
        $abs_path = defined('AIEO_DIR') ? AIEO_DIR . $rel_path : plugin_dir_path(AIEO_FILE) . $rel_path;
        $mtime    = file_exists($abs_path) ? (string) filemtime($abs_path) : '';
        $version  = $mtime !== '' ? $mtime : (defined('AIEO_VERSION') ? AIEO_VERSION : '1.0');
        wp_register_script(
            'aieo-variations-gallery',
            plugins_url($rel_path, AIEO_FILE),
            array('jquery'), $version, true
        );
    }

    public function admin_enqueue($hook) {
        if (!in_array($hook, array('post.php','post-new.php'), true)) { return; }
        $screen = function_exists('get_current_screen') ? get_current_screen() : null;
        if (!$screen || $screen->post_type !== 'product') { return; }
        $version = defined('AIEO_VERSION') ? AIEO_VERSION : '1.0';
        wp_enqueue_media();
        wp_enqueue_style(
            'aieo-variations-gallery-admin',
            plugins_url('assets/css/product-display/variations-gallery-admin.css', AIEO_FILE),
            array(), $version
        );
        wp_enqueue_script(
            'aieo-variations-gallery-admin',
            plugins_url('assets/js/product-display/variations-gallery-admin.js', AIEO_FILE),
            array('jquery', 'wp-mediaelement'), $version, true
        );
        wp_localize_script('aieo-variations-gallery-admin', 'omPPEVariationsGallery', array(
            'placeholderVideoUrl' => plugins_url('assets/images/product-display/video-placeholder.svg', AIEO_FILE),
            'editText'            => esc_attr__('Edit', 'ai-eshop-optimizer'),
            'addToGallery'        => esc_attr__('Add to gallery', 'ai-eshop-optimizer'),
        ));
    }

    public function add_variation_gallery_field($loop, $variation_data, $variation) {
        $attachment_ids = $this->read_variation_gallery_entries((int) $variation->ID);
        $placeholder    = plugins_url('assets/images/product-display/video-placeholder.svg', AIEO_FILE);

        echo '<div class="form-row form-row-full om-ppe-variation-gallery">';
        echo '<p><strong>' . esc_html__('Variation Gallery', 'ai-eshop-optimizer') . '</strong></p>';
        echo '<ul class="om-ppe-variation-gallery-sortable">';
        if (!empty($attachment_ids) && is_array($attachment_ids)) {
            foreach ($attachment_ids as $attachment_id) {
                if (is_numeric($attachment_id) && wp_attachment_is('video', (int) $attachment_id)) {
                    echo '<li class="om-ppe-video-thumbnail">';
                    echo '<figure><img src="' . esc_url($placeholder) . '" alt="" /></figure>';
                    echo '<span class="om-ppe-remove-item dashicons dashicons-no"></span>';
                    echo '<input type="hidden" name="botiga_variation_gallery[' . esc_attr($loop) . '][]" value="' . esc_attr($attachment_id) . '" />';
                    echo '</li>';
                } elseif (is_string($attachment_id) && preg_match('(youtube|youtu\.be|vimeo)', $attachment_id)) {
                    echo '<li class="om-ppe-video-url-thumbnail">';
                    echo '<figure data-edit-text="' . esc_attr__('Edit', 'ai-eshop-optimizer') . '"><img src="' . esc_url($placeholder) . '" alt="" /></figure>';
                    echo '<span class="om-ppe-remove-item dashicons dashicons-no"></span>';
                    echo '<input type="hidden" name="botiga_variation_gallery[' . esc_attr($loop) . '][]" value="' . esc_attr($attachment_id) . '" />';
                    echo '</li>';
                } else {
                    $img = wp_get_attachment_image_src((int) $attachment_id, 'thumbnail');
                    $src = !empty($img[0]) ? $img[0] : wc_placeholder_img_src('thumbnail');
                    echo '<li>';
                    echo '<figure><img src="' . esc_url($src) . '" alt="" /></figure>';
                    echo '<span class="om-ppe-remove-item dashicons dashicons-no"></span>';
                    echo '<input type="hidden" name="botiga_variation_gallery[' . esc_attr($loop) . '][]" value="' . esc_attr($attachment_id) . '" />';
                    echo '</li>';
                }
            }
        }
        echo '</ul>';
        echo '<p style="display:flex;gap:10px;">';
        echo '<a href="#" class="om-ppe-add-media button" data-loop="' . esc_attr($loop) . '">' . esc_html__('Add Media', 'ai-eshop-optimizer') . '</a>';
        echo '<a href="#" class="om-ppe-add-video-url button" data-loop="' . esc_attr($loop) . '">' . esc_html__('Add Video URL', 'ai-eshop-optimizer') . '</a>';
        echo '</p>';
        echo '</div>';
    }

    
    public static function resolve_image_ids(int $variation_id, string $context = ''): array {
        
        $filtered = apply_filters('aieo_variation_gallery_image_ids', null, $variation_id, $context);
        if (is_array($filtered)) {
            return array_values(array_filter(array_map('intval', $filtered)));
        }

        $canonical_csv = (string) get_post_meta($variation_id, '_product_image_gallery', true);
        if ($canonical_csv !== '') {
            $ids = array_values(array_filter(array_map('intval', explode(',', $canonical_csv))));
            if (!empty($ids)) { return $ids; }
        }

        $legacy = get_post_meta($variation_id, 'botiga_variation_gallery', true);
        if (is_array($legacy)) {
            $ids = array();
            foreach ($legacy as $entry) {
                if (is_numeric($entry) && (int) $entry > 0 && !wp_attachment_is('video', (int) $entry)) {
                    $ids[] = (int) $entry;
                }
            }
            return $ids;
        }

        return array();
    }

    
    private function read_variation_gallery_entries(int $variation_id): array {
        $images = self::resolve_image_ids($variation_id, 'admin');
        $videos = get_post_meta($variation_id, '_aieo_variation_gallery_videos', true);

        if (empty($images) && empty($videos)) {
            $legacy = get_post_meta($variation_id, 'botiga_variation_gallery', true);
            return is_array($legacy) ? array_values($legacy) : array();
        }
        $videos = is_array($videos) ? $videos : array();

        $videos_by_pos = array();
        foreach ($videos as $v) {
            if (!is_array($v) || !isset($v['position'])) { continue; }
            $videos_by_pos[(int) $v['position']] = $v;
        }

        $total      = count($images) + count($videos_by_pos);
        $result     = array();
        $img_cursor = 0;

        for ($i = 0; $i < $total; $i++) {
            if (isset($videos_by_pos[$i])) {
                $v = $videos_by_pos[$i];
                if (($v['type'] ?? '') === 'attachment' && !empty($v['id'])) {
                    $result[] = (string) $v['id'];
                } elseif (in_array(($v['type'] ?? ''), array('youtube', 'vimeo'), true) && !empty($v['url'])) {
                    $result[] = wp_json_encode(array(
                        'url'          => (string) $v['url'],
                        'aspect_ratio' => isset($v['aspect_ratio']) ? (string) $v['aspect_ratio'] : '16-9',
                    ));
                }
            } elseif ($img_cursor < count($images)) {
                $result[] = (string) $images[$img_cursor++];
            }
        }

        
        while ($img_cursor < count($images)) {
            $result[] = (string) $images[$img_cursor++];
        }

        return $result;
    }

    public function save_variation_gallery($variation_id, $i) {
        if (!empty($_POST['botiga_variation_gallery'][$i]) && is_array($_POST['botiga_variation_gallery'][$i])) {
            $entries = array_map('sanitize_text_field', wp_unslash($_POST['botiga_variation_gallery'][$i]));
            $this->persist_variation_gallery((int) $variation_id, $entries);
        } else {
            $this->clear_variation_gallery((int) $variation_id);
        }
    }

    public function save_variation_galleries_on_product_save($post_id, $post = null) {
        if (empty($_POST['botiga_variation_gallery']) || !is_array($_POST['botiga_variation_gallery'])) { return; }
        $variation_ids = isset($_POST['variable_post_id']) ? array_map('absint', wp_unslash($_POST['variable_post_id'])) : array();
        if (empty($variation_ids)) { return; }
        foreach (wp_unslash($_POST['botiga_variation_gallery']) as $loop_index => $gallery_data) {
            if (!isset($variation_ids[$loop_index])) { continue; }
            $vid = (int) $variation_ids[$loop_index];
            if (!empty($gallery_data) && is_array($gallery_data)) {
                $entries = array_map('sanitize_text_field', $gallery_data);
                $this->persist_variation_gallery($vid, $entries);
            } else {
                $this->clear_variation_gallery($vid);
            }
        }
    }

    
    private function persist_variation_gallery(int $variation_id, array $entries): void {
        $image_ids = array();
        $videos    = array();

        foreach ($entries as $position => $entry) {
            if (!class_exists('AIEO_WC_Compat_Migration')) { continue; }
            $classified = AIEO_WC_Compat_Migration::classify_gallery_entry($entry);
            if ($classified === null) { continue; }

            if ($classified['kind'] === 'image') {
                $image_ids[] = $classified['id'];
            } else {
                $videos[] = array_merge($classified, array('position' => (int) $position));
            }
        }

        if (!empty($image_ids)) {
            update_post_meta($variation_id, '_product_image_gallery', implode(',', $image_ids));
            $existing_thumb = (int) get_post_meta($variation_id, '_thumbnail_id', true);
            if (!$existing_thumb || !wp_attachment_is_image($existing_thumb)) {
                update_post_meta($variation_id, '_thumbnail_id', $image_ids[0]);
            }
        } else {
            delete_post_meta($variation_id, '_product_image_gallery');
        }

        if (!empty($videos)) {
            update_post_meta($variation_id, '_aieo_variation_gallery_videos', $videos);
        } else {
            delete_post_meta($variation_id, '_aieo_variation_gallery_videos');
        }

        update_post_meta($variation_id, '_wc_variation_gallery_legacy_fallback_disabled', 'yes');

        
        
        
        
        delete_post_meta($variation_id, 'botiga_variation_gallery');
    }

    private function clear_variation_gallery(int $variation_id): void {
        delete_post_meta($variation_id, '_product_image_gallery');
        delete_post_meta($variation_id, '_aieo_variation_gallery_videos');
        delete_post_meta($variation_id, 'botiga_variation_gallery');
        
        update_post_meta($variation_id, '_wc_variation_gallery_legacy_fallback_disabled', 'yes');
    }

    public function add_variation_gallery_data($variation_details, $variable_product, $variation) {
        if (!is_singular('product')) { return $variation_details; }
        $gallery = $this->read_variation_gallery_entries((int) $variation->get_id());
        if (empty($gallery)) { return $variation_details; }

        wp_enqueue_script('aieo-variations-gallery');

        $variation_thumb = get_post_meta($variation->get_id(), '_thumbnail_id', true);
        if (!empty($variation_thumb) && !in_array((int) $variation_thumb, array_map('intval', $gallery), true)) {
            $gallery = array_merge(array($variation_thumb), $gallery);
        }
        $placeholder = plugins_url('assets/images/product-display/video-placeholder.svg', AIEO_FILE);

        foreach ($gallery as $attachment_id) {
            if (is_numeric($attachment_id) && wp_attachment_is('video', (int) $attachment_id)) {
                $variation_details['variation_gallery_images'][] = array(
                    'poster' => $placeholder,
                    'url'    => wp_get_attachment_url((int) $attachment_id),
                    'type'   => 'video',
                );
            } elseif (is_string($attachment_id) && preg_match('(youtube|youtu\.be)', $attachment_id)) {
                $obj = json_decode($attachment_id);
                if ($obj && isset($obj->url)) {
                    preg_match('#(?<=v=)[a-zA-Z0-9-]+(?=&)|(?<=v\/)[^&\n]+|(?<=v=)[^&\n]+|(?<=youtu\.be/|youtube\.com/embed/)[^&\n]+#', $obj->url, $m);
                    $variation_details['variation_gallery_images'][] = array(
                        'poster'       => $placeholder,
                        'url'          => $attachment_id,
                        'video_id'     => !empty($m[0]) ? $m[0] : '',
                        'type'         => 'embed',
                        'provider'     => 'youtube',
                        'aspect_ratio' => isset($obj->aspect_ratio) ? $obj->aspect_ratio : '16-9',
                    );
                }
            } elseif (is_string($attachment_id) && preg_match('(vimeo)', $attachment_id)) {
                $obj = json_decode($attachment_id);
                if ($obj && isset($obj->url)) {
                    preg_match('#(?<=vimeo\.com/video/|vimeo\.com/)[^&\n]+#', $obj->url, $m);
                    $variation_details['variation_gallery_images'][] = array(
                        'poster'       => $placeholder,
                        'url'          => $attachment_id,
                        'video_id'     => !empty($m[0]) ? $m[0] : '',
                        'type'         => 'embed',
                        'provider'     => 'vimeo',
                        'aspect_ratio' => isset($obj->aspect_ratio) ? $obj->aspect_ratio : '16-9',
                    );
                }
            } else {
                $att = wc_get_product_attachment_props((int) $attachment_id);
                if (!empty($att['src'])) {
                    $variation_details['variation_gallery_images'][] = $att;
                }
            }
        }
        return $variation_details;
    }

    public function render_subtab() {
        $s = $this->get_settings();
        $nonce = wp_create_nonce(AIEO_DMM::NONCE_ACTION);
        $ajax  = admin_url('admin-ajax.php');
        echo '<div class="aieo-dmm-section">';
        echo '<h2>' . esc_html__('Variations Gallery', 'ai-eshop-optimizer') . '</h2>';
        echo '<p class="description">' . esc_html__('Per-variation image galleries — switching attributes (e.g. colour) swaps the gallery images for that variation. Per-variation gallery picker appears under each variation row on the product edit screen → Variations tab. Same `botiga_variation_gallery` meta key as the legacy plugin + Botiga theme so existing data carries over unchanged.', 'ai-eshop-optimizer') . '</p>';
        echo '<form id="aieo-dmm-vg-form" class="aieo-dmm-form aieo-dmm-card"><table class="form-table">';
        echo '<tr><th>' . esc_html__('Enable', 'ai-eshop-optimizer') . '</th><td><label><input type="checkbox" name="enabled" value="1" ' . checked(!empty($s['enabled']), true, false) . '> ' . esc_html__('Show per-variation gallery picker on product edit + swap on the frontend', 'ai-eshop-optimizer') . '</label></td></tr>';
        echo '</table>';
        echo '<p><button type="button" class="button button-primary" id="aieo-dmm-vg-save">' . esc_html__('Save', 'ai-eshop-optimizer') . '</button>';
        echo ' <span id="aieo-dmm-vg-status" style="margin-left:10px;color:#646970;font-size:13px;"></span></p>';
        echo '</form>';
        echo '<script>(function(){var f=document.getElementById("aieo-dmm-vg-form");var b=document.getElementById("aieo-dmm-vg-save");var s=document.getElementById("aieo-dmm-vg-status");if(!b)return;b.addEventListener("click",function(){var fd=new FormData(f);fd.set("action","aieo_dmm_variations_gallery_save");fd.set("nonce","' . esc_js($nonce) . '");s.style.color="#646970";s.textContent="' . esc_js(__('Saving…', 'ai-eshop-optimizer')) . '";fetch("' . esc_js($ajax) . '",{method:"POST",credentials:"same-origin",body:fd}).then(function(r){return r.json();}).then(function(j){if(j&&j.success){s.style.color="#15803d";s.textContent=j.data.message;}else{s.style.color="#b91c1c";s.textContent=(j&&j.data&&j.data.message)||"' . esc_js(__('Save failed.', 'ai-eshop-optimizer')) . '";}});});})();</script>';

        $this->render_migration_card($nonce, $ajax);

        echo '</div>';
    }

    
    private function render_migration_card($nonce, $ajax) {
        if (!class_exists('AIEO_WC_Compat_Migration')) { return; }
        $status = $this->migration_status_snapshot();
        echo '<div class="aieo-dmm-card" id="aieo-dmm-vg-mig-card" style="margin-top:18px;">';
        echo '<h3>' . esc_html__('WC 10.9 compatibility migration', 'ai-eshop-optimizer') . '</h3>';
        echo '<p class="description">' . esc_html__('Moves legacy variation galleries from botiga_variation_gallery → WC 10.9 canonical _product_image_gallery, and AIEO swatch term metas → canonical color meta + sidecars. Idempotent: rows already attempted are skipped via a per-row marker. Safe to interrupt and resume.', 'ai-eshop-optimizer') . '</p>';

        echo '<table class="widefat striped" style="max-width:640px;margin:8px 0;"><tbody>';
        echo '<tr><th>' . esc_html__('Status', 'ai-eshop-optimizer') . '</th><td id="aieo-dmm-vg-mig-completed-cell">' . ($status['completed_at'] ? '<strong style="color:#15803d;">' . esc_html__('Completed', 'ai-eshop-optimizer') . '</strong> ' . esc_html(gmdate('Y-m-d H:i:s', (int) $status['completed_at']) . ' UTC') : '<strong style="color:#b45309;">' . esc_html__('Stopped — not yet complete', 'ai-eshop-optimizer') . '</strong>') . '</td></tr>';
        echo '<tr><th>' . esc_html__('Variations remaining', 'ai-eshop-optimizer') . '</th><td><span id="aieo-dmm-vg-mig-vars-remaining">' . esc_html(number_format_i18n((int) $status['variations_remaining'])) . '</span></td></tr>';
        echo '<tr><th>' . esc_html__('Swatch terms remaining', 'ai-eshop-optimizer') . '</th><td><span id="aieo-dmm-vg-mig-terms-remaining">' . esc_html(number_format_i18n((int) $status['terms_remaining'])) . '</span></td></tr>';
        echo '<tr><th>' . esc_html__('Action Scheduler pending', 'ai-eshop-optimizer') . '</th><td><span id="aieo-dmm-vg-mig-as-pending">' . esc_html(number_format_i18n((int) $status['as_pending'])) . '</span>';
        if ((int) $status['as_pending'] > 0) {
            echo ' <button type="button" class="button button-small" id="aieo-dmm-vg-mig-clear-as">' . esc_html__('Delete pending AS jobs', 'ai-eshop-optimizer') . '</button>';
        }
        echo '</td></tr>';
        echo '</tbody></table>';

        echo '<p>';
        echo '<button type="button" class="button" id="aieo-dmm-vg-mig-run1">' . esc_html__('Run one batch (250 rows)', 'ai-eshop-optimizer') . '</button> ';
        echo '<button type="button" class="button button-primary" id="aieo-dmm-vg-mig-runall">' . esc_html__('Run all batches', 'ai-eshop-optimizer') . '</button> ';
        echo '<button type="button" class="button button-link-delete" id="aieo-dmm-vg-mig-reset">' . esc_html__('Reset (clear completion flag + markers)', 'ai-eshop-optimizer') . '</button>';
        echo '</p>';

        echo '<div id="aieo-dmm-vg-mig-progress" style="display:none;max-width:640px;">';
        echo '<div style="background:#e5e7eb;height:14px;border-radius:7px;overflow:hidden;"><div id="aieo-dmm-vg-mig-bar" style="background:#2563eb;height:100%;width:0%;transition:width 0.2s;"></div></div>';
        echo '<p id="aieo-dmm-vg-mig-status-text" style="font-size:13px;color:#646970;margin:6px 0 0;"></p>';
        echo '</div>';
        echo '<pre id="aieo-dmm-vg-mig-errors" style="display:none;max-height:200px;overflow:auto;background:#fef2f2;padding:8px;font-size:11px;border-radius:4px;margin-top:8px;"></pre>';

        
        ?>
        <script>
        (function () {
            var card = document.getElementById('aieo-dmm-vg-mig-card');
            if (!card) return;
            var ajax = <?php echo wp_json_encode($ajax); ?>;
            var nonce = <?php echo wp_json_encode($nonce); ?>;
            var btn1 = document.getElementById('aieo-dmm-vg-mig-run1');
            var btnAll = document.getElementById('aieo-dmm-vg-mig-runall');
            var btnReset = document.getElementById('aieo-dmm-vg-mig-reset');
            var btnClearAs = document.getElementById('aieo-dmm-vg-mig-clear-as');
            var progress = document.getElementById('aieo-dmm-vg-mig-progress');
            var bar = document.getElementById('aieo-dmm-vg-mig-bar');
            var statusText = document.getElementById('aieo-dmm-vg-mig-status-text');
            var errors = document.getElementById('aieo-dmm-vg-mig-errors');
            var varsCell = document.getElementById('aieo-dmm-vg-mig-vars-remaining');
            var termsCell = document.getElementById('aieo-dmm-vg-mig-terms-remaining');
            var asCell = document.getElementById('aieo-dmm-vg-mig-as-pending');
            var completedCell = document.getElementById('aieo-dmm-vg-mig-completed-cell');

            function post(action, extra) {
                var fd = new FormData();
                fd.set('action', action);
                fd.set('nonce', nonce);
                if (extra) { Object.keys(extra).forEach(function (k) { fd.set(k, extra[k]); }); }
                return fetch(ajax, { method: 'POST', credentials: 'same-origin', body: fd })
                    .then(function (r) { return r.json(); });
            }

            function refreshStatus() {
                return post('aieo_dmm_vg_migration_status').then(function (j) {
                    if (!j || !j.success) { return null; }
                    var d = j.data;
                    if (varsCell)  varsCell.textContent  = (d.variations_remaining || 0).toLocaleString();
                    if (termsCell) termsCell.textContent = (d.terms_remaining || 0).toLocaleString();
                    if (asCell)    asCell.textContent    = (d.as_pending || 0).toLocaleString();
                    return d;
                });
            }

            function setBusy(busy) {
                [btn1, btnAll, btnReset, btnClearAs].forEach(function (b) { if (b) b.disabled = busy; });
            }

            if (btn1) btn1.addEventListener('click', function () {
                setBusy(true);
                progress.style.display = 'block'; bar.style.width = '0%';
                statusText.style.color = '#646970';
                statusText.textContent = <?php echo wp_json_encode(__('Running one batch…', 'ai-eshop-optimizer')); ?>;
                post('aieo_dmm_vg_migration_run_batch').then(function (j) {
                    setBusy(false);
                    if (!j || !j.success) {
                        statusText.style.color = '#b91c1c';
                        statusText.textContent = (j && j.data && j.data.message) || 'Error';
                        return;
                    }
                    bar.style.width = '100%';
                    statusText.style.color = '#15803d';
                    statusText.textContent = <?php echo wp_json_encode(__('Batch done. Remaining:', 'ai-eshop-optimizer')); ?> + ' ' + (j.data.variations_remaining + j.data.terms_remaining) + (j.data.more ? '' : <?php echo wp_json_encode(' — ' . __('All done.', 'ai-eshop-optimizer')); ?>);
                    refreshStatus();
                });
            });

            if (btnAll) btnAll.addEventListener('click', function () {
                setBusy(true);
                progress.style.display = 'block';
                bar.style.width = '0%';
                statusText.style.color = '#646970';
                statusText.textContent = <?php echo wp_json_encode(__('Running…', 'ai-eshop-optimizer')); ?>;
                var totalAtStart = null;

                function tick() {
                    post('aieo_dmm_vg_migration_run_batch').then(function (j) {
                        if (!j || !j.success) {
                            setBusy(false);
                            statusText.style.color = '#b91c1c';
                            statusText.textContent = (j && j.data && j.data.message) || 'Error';
                            return;
                        }
                        var d = j.data;
                        var remaining = (d.variations_remaining || 0) + (d.terms_remaining || 0);
                        if (totalAtStart === null) { totalAtStart = remaining + 250; }
                        var done = totalAtStart - remaining;
                        var pct = totalAtStart > 0 ? Math.min(100, Math.round((done / totalAtStart) * 100)) : 100;
                        bar.style.width = pct + '%';
                        statusText.textContent = <?php echo wp_json_encode(__('Remaining:', 'ai-eshop-optimizer')); ?> + ' ' + remaining.toLocaleString();
                        refreshStatus();
                        if (d.more) { setTimeout(tick, 200); } else {
                            setBusy(false);
                            statusText.style.color = '#15803d';
                            statusText.textContent = <?php echo wp_json_encode(__('All done.', 'ai-eshop-optimizer')); ?>;
                            if (completedCell && d.completed_at) {
                                completedCell.innerHTML = '<strong style="color:#15803d;">' + <?php echo wp_json_encode(__('Completed', 'ai-eshop-optimizer')); ?> + '</strong> ' + d.completed_at_formatted;
                            }
                        }
                    });
                }
                tick();
            });

            if (btnReset) btnReset.addEventListener('click', function () {
                if (!confirm(<?php echo wp_json_encode(__('Reset will: clear the completion flag, delete the per-row "_aieo_variation_migrated" + "_aieo_swatch_term_migrated" markers from every product/term. The next "Run all" will reprocess every legacy row from scratch. Continue?', 'ai-eshop-optimizer')); ?>)) { return; }
                setBusy(true);
                statusText.style.color = '#646970';
                progress.style.display = 'block'; bar.style.width = '0%';
                statusText.textContent = <?php echo wp_json_encode(__('Resetting…', 'ai-eshop-optimizer')); ?>;
                post('aieo_dmm_vg_migration_reset').then(function (j) {
                    setBusy(false);
                    if (!j || !j.success) {
                        statusText.style.color = '#b91c1c';
                        statusText.textContent = (j && j.data && j.data.message) || 'Error';
                        return;
                    }
                    statusText.style.color = '#15803d';
                    statusText.textContent = j.data.message;
                    if (completedCell) {
                        completedCell.innerHTML = '<strong style="color:#b45309;">' + <?php echo wp_json_encode(__('Stopped — not yet complete', 'ai-eshop-optimizer')); ?> + '</strong>';
                    }
                    refreshStatus();
                });
            });

            if (btnClearAs) btnClearAs.addEventListener('click', function () {
                setBusy(true);
                post('aieo_dmm_vg_migration_clear_as').then(function (j) {
                    setBusy(false);
                    if (j && j.success) { refreshStatus(); }
                });
            });
        })();
        </script>
        <?php
        echo '</div>';
    }

    
    private function migration_status_snapshot() {
        global $wpdb;
        $migrated_meta      = AIEO_WC_Compat_Migration::MIGRATED_META;
        $term_migrated_meta = AIEO_WC_Compat_Migration::TERM_MIGRATED_META;

        
        $variations_remaining = (int) $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(DISTINCT legacy.post_id)
             FROM {$wpdb->postmeta} AS legacy
             INNER JOIN {$wpdb->posts} AS posts
                 ON posts.ID = legacy.post_id AND posts.post_type = 'product_variation'
             LEFT JOIN {$wpdb->postmeta} AS canonical
                 ON canonical.post_id = legacy.post_id
                 AND canonical.meta_key = '_product_image_gallery'
                 AND canonical.meta_value <> ''
             LEFT JOIN {$wpdb->postmeta} AS attempted
                 ON attempted.post_id = legacy.post_id
                 AND attempted.meta_key = %s
                 AND attempted.meta_value = 'yes'
             WHERE legacy.meta_key = 'botiga_variation_gallery'
                 AND legacy.meta_value <> ''
                 AND canonical.post_id IS NULL
                 AND attempted.post_id IS NULL",
            $migrated_meta
        ));

        
        $terms_remaining = (int) $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(DISTINCT tm.term_id)
             FROM {$wpdb->termmeta} AS tm
             INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = tm.term_id
             LEFT JOIN {$wpdb->termmeta} AS canonical
                 ON canonical.term_id = tm.term_id
                 AND canonical.meta_key = 'color'
                 AND canonical.meta_value <> ''
             LEFT JOIN {$wpdb->termmeta} AS sidecar_type
                 ON sidecar_type.term_id = tm.term_id
                 AND sidecar_type.meta_key = '_aieo_swatch_color_type'
             LEFT JOIN {$wpdb->termmeta} AS sidecar_image
                 ON sidecar_image.term_id = tm.term_id
                 AND sidecar_image.meta_key = '_aieo_swatch_image_id'
             LEFT JOIN {$wpdb->termmeta} AS attempted
                 ON attempted.term_id = tm.term_id
                 AND attempted.meta_key = %s
                 AND attempted.meta_value = 'yes'
             WHERE tm.meta_key IN ('product_attribute_color', 'product_attribute_image')
                 AND tm.meta_value <> ''
                 AND tt.taxonomy LIKE %s
                 AND canonical.term_id IS NULL
                 AND sidecar_type.term_id IS NULL
                 AND sidecar_image.term_id IS NULL
                 AND attempted.term_id IS NULL",
            $term_migrated_meta,
            $wpdb->esc_like('pa_') . '%'
        ));

        
        $as_pending = (int) $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM {$wpdb->prefix}actionscheduler_actions
              WHERE hook = %s AND status = 'pending'",
            AIEO_WC_Compat_Migration::UPDATE_HOOK
        ));

        $completed_raw = get_option(AIEO_WC_Compat_Migration::COMPLETED_OPTION);
        $completed_at = is_numeric($completed_raw)
            ? (int) $completed_raw
            : ($completed_raw ? (int) strtotime((string) $completed_raw) : 0);

        return array(
            'variations_remaining'   => $variations_remaining,
            'terms_remaining'        => $terms_remaining,
            'as_pending'             => $as_pending,
            'completed_at'           => $completed_at,
            'completed_at_formatted' => $completed_at ? gmdate('Y-m-d H:i:s', $completed_at) . ' UTC' : '',
        );
    }

    
    public function ajax_migration_status() {
        AIEO_DMM::verify_ajax_request();
        wp_send_json_success($this->migration_status_snapshot());
    }

    
    public function ajax_migration_run_batch() {
        AIEO_DMM::verify_ajax_request();
        if (!class_exists('AIEO_WC_Compat_Migration')) {
            wp_send_json_error(array('message' => __('Migration class not loaded.', 'ai-eshop-optimizer')));
        }
        
        
        
        
        $had_completed = get_option(AIEO_WC_Compat_Migration::COMPLETED_OPTION);
        if ($had_completed) { delete_option(AIEO_WC_Compat_Migration::COMPLETED_OPTION); }
        $more = AIEO_WC_Compat_Migration::run();
        
        
        
        $snap = $this->migration_status_snapshot();
        wp_send_json_success(array_merge($snap, array('more' => (bool) $more)));
    }

    
    public function ajax_migration_reset() {
        AIEO_DMM::verify_ajax_request();
        if (!class_exists('AIEO_WC_Compat_Migration')) {
            wp_send_json_error(array('message' => __('Migration class not loaded.', 'ai-eshop-optimizer')));
        }
        global $wpdb;
        delete_option(AIEO_WC_Compat_Migration::COMPLETED_OPTION);

        $migrated_meta      = AIEO_WC_Compat_Migration::MIGRATED_META;
        $term_migrated_meta = AIEO_WC_Compat_Migration::TERM_MIGRATED_META;

        $pm_deleted = (int) $wpdb->query($wpdb->prepare(
            "DELETE FROM {$wpdb->postmeta} WHERE meta_key = %s",
            $migrated_meta
        ));
        $tm_deleted = (int) $wpdb->query($wpdb->prepare(
            "DELETE FROM {$wpdb->termmeta} WHERE meta_key = %s",
            $term_migrated_meta
        ));

        wp_send_json_success(array(
            'message' => sprintf(
                
                __('Reset done. Cleared completion flag + %1$d postmeta + %2$d termmeta markers.', 'ai-eshop-optimizer'),
                $pm_deleted,
                $tm_deleted
            ),
        ));
    }

    
    public function ajax_migration_clear_as() {
        AIEO_DMM::verify_ajax_request();
        if (!class_exists('AIEO_WC_Compat_Migration')) {
            wp_send_json_error(array('message' => __('Migration class not loaded.', 'ai-eshop-optimizer')));
        }
        global $wpdb;
        $deleted = (int) $wpdb->query($wpdb->prepare(
            "DELETE FROM {$wpdb->prefix}actionscheduler_actions
              WHERE hook = %s AND status IN ('pending','in-progress')",
            AIEO_WC_Compat_Migration::UPDATE_HOOK
        ));
        wp_send_json_success(array(
            'message' => sprintf(
                
                __('Deleted %d pending/in-progress AS jobs.', 'ai-eshop-optimizer'),
                $deleted
            ),
            'deleted' => $deleted,
        ));
    }
}
