<?php

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

class AIEO_DMM_Product_Exchanger extends AIEO_DMM_Module_Base {

    public function get_id()       { return 'product_exchanger'; }
    public function get_label()    { return __('Product Exchanger', 'ai-eshop-optimizer'); }
    public function get_priority() { return 12; }
    public function get_group()    { return 'import_export'; }

    public function __construct() {
        $this->load_services();
    }

    private function load_services() {
        $base = AIEO_DIR . 'includes/dmm/exchanger/';
        foreach (array(
            'class-aieo-exchanger-run-log.php',
            'class-aieo-exchanger-feeds.php',
            'class-aieo-exchanger-imports.php',
            'class-aieo-exchanger-product-serializer.php',
            'class-aieo-exchanger-image-resolver.php',
            'class-aieo-exchanger-term-resolver.php',
            'class-aieo-exchanger-product-importer.php',
            'class-aieo-exchanger-feed-builder.php',
            'class-aieo-exchanger-puller.php',
            'class-aieo-exchanger-rest.php',
            'class-aieo-exchanger-cron.php',
        ) as $f) {
            $path = $base . $f;
            if (file_exists($path)) { require_once $path; }
        }
        if (class_exists('AIEO_Exchanger_Rest'))  { AIEO_Exchanger_Rest::register(); }
        if (class_exists('AIEO_Exchanger_Cron')) { AIEO_Exchanger_Cron::register(); }
    }

    public function register_hooks() {
        
        add_action('wp_ajax_aieo_exch_save_feed',     array($this, 'ajax_save_feed'));
        add_action('wp_ajax_aieo_exch_delete_feed',   array($this, 'ajax_delete_feed'));
        add_action('wp_ajax_aieo_exch_build_feed',    array($this, 'ajax_build_feed'));
        add_action('wp_ajax_aieo_exch_rotate_token',  array($this, 'ajax_rotate_token'));
        add_action('wp_ajax_aieo_exch_notify_targets',array($this, 'ajax_notify_targets'));
        add_action('wp_ajax_aieo_exch_save_import',   array($this, 'ajax_save_import'));
        add_action('wp_ajax_aieo_exch_delete_import', array($this, 'ajax_delete_import'));
        add_action('wp_ajax_aieo_exch_run_import',    array($this, 'ajax_run_import'));
    }

    public function render_subtab() {
        $section = isset($_GET['exch_section']) ? sanitize_key((string) $_GET['exch_section']) : 'feeds';
        if (!in_array($section, array('feeds', 'imports', 'runlog', 'settings'), true)) {
            $section = 'feeds';
        }
        $base_url = admin_url('admin.php?page=' . AIEO_DMM::MENU_SLUG . '&dmm_tab=product_exchanger');

        echo '<div class="aieo-dmm-section">';
        echo '<h2>' . esc_html__('Product Exchanger', 'ai-eshop-optimizer') . '</h2>';
        echo '<p class="description">' . esc_html__('Publish product feeds (token-gated, sharded JSON) for sister sites to consume, and import from feeds published by source sites. Replaces the rudr-simple-wp-crosspost plugin family.', 'ai-eshop-optimizer') . '</p>';

        echo '<div class="nav-tab-wrapper" style="margin-bottom:14px;">';
        foreach (array(
            'feeds'    => __('Feeds (outbound)', 'ai-eshop-optimizer'),
            'imports'  => __('Imports (inbound)', 'ai-eshop-optimizer'),
            'runlog'   => __('Run log', 'ai-eshop-optimizer'),
            'settings' => __('Settings', 'ai-eshop-optimizer'),
        ) as $slug => $label) {
            $active = $section === $slug ? ' nav-tab-active' : '';
            echo '<a href="' . esc_url($base_url . '&exch_section=' . $slug) . '" class="nav-tab' . $active . '">' . esc_html($label) . '</a>'; 
        }
        echo '</div>';

        switch ($section) {
            case 'imports':  $this->render_imports();  break;
            case 'runlog':   $this->render_runlog();   break;
            case 'settings': $this->render_settings(); break;
            case 'feeds':
            default:         $this->render_feeds();
        }

        echo '</div>';
    }

    

    private function render_feeds() {
        $feeds = AIEO_Exchanger_Feeds::list_all();
        $nonce = wp_create_nonce('aieo_exch_admin');
        $ajax  = admin_url('admin-ajax.php');
        $cron_choices = $this->cron_choices();

        echo '<table class="wp-list-table widefat fixed striped">';
        echo '<thead><tr>';
        echo '<th>' . esc_html__('Feed', 'ai-eshop-optimizer') . '</th>';
        echo '<th>' . esc_html__('Slug / token', 'ai-eshop-optimizer') . '</th>';
        echo '<th>' . esc_html__('Schedule', 'ai-eshop-optimizer') . '</th>';
        echo '<th>' . esc_html__('Last build', 'ai-eshop-optimizer') . '</th>';
        echo '<th>' . esc_html__('Enabled', 'ai-eshop-optimizer') . '</th>';
        echo '<th></th>';
        echo '</tr></thead><tbody>';
        if (empty($feeds)) {
            echo '<tr><td colspan="6"><em>' . esc_html__('No feeds yet. Create one below.', 'ai-eshop-optimizer') . '</em></td></tr>';
        } else {
            foreach ($feeds as $feed) {
                $manifest_url = AIEO_Exchanger_Feeds::manifest_url($feed);
                $fid = (int) $feed['id'];
                echo '<tr>';
                echo '<td><strong>' . esc_html($feed['label'] ?: $feed['slug']) . '</strong></td>';
                echo '<td><code>' . esc_html($feed['slug']) . '</code><br>';
                echo '<input type="text" readonly value="' . esc_attr((string) $feed['feed_token']) . '" class="code aieo-exch-token-input" data-aieo-feed-id="' . esc_attr($fid) . '" style="font-size:11px;width:100%;max-width:520px;margin:4px 0;font-family:monospace;" onclick="this.select();">';
                echo '<small><button type="button" class="button-link aieo-exch-token-copy" data-aieo-feed-id="' . esc_attr($fid) . '">' . esc_html__('Copy token', 'ai-eshop-optimizer') . '</button> · ';
                echo '<a href="#" data-aieo-exch-copy="' . esc_attr($manifest_url) . '">' . esc_html__('Copy manifest URL', 'ai-eshop-optimizer') . '</a></small></td>';
                echo '<td>' . esc_html($feed['schedule_cron'] ?: '—') . '</td>';
                echo '<td>' . esc_html($feed['last_built_at'] ?: '—') . '<br><small style="color:' . ((string) $feed['last_build_status'] === 'OK' ? '#15803d' : '#b91c1c') . ';">' . esc_html((string) $feed['last_build_status']) . '</small></td>';
                echo '<td>' . ($feed['enabled'] ? '✓' : '—') . '</td>';
                echo '<td style="white-space:nowrap;">';
                echo '<button class="button" data-aieo-exch-edit-feed="' . esc_attr((int) $feed['id']) . '">' . esc_html__('Edit', 'ai-eshop-optimizer') . '</button> ';
                echo '<button class="button button-primary" data-aieo-exch-build="' . esc_attr((int) $feed['id']) . '">' . esc_html__('Build now', 'ai-eshop-optimizer') . '</button> ';
                echo '<button class="button" data-aieo-exch-rotate="' . esc_attr((int) $feed['id']) . '">' . esc_html__('Rotate token', 'ai-eshop-optimizer') . '</button> ';
                echo '<button class="button" data-aieo-exch-notify="' . esc_attr((int) $feed['id']) . '">' . esc_html__('Notify targets', 'ai-eshop-optimizer') . '</button> ';
                echo '<button class="button button-link-delete" data-aieo-exch-delete-feed="' . esc_attr((int) $feed['id']) . '">' . esc_html__('Delete', 'ai-eshop-optimizer') . '</button>';
                echo '</td></tr>';
            }
        }
        echo '</tbody></table>';
        echo '<p id="aieo-exch-feed-status" style="margin-top:8px;font-size:13px;"></p>';

        echo '<div class="aieo-dmm-card" style="margin-top:18px;">';
        echo '<h3 id="aieo-exch-feed-form-title">' . esc_html__('Add a feed', 'ai-eshop-optimizer') . '</h3>';
        echo '<form id="aieo-exch-feed-form" class="aieo-dmm-form" onsubmit="return false;">';
        echo '<input type="hidden" name="id" value="0">';
        echo '<table class="form-table">';
        echo '<tr><th>' . esc_html__('Slug', 'ai-eshop-optimizer') . '</th><td><input type="text" name="slug" required pattern="[a-z0-9_-]+" class="regular-text" placeholder="all-products"></td></tr>';
        echo '<tr><th>' . esc_html__('Label', 'ai-eshop-optimizer') . '</th><td><input type="text" name="label" class="regular-text"></td></tr>';
        echo '<tr><th>' . esc_html__('Schedule', 'ai-eshop-optimizer') . '</th><td><select name="schedule_cron">';
        foreach ($cron_choices as $val => $label) {
            echo '<option value="' . esc_attr($val) . '">' . esc_html($label) . '</option>';
        }
        echo '</select><p class="description">' . esc_html__('Hourly cron tick rebuilds the feed when the cadence is due.', 'ai-eshop-optimizer') . '</p></td></tr>';
        echo '<tr><th>' . esc_html__('Shard size', 'ai-eshop-optimizer') . '</th><td><input type="number" name="shard_size" value="500" min="50" max="2000"><p class="description">' . esc_html__('Products per shard JSON file. 500 is a safe default for catalogs up to 50k.', 'ai-eshop-optimizer') . '</p></td></tr>';
        echo '<tr><th>' . esc_html__('Price min', 'ai-eshop-optimizer') . '</th><td><input type="number" name="price_min" step="0.01"></td></tr>';
        echo '<tr><th>' . esc_html__('Price max', 'ai-eshop-optimizer') . '</th><td><input type="number" name="price_max" step="0.01"></td></tr>';
        echo '</table>';

        echo '<h4>' . esc_html__('Targeting', 'ai-eshop-optimizer') . '</h4>';
        
        include AIEO_DIR . 'assets/pages/dmm/_partials/targeting-selector.php';

        echo '<p style="margin-top:14px;">';
        echo '<button type="button" class="button button-primary" id="aieo-exch-feed-save">' . esc_html__('Save feed', 'ai-eshop-optimizer') . '</button> ';
        echo '<button type="button" class="button" id="aieo-exch-feed-cancel">' . esc_html__('Reset form', 'ai-eshop-optimizer') . '</button> ';
        echo '<span id="aieo-exch-feed-savestatus" style="margin-left:10px;font-size:13px;color:#646970;"></span>';
        echo '</p>';
        echo '</form>';
        echo '</div>';

        $this->print_admin_js($nonce, $ajax, $feeds);
    }

    private function render_imports() {
        $jobs  = AIEO_Exchanger_Imports::list_all();
        $nonce = wp_create_nonce('aieo_exch_admin');
        $ajax  = admin_url('admin-ajax.php');
        $cron_choices = $this->cron_choices();
        $modes = array(
            'create_link_only'      => __('1 — Create new (link existing terms only)', 'ai-eshop-optimizer'),
            'create_with_term_meta' => __('2 — Create new + create missing terms WITH meta + images', 'ai-eshop-optimizer'),
            'create_no_term_meta'   => __('3 — Create new + create missing terms WITHOUT meta/images', 'ai-eshop-optimizer'),
            'update_only'           => __('4 — Update existing only (skip new)', 'ai-eshop-optimizer'),
            'overwrite'             => __('5 — Overwrite (full replace, unlink stale terms)', 'ai-eshop-optimizer'),
        );

        echo '<table class="wp-list-table widefat fixed striped">';
        echo '<thead><tr>';
        echo '<th>' . esc_html__('Job', 'ai-eshop-optimizer') . '</th>';
        echo '<th>' . esc_html__('Source', 'ai-eshop-optimizer') . '</th>';
        echo '<th>' . esc_html__('Mode / match', 'ai-eshop-optimizer') . '</th>';
        echo '<th>' . esc_html__('Schedule', 'ai-eshop-optimizer') . '</th>';
        echo '<th>' . esc_html__('Last run', 'ai-eshop-optimizer') . '</th>';
        echo '<th>' . esc_html__('Enabled', 'ai-eshop-optimizer') . '</th>';
        echo '<th></th>';
        echo '</tr></thead><tbody>';
        if (empty($jobs)) {
            echo '<tr><td colspan="7"><em>' . esc_html__('No import jobs yet. Create one below.', 'ai-eshop-optimizer') . '</em></td></tr>';
        } else {
            foreach ($jobs as $job) {
                echo '<tr>';
                echo '<td><strong>' . esc_html($job['label'] ?: $job['slug']) . '</strong><br><code style="font-size:11px;">' . esc_html($job['slug']) . '</code></td>';
                echo '<td><small style="word-break:break-all;">' . esc_html($job['source_url']) . '</small></td>';
                echo '<td><code>' . esc_html($job['mode']) . '</code><br><small>' . esc_html($job['match_key']) . '</small></td>';
                echo '<td>' . esc_html($job['schedule_cron'] ?: '—') . '</td>';
                echo '<td>' . esc_html($job['last_run_at'] ?: '—') . '<br><small style="color:' . ((string) $job['last_status'] === 'OK' ? '#15803d' : '#b91c1c') . ';">' . esc_html((string) $job['last_status']) . '</small></td>';
                echo '<td>' . ($job['enabled'] ? '✓' : '—') . '</td>';
                echo '<td style="white-space:nowrap;">';
                echo '<button class="button" data-aieo-exch-edit-import="' . esc_attr((int) $job['id']) . '">' . esc_html__('Edit', 'ai-eshop-optimizer') . '</button> ';
                echo '<button class="button button-primary" data-aieo-exch-run="' . esc_attr((int) $job['id']) . '">' . esc_html__('Run now', 'ai-eshop-optimizer') . '</button> ';
                echo '<button class="button button-link-delete" data-aieo-exch-delete-import="' . esc_attr((int) $job['id']) . '">' . esc_html__('Delete', 'ai-eshop-optimizer') . '</button>';
                echo '</td></tr>';
            }
        }
        echo '</tbody></table>';
        echo '<p id="aieo-exch-import-status" style="margin-top:8px;font-size:13px;"></p>';

        echo '<div class="aieo-dmm-card" style="margin-top:18px;">';
        echo '<h3 id="aieo-exch-import-form-title">' . esc_html__('Add an import job', 'ai-eshop-optimizer') . '</h3>';
        echo '<form id="aieo-exch-import-form" class="aieo-dmm-form" onsubmit="return false;">';
        echo '<input type="hidden" name="id" value="0">';
        echo '<table class="form-table">';
        echo '<tr><th>' . esc_html__('Slug', 'ai-eshop-optimizer') . '</th><td><input type="text" name="slug" required pattern="[a-z0-9_-]+" class="regular-text" placeholder="from-master"></td></tr>';
        echo '<tr><th>' . esc_html__('Label', 'ai-eshop-optimizer') . '</th><td><input type="text" name="label" class="regular-text"></td></tr>';
        echo '<tr><th>' . esc_html__('Source manifest URL', 'ai-eshop-optimizer') . '</th><td><input type="text" name="source_url" class="large-text" placeholder="https://source.example/wp-json/aieo/v1/exchanger/{slug}/manifest"></td></tr>';
        echo '<tr><th>' . esc_html__('Feed token', 'ai-eshop-optimizer') . '</th><td><input type="text" name="feed_token" class="large-text" placeholder="64-char hex from the source feed"></td></tr>';
        echo '<tr><th>' . esc_html__('Match key', 'ai-eshop-optimizer') . '</th><td><select name="match_key"><option value="sku">SKU</option><option value="barcode">Barcode (_global_unique_id)</option></select></td></tr>';
        echo '<tr><th>' . esc_html__('Mode', 'ai-eshop-optimizer') . '</th><td><select name="mode">';
        foreach ($modes as $val => $label) {
            $sel = ($val === 'create_with_term_meta') ? ' selected' : '';
            echo '<option value="' . esc_attr($val) . '"' . $sel . '>' . esc_html($label) . '</option>'; 
        }
        echo '</select></td></tr>';
        echo '<tr><th>' . esc_html__('Schedule', 'ai-eshop-optimizer') . '</th><td><select name="schedule_cron">';
        foreach ($cron_choices as $val => $label) {
            echo '<option value="' . esc_attr($val) . '">' . esc_html($label) . '</option>';
        }
        echo '</select></td></tr>';
        echo '<tr><th>' . esc_html__('Enabled', 'ai-eshop-optimizer') . '</th><td><label><input type="checkbox" name="enabled" value="1" checked></label></td></tr>';
        echo '</table>';
        echo '<p>';
        echo '<button type="button" class="button button-primary" id="aieo-exch-import-save">' . esc_html__('Save job', 'ai-eshop-optimizer') . '</button> ';
        echo '<button type="button" class="button" id="aieo-exch-import-cancel">' . esc_html__('Reset form', 'ai-eshop-optimizer') . '</button> ';
        echo '<span id="aieo-exch-import-savestatus" style="margin-left:10px;font-size:13px;color:#646970;"></span>';
        echo '</p>';
        echo '</form>';
        echo '</div>';

        $this->print_admin_js($nonce, $ajax, array(), $jobs);
    }

    private function render_runlog() {
        $rows = AIEO_Exchanger_Run_Log::recent(100);
        echo '<table class="wp-list-table widefat fixed striped">';
        echo '<thead><tr>';
        echo '<th>' . esc_html__('When', 'ai-eshop-optimizer') . '</th>';
        echo '<th>' . esc_html__('Side / job', 'ai-eshop-optimizer') . '</th>';
        echo '<th>' . esc_html__('Shard', 'ai-eshop-optimizer') . '</th>';
        echo '<th>' . esc_html__('Processed', 'ai-eshop-optimizer') . '</th>';
        echo '<th>' . esc_html__('Created', 'ai-eshop-optimizer') . '</th>';
        echo '<th>' . esc_html__('Updated', 'ai-eshop-optimizer') . '</th>';
        echo '<th>' . esc_html__('Skipped', 'ai-eshop-optimizer') . '</th>';
        echo '<th>' . esc_html__('Errors', 'ai-eshop-optimizer') . '</th>';
        echo '</tr></thead><tbody>';
        if (empty($rows)) {
            echo '<tr><td colspan="8"><em>' . esc_html__('No runs yet.', 'ai-eshop-optimizer') . '</em></td></tr>';
        } else {
            foreach ($rows as $r) {
                $errors = (int) $r['errors_count'];
                echo '<tr>';
                echo '<td>' . esc_html((string) $r['started_at']) . ' UTC</td>';
                echo '<td>' . esc_html((string) $r['side']) . ' #' . (int) $r['job_id'] . '</td>';
                echo '<td>' . (int) $r['shard'] . '</td>';
                echo '<td>' . (int) $r['processed'] . '</td>';
                echo '<td style="color:#15803d;">' . (int) $r['created'] . '</td>';
                echo '<td>' . (int) $r['updated'] . '</td>';
                echo '<td>' . (int) $r['skipped'] . '</td>';
                echo '<td' . ($errors > 0 ? ' style="color:#b91c1c;"' : '') . '>' . $errors . '</td>'; 
                echo '</tr>';
                if ($errors > 0 && !empty($r['errors_json'])) {
                    echo '<tr><td colspan="8" style="background:#fef2f2;font-family:monospace;font-size:11px;"><pre style="margin:0;white-space:pre-wrap;">' . esc_html(substr((string) $r['errors_json'], 0, 1500)) . '</pre></td></tr>';
                }
            }
        }
        echo '</tbody></table>';
    }

    private function render_settings() {
        echo '<div class="aieo-dmm-card">';
        echo '<h3 style="margin-top:0;">' . esc_html__('Schema state', 'ai-eshop-optimizer') . '</h3>';
        echo '<ul>';
        foreach (array(
            'aieo_dmm_exchanger_feeds'   => __('Feeds', 'ai-eshop-optimizer'),
            'aieo_dmm_exchanger_imports' => __('Imports', 'ai-eshop-optimizer'),
            'aieo_dmm_exchanger_run_log' => __('Run log', 'ai-eshop-optimizer'),
        ) as $tbl => $label) {
            global $wpdb;
            $full = $wpdb->prefix . $tbl;
            
            $exists = (string) $wpdb->get_var("SHOW TABLES LIKE '{$full}'") === $full;
            echo '<li>' . esc_html($label) . ' (<code>' . esc_html($full) . '</code>) — ' . ($exists ? '<span style="color:#15803d">✓</span>' : '<span style="color:#b91c1c">missing</span>') . '</li>';
        }
        echo '</ul>';
        echo '<p class="description">' . esc_html__('Schema is auto-created on plugin activation. To rebuild manually: wp eval \'aieo_dmm_create_tables();\'', 'ai-eshop-optimizer') . '</p>';
        echo '</div>';

        echo '<div class="aieo-dmm-card" style="margin-top:14px;">';
        echo '<h3 style="margin-top:0;">' . esc_html__('Cron events', 'ai-eshop-optimizer') . '</h3>';
        echo '<ul>';
        foreach (array(
            'aieo_exchanger_build_feeds_tick'   => __('Source: build feeds tick (hourly)', 'ai-eshop-optimizer'),
            'aieo_exchanger_run_imports_tick'   => __('Target: run imports tick (hourly)', 'ai-eshop-optimizer'),
            'aieo_exchanger_prune_runlog'       => __('Run-log retention prune (daily)', 'ai-eshop-optimizer'),
        ) as $hook => $label) {
            $next = wp_next_scheduled($hook);
            echo '<li>' . esc_html($label) . ' — ' . ($next ? esc_html(date_i18n('Y-m-d H:i:s', $next)) : '<em>not scheduled</em>') . '</li>';
        }
        echo '</ul>';
        echo '</div>';
    }

    private function cron_choices() {
        return array(
            ''           => __('Manual only', 'ai-eshop-optimizer'),
            'hourly'     => __('Hourly', 'ai-eshop-optimizer'),
            'twicedaily' => __('Twice daily', 'ai-eshop-optimizer'),
            'daily'      => __('Daily', 'ai-eshop-optimizer'),
            'weekly'     => __('Weekly', 'ai-eshop-optimizer'),
        );
    }

    
    private function print_admin_js($nonce, $ajax, $feeds = array(), $jobs = array()) {
        $feeds_json = wp_json_encode(array_map(function($f) {
            return array(
                'id'                    => (int) $f['id'],
                'slug'                  => (string) $f['slug'],
                'label'                 => (string) $f['label'],
                'enabled'               => (int) $f['enabled'],
                'schedule_cron'         => (string) $f['schedule_cron'],
                'shard_size'            => (int) $f['shard_size'],
                'rule_operator'         => (string) ($f['rule_operator'] ?? 'AND'),
                'date_from'             => (string) ($f['date_from'] ?? ''),
                'date_to'               => (string) ($f['date_to']   ?? ''),
                'min_subtotal'          => (float)  $f['min_subtotal'],
                'price_min'             => $f['price_min'],
                'price_max'             => $f['price_max'],
                'brand_term_ids'        => array_values((array) $f['brand_term_ids']),
                'category_term_ids'     => array_values((array) $f['category_term_ids']),
                'need_term_ids'         => array_values((array) $f['need_term_ids']),
                'product_ids'           => array_values((array) $f['product_ids']),
                'excluded_brand_ids'    => array_values((array) $f['excluded_brand_ids']),
                'excluded_category_ids' => array_values((array) $f['excluded_category_ids']),
                'excluded_need_ids'     => array_values((array) $f['excluded_need_ids']),
                'excluded_product_ids'  => array_values((array) $f['excluded_product_ids']),
            );
        }, $feeds));
        $jobs_json = wp_json_encode(array_map(function($j) {
            return array(
                'id'           => (int) $j['id'],
                'slug'         => (string) $j['slug'],
                'label'        => (string) $j['label'],
                'enabled'      => (int) $j['enabled'],
                'source_url'   => (string) $j['source_url'],
                'feed_token'   => (string) $j['feed_token'],
                'match_key'    => (string) $j['match_key'],
                'mode'         => (string) $j['mode'],
                'schedule_cron'=> (string) $j['schedule_cron'],
            );
        }, $jobs));

        
        echo '<script>(function(){
            var nonce = "' . esc_js($nonce) . '";
            var ajax  = "' . esc_js($ajax) . '";
            var FEEDS = ' . $feeds_json . ';
            var JOBS  = ' . $jobs_json . ';

            function post(action, data) {
                var fd = new FormData();
                fd.set("action", action); fd.set("nonce", nonce);
                Object.keys(data || {}).forEach(function(k){
                    var v = data[k];
                    if (Array.isArray(v)) { v.forEach(function(item){ fd.append(k, item); }); }
                    else { fd.set(k, v); }
                });
                return fetch(ajax, {method:"POST", credentials:"same-origin", body: fd}).then(function(r){ return r.json(); });
            }

            function setStatus(id, color, text){
                var el = document.getElementById(id); if (!el) return;
                el.style.color = color; el.textContent = text;
            }

            // ---- FEED form ----
            var feedForm = document.getElementById("aieo-exch-feed-form");
            if (feedForm) {
                document.querySelectorAll("[data-aieo-exch-edit-feed]").forEach(function(b){
                    b.addEventListener("click", function(){
                        var id = parseInt(b.getAttribute("data-aieo-exch-edit-feed"), 10);
                        var f = FEEDS.filter(function(x){return x.id===id;})[0]; if (!f) return;
                        feedForm.querySelector("[name=id]").value       = f.id;
                        feedForm.querySelector("[name=slug]").value     = f.slug;
                        feedForm.querySelector("[name=label]").value    = f.label;
                        feedForm.querySelector("[name=schedule_cron]").value = f.schedule_cron;
                        feedForm.querySelector("[name=shard_size]").value    = f.shard_size;
                        feedForm.querySelector("[name=price_min]").value     = f.price_min || "";
                        feedForm.querySelector("[name=price_max]").value     = f.price_max || "";
                        feedForm.querySelector("[name=date_from]").value     = f.date_from || "";
                        feedForm.querySelector("[name=date_to]").value       = f.date_to   || "";
                        feedForm.querySelector("[name=min_subtotal]").value  = f.min_subtotal || 0;
                        var op = (f.rule_operator || "AND").toUpperCase();
                        feedForm.querySelectorAll("[name=rule_operator]").forEach(function(r){ r.checked = (r.value === op); });
                        document.getElementById("aieo-exch-feed-form-title").textContent = "Edit feed";
                        document.getElementById("aieo-exch-feed-form-title").scrollIntoView({behavior:"smooth"});
                    });
                });
                document.getElementById("aieo-exch-feed-cancel").addEventListener("click", function(){
                    feedForm.reset(); feedForm.querySelector("[name=id]").value = 0;
                    document.getElementById("aieo-exch-feed-form-title").textContent = "Add a feed";
                });
                document.getElementById("aieo-exch-feed-save").addEventListener("click", function(){
                    var fd = new FormData(feedForm);
                    fd.set("action", "aieo_exch_save_feed"); fd.set("nonce", nonce);
                    setStatus("aieo-exch-feed-savestatus", "#646970", "Saving…");
                    fetch(ajax, {method:"POST", credentials:"same-origin", body: fd})
                        .then(function(r){return r.json();}).then(function(j){
                            if (j && j.success) {
                                setStatus("aieo-exch-feed-savestatus", "#15803d", "Saved.");
                                setTimeout(function(){ location.reload(); }, 600);
                            } else {
                                setStatus("aieo-exch-feed-savestatus", "#b91c1c", (j && j.data && j.data.message) || "Save failed.");
                            }
                        });
                });
            }
            document.querySelectorAll("[data-aieo-exch-build]").forEach(function(b){
                b.addEventListener("click", function(){
                    var id = b.getAttribute("data-aieo-exch-build");
                    setStatus("aieo-exch-feed-status", "#646970", "Building feed " + id + "…");
                    b.disabled = true;
                    post("aieo_exch_build_feed", {id: id}).then(function(j){
                        b.disabled = false;
                        if (j && j.success) {
                            var d = j.data || {};
                            setStatus("aieo-exch-feed-status", "#15803d", "Built " + (d.products|0) + " products in " + (d.shards|0) + " shard(s). Manifest: " + (d.manifest_url || ""));
                            setTimeout(function(){ location.reload(); }, 1500);
                        } else {
                            setStatus("aieo-exch-feed-status", "#b91c1c", (j && j.data && j.data.message) || "Build failed.");
                        }
                    });
                });
            });
            document.querySelectorAll("[data-aieo-exch-rotate]").forEach(function(b){
                b.addEventListener("click", function(){
                    if (!confirm("Rotate the bearer token? Targets configured with the old token will stop working until re-paired.")) return;
                    var id = b.getAttribute("data-aieo-exch-rotate");
                    post("aieo_exch_rotate_token", {id: id}).then(function(j){
                        if (j && j.success) {
                            var newTok = (j.data && j.data.feed_token) ? j.data.feed_token : "";
                            var inp = document.querySelector(".aieo-exch-token-input[data-aieo-feed-id=\'" + id + "\']");
                            if (inp) { inp.value = newTok; inp.focus(); inp.select(); }
                            setStatus("aieo-exch-feed-status", "#15803d", "Token rotated. The new value is shown in the row above — click \'Copy token\' to copy.");
                        } else {
                            setStatus("aieo-exch-feed-status", "#b91c1c", (j && j.data && j.data.message) || "Rotate failed.");
                        }
                    });
                });
            });
            document.querySelectorAll(".aieo-exch-token-copy").forEach(function(b){
                b.addEventListener("click", function(){
                    var id = b.getAttribute("data-aieo-feed-id");
                    var inp = document.querySelector(".aieo-exch-token-input[data-aieo-feed-id=\'" + id + "\']");
                    if (!inp) return;
                    navigator.clipboard.writeText(inp.value).then(function(){
                        var orig = b.textContent;
                        b.textContent = "Copied!"; setTimeout(function(){ b.textContent = orig; }, 1200);
                    });
                });
            });
            document.querySelectorAll("[data-aieo-exch-notify]").forEach(function(b){
                b.addEventListener("click", function(){
                    post("aieo_exch_notify_targets", {id: b.getAttribute("data-aieo-exch-notify")}).then(function(j){
                        if (j && j.success) {
                            var d = j.data || {};
                            setStatus("aieo-exch-feed-status", "#15803d", "Notified " + (d.notified|0) + " target(s); " + (d.errors|0) + " error(s).");
                        } else {
                            setStatus("aieo-exch-feed-status", "#b91c1c", (j && j.data && j.data.message) || "Notify failed.");
                        }
                    });
                });
            });
            document.querySelectorAll("[data-aieo-exch-delete-feed]").forEach(function(b){
                b.addEventListener("click", function(){
                    if (!confirm("Delete this feed? Existing destination jobs will lose access until re-paired.")) return;
                    post("aieo_exch_delete_feed", {id: b.getAttribute("data-aieo-exch-delete-feed")}).then(function(){ location.reload(); });
                });
            });

            // Copy manifest URL helper
            document.querySelectorAll("[data-aieo-exch-copy]").forEach(function(a){
                a.addEventListener("click", function(e){
                    e.preventDefault();
                    var url = a.getAttribute("data-aieo-exch-copy");
                    navigator.clipboard.writeText(url).then(function(){
                        a.textContent = "Copied!"; setTimeout(function(){ a.textContent = "Copy manifest URL"; }, 1200);
                    });
                });
            });

            // ---- IMPORT form ----
            var importForm = document.getElementById("aieo-exch-import-form");
            if (importForm) {
                document.querySelectorAll("[data-aieo-exch-edit-import]").forEach(function(b){
                    b.addEventListener("click", function(){
                        var id = parseInt(b.getAttribute("data-aieo-exch-edit-import"), 10);
                        var j = JOBS.filter(function(x){return x.id===id;})[0]; if (!j) return;
                        importForm.querySelector("[name=id]").value         = j.id;
                        importForm.querySelector("[name=slug]").value       = j.slug;
                        importForm.querySelector("[name=label]").value      = j.label;
                        importForm.querySelector("[name=source_url]").value = j.source_url;
                        importForm.querySelector("[name=feed_token]").value = j.feed_token;
                        importForm.querySelector("[name=match_key]").value  = j.match_key;
                        importForm.querySelector("[name=mode]").value       = j.mode;
                        importForm.querySelector("[name=schedule_cron]").value = j.schedule_cron;
                        importForm.querySelector("[name=enabled]").checked  = !!j.enabled;
                        document.getElementById("aieo-exch-import-form-title").textContent = "Edit import job";
                        document.getElementById("aieo-exch-import-form-title").scrollIntoView({behavior:"smooth"});
                    });
                });
                document.getElementById("aieo-exch-import-cancel").addEventListener("click", function(){
                    importForm.reset(); importForm.querySelector("[name=id]").value = 0;
                    document.getElementById("aieo-exch-import-form-title").textContent = "Add an import job";
                });
                document.getElementById("aieo-exch-import-save").addEventListener("click", function(){
                    var fd = new FormData(importForm);
                    fd.set("action", "aieo_exch_save_import"); fd.set("nonce", nonce);
                    setStatus("aieo-exch-import-savestatus", "#646970", "Saving…");
                    fetch(ajax, {method:"POST", credentials:"same-origin", body: fd})
                        .then(function(r){return r.json();}).then(function(j){
                            if (j && j.success) {
                                setStatus("aieo-exch-import-savestatus", "#15803d", "Saved.");
                                setTimeout(function(){ location.reload(); }, 600);
                            } else {
                                setStatus("aieo-exch-import-savestatus", "#b91c1c", (j && j.data && j.data.message) || "Save failed.");
                            }
                        });
                });
            }
            document.querySelectorAll("[data-aieo-exch-run]").forEach(function(b){
                b.addEventListener("click", function(){
                    var id = b.getAttribute("data-aieo-exch-run");
                    setStatus("aieo-exch-import-status", "#646970", "Running import " + id + "…");
                    b.disabled = true;
                    post("aieo_exch_run_import", {id: id}).then(function(j){
                        b.disabled = false;
                        if (j && j.success) {
                            var d = j.data || {};
                            setStatus("aieo-exch-import-status", "#15803d", "Run complete — processed " + (d.processed|0) + ", created " + (d.created|0) + ", updated " + (d.updated|0) + ", skipped " + (d.skipped|0) + ", errors " + (d.errors|0) + ".");
                        } else {
                            setStatus("aieo-exch-import-status", "#b91c1c", (j && j.data && j.data.message) || "Run failed.");
                        }
                    });
                });
            });
            document.querySelectorAll("[data-aieo-exch-delete-import]").forEach(function(b){
                b.addEventListener("click", function(){
                    if (!confirm("Delete this import job?")) return;
                    post("aieo_exch_delete_import", {id: b.getAttribute("data-aieo-exch-delete-import")}).then(function(){ location.reload(); });
                });
            });
        })();</script>';
        
    }

    

    public function ajax_save_feed() {
        check_ajax_referer('aieo_exch_admin', 'nonce');
        if (!$this->can_manage()) { wp_send_json_error(array('message' => 'forbidden')); }

        $data = array(
            'id'             => isset($_POST['id']) ? (int) $_POST['id'] : 0,
            'slug'           => isset($_POST['slug'])  ? sanitize_key(wp_unslash((string) $_POST['slug']))   : '',
            'label'          => isset($_POST['label']) ? sanitize_text_field(wp_unslash((string) $_POST['label'])) : '',
            'enabled'        => !empty($_POST['enabled']),
            'schedule_cron'  => isset($_POST['schedule_cron']) ? sanitize_key(wp_unslash((string) $_POST['schedule_cron'])) : '',
            'shard_size'     => isset($_POST['shard_size']) ? (int) $_POST['shard_size'] : 500,
            'rule_operator'  => isset($_POST['rule_operator']) ? sanitize_text_field(wp_unslash((string) $_POST['rule_operator'])) : 'AND',
            'date_from'      => isset($_POST['date_from']) ? sanitize_text_field(wp_unslash((string) $_POST['date_from'])) : '',
            'date_to'        => isset($_POST['date_to'])   ? sanitize_text_field(wp_unslash((string) $_POST['date_to']))   : '',
            'min_subtotal'   => isset($_POST['min_subtotal']) ? (float) $_POST['min_subtotal'] : 0,
            'price_min'      => isset($_POST['price_min']) && $_POST['price_min'] !== '' ? (float) $_POST['price_min'] : null,
            'price_max'      => isset($_POST['price_max']) && $_POST['price_max'] !== '' ? (float) $_POST['price_max'] : null,
            'brand_term_ids'        => isset($_POST['brand_term_ids'])        ? array_map('intval', (array) wp_unslash($_POST['brand_term_ids']))        : array(),
            'category_term_ids'     => isset($_POST['category_term_ids'])     ? array_map('intval', (array) wp_unslash($_POST['category_term_ids']))     : array(),
            'need_term_ids'         => isset($_POST['need_term_ids'])         ? array_map('intval', (array) wp_unslash($_POST['need_term_ids']))         : array(),
            'excluded_brand_ids'    => isset($_POST['excluded_brand_ids'])    ? array_map('intval', (array) wp_unslash($_POST['excluded_brand_ids']))    : array(),
            'excluded_category_ids' => isset($_POST['excluded_category_ids']) ? array_map('intval', (array) wp_unslash($_POST['excluded_category_ids'])) : array(),
            'excluded_need_ids'     => isset($_POST['excluded_need_ids'])     ? array_map('intval', (array) wp_unslash($_POST['excluded_need_ids']))     : array(),
        );

        
        
        
        $data['product_ids']           = AIEO_DMM_Product_Picker::roll_up_to_parents( AIEO_DMM_Product_Picker::collect_ids('product_ids') );
        $data['excluded_product_ids']  = AIEO_DMM_Product_Picker::roll_up_to_parents( AIEO_DMM_Product_Picker::collect_ids('excluded_product_ids') );

        $r = AIEO_Exchanger_Feeds::save($data);
        if (is_wp_error($r)) { wp_send_json_error(array('message' => $r->get_error_message())); }
        wp_send_json_success(array('id' => (int) $r));
    }

    public function ajax_delete_feed() {
        check_ajax_referer('aieo_exch_admin', 'nonce');
        if (!$this->can_manage()) { wp_send_json_error(array('message' => 'forbidden')); }
        AIEO_Exchanger_Feeds::delete(isset($_POST['id']) ? (int) $_POST['id'] : 0);
        wp_send_json_success();
    }

    public function ajax_build_feed() {
        check_ajax_referer('aieo_exch_admin', 'nonce');
        if (!$this->can_manage()) { wp_send_json_error(array('message' => 'forbidden')); }
        $r = AIEO_Exchanger_Feed_Builder::build(isset($_POST['id']) ? (int) $_POST['id'] : 0);
        if (empty($r['ok'])) {
            wp_send_json_error(array('message' => (string) ($r['error'] ?? 'build_failed')));
        }
        wp_send_json_success($r);
    }

    public function ajax_rotate_token() {
        check_ajax_referer('aieo_exch_admin', 'nonce');
        if (!$this->can_manage()) { wp_send_json_error(array('message' => 'forbidden')); }
        $token = AIEO_Exchanger_Feeds::rotate_token(isset($_POST['id']) ? (int) $_POST['id'] : 0);
        wp_send_json_success(array('feed_token' => $token));
    }

    public function ajax_notify_targets() {
        check_ajax_referer('aieo_exch_admin', 'nonce');
        if (!$this->can_manage()) { wp_send_json_error(array('message' => 'forbidden')); }
        $feed = AIEO_Exchanger_Feeds::get(isset($_POST['id']) ? (int) $_POST['id'] : 0);
        if (!$feed) { wp_send_json_error(array('message' => 'feed_not_found')); }
        $r = AIEO_Exchanger_Rest::notify_targets($feed);
        wp_send_json_success($r);
    }

    public function ajax_save_import() {
        check_ajax_referer('aieo_exch_admin', 'nonce');
        if (!$this->can_manage()) { wp_send_json_error(array('message' => 'forbidden')); }
        $data = array(
            'id'            => isset($_POST['id']) ? (int) $_POST['id'] : 0,
            'slug'          => isset($_POST['slug'])  ? sanitize_key(wp_unslash((string) $_POST['slug']))   : '',
            'label'         => isset($_POST['label']) ? sanitize_text_field(wp_unslash((string) $_POST['label'])) : '',
            'enabled'       => !empty($_POST['enabled']),
            'source_url'    => isset($_POST['source_url']) ? esc_url_raw(wp_unslash((string) $_POST['source_url'])) : '',
            'feed_token'    => isset($_POST['feed_token']) ? sanitize_text_field(wp_unslash((string) $_POST['feed_token'])) : '',
            'match_key'     => isset($_POST['match_key']) ? sanitize_key(wp_unslash((string) $_POST['match_key'])) : 'sku',
            'mode'          => isset($_POST['mode']) ? sanitize_key(wp_unslash((string) $_POST['mode'])) : 'create_with_term_meta',
            'schedule_cron' => isset($_POST['schedule_cron']) ? sanitize_key(wp_unslash((string) $_POST['schedule_cron'])) : '',
        );
        $r = AIEO_Exchanger_Imports::save($data);
        if (is_wp_error($r)) { wp_send_json_error(array('message' => $r->get_error_message())); }
        wp_send_json_success(array('id' => (int) $r));
    }

    public function ajax_delete_import() {
        check_ajax_referer('aieo_exch_admin', 'nonce');
        if (!$this->can_manage()) { wp_send_json_error(array('message' => 'forbidden')); }
        AIEO_Exchanger_Imports::delete(isset($_POST['id']) ? (int) $_POST['id'] : 0);
        wp_send_json_success();
    }

    public function ajax_run_import() {
        check_ajax_referer('aieo_exch_admin', 'nonce');
        if (!$this->can_manage()) { wp_send_json_error(array('message' => 'forbidden')); }
        $r = AIEO_Exchanger_Puller::run_full(isset($_POST['id']) ? (int) $_POST['id'] : 0);
        if (empty($r['ok'])) {
            wp_send_json_error(array('message' => (string) ($r['error'] ?? 'run_failed')));
        }
        wp_send_json_success($r);
    }

    private function can_manage() {
        return current_user_can(defined('AIEO_CAPABILITY') ? AIEO_CAPABILITY : 'manage_options');
    }
}
