/**
 * Rank Booster — Core UI
 *
 * Handles: URL input, prepare, table rendering, action toggles,
 * row selection, bulk edit, credits, settings, sub-tabs, focus keywords.
 */
(function($) {
    'use strict';

    // Expose module globally
    window.RankBooster = window.RankBooster || {};

    var state = {
        rows: [],           // array of row objects from prepare
        categories: {},     // check slug → label map
        sessionId: null,
        activeRowIdx: null, // for row settings popup
    };

    var CUSTOM_PROMPT_MAX = 2000;

    RankBooster.state = state;

    /* ════════════════════════════════════════════
       Init on document ready
       ════════════════════════════════════════════ */

    $(document).ready(function() {
        if ($('.rank-booster-section').length === 0) return;

        bindSubTabs();
        bindBack();
        bindPrepare();
        bindSelectAll();
        bindOptimizeButtons();
        bindSettingsModal();
        bindRowSettingsPopup();
        bindBulkEdit();

        // Close banner button
        $('#rb-banner-close').on('click', function() {
            $('#rb-active-banner').hide();
        });

        // Check for active session on load
        checkActiveSession();

        // Load AI credits on page load
        loadCredits();
    });

    /* ════════════════════════════════════════════
       Sub-tab navigation
       ════════════════════════════════════════════ */

    function bindSubTabs() {
        $('.rank-booster-subtab').on('click', function() {
            var tab = $(this).data('subtab');
            $('.rank-booster-subtab').removeClass('active');
            $(this).addClass('active');
            $('.rank-booster-subtab-content').hide();
            $('#rank-booster-' + tab).show();

            if (tab === 'history') {
                loadHistory(1);
            }
        });
    }

    /* ════════════════════════════════════════════
       AI Credits
       ════════════════════════════════════════════ */

    function updateCreditStatus(credits) {
        if (credits && credits.total > 0) {
            $('#rb-credit-status').text('AI Credits left: ' + credits.remaining + ' / ' + credits.total);
        }
    }

    // Expose so processing module can call it after each poll
    RankBooster.updateCreditStatus = updateCreditStatus;

    function loadCredits() {
        $.post(rank_ajax_obj.ajax_url, {
            action: 'rank_booster_get_credits',
            nonce: rank_ajax_obj.nonce,
        }, function(resp) {
            if (resp.success && resp.data && resp.data.credits) {
                updateCreditStatus(resp.data.credits);
            }
        });
    }

    /* ════════════════════════════════════════════
       Check for active session on page load
       ════════════════════════════════════════════ */

    function checkActiveSession() {
        $.ajax({
            url: rank_ajax_obj.ajax_url,
            type: 'POST',
            data: {
                action: 'rank_booster_get_active_session',
                nonce: rank_ajax_obj.nonce
            },
            timeout: 8000,
            success: function(resp) {
                if (!resp.success || !resp.data || !resp.data.has_active) return;
                state.sessionId = resp.data.session_id;
                // Lock UI: hide input, go straight to processing
                $('#rb-url-input-area').hide();
                $('#rb-v8-info').hide();
                $('#rb-table-area').hide();
                $('#rb-processing-area').show();
                RankBoosterProcessing.startPolling(resp.data.session_id);
            }
        });
    }

    /* ════════════════════════════════════════════
       Prepare URLs
       ════════════════════════════════════════════ */

    var MAX_URLS = 100;

    function bindBack() {
        $('#rb-back-btn').on('click', function(e) {
            e.preventDefault();
            state.rows = [];
            $('#rb-urls').val('');
            $('#rb-table-area').hide();
            $('#rb-url-input-area').show();
            $('#rb-v8-info').show();
        });
    }

    function bindPrepare() {
        $('#rb-prepare-btn').on('click', function() {
            var urls = $('#rb-urls').val().trim();
            if (!urls) return;

            // Enforce URL limit
            var urlList = urls.split(/[\n,]+/).map(function(u){ return u.trim(); }).filter(Boolean);
            var unique = [];
            $.each(urlList, function(i, u){ if ($.inArray(u, unique) === -1) unique.push(u); });
            if (unique.length > MAX_URLS) {
                alert('Maximum ' + MAX_URLS + ' URLs per run. You entered ' + unique.length + '.');
                return;
            }

            var $btn = $(this);
            var $spin = $('#rb-prepare-spinner');
            $btn.prop('disabled', true);
            $spin.addClass('is-active');

            $.post(rank_ajax_obj.ajax_url, {
                action: 'rank_booster_prepare_urls',
                nonce: rank_ajax_obj.nonce,
                urls: urls
            }, function(resp) {
                $btn.prop('disabled', false);
                $spin.removeClass('is-active');

                if (!resp.success) {
                    alert(resp.data ? resp.data.message : 'Error preparing URLs');
                    return;
                }

                state.rows = resp.data.results.map(function(r, i) {
                    var isLimited = r.status === 'limited';
                    return $.extend(r, {
                        idx: i,
                        selected: false, // checkbox is only for bulk edit, not for optimize queue
                        mode: isLimited ? 'manual' : 'automatic',
                        selectedChecks: [],
                        allowedChecks: r.allowed_checks || null,
                        focusKeywords: [],
                        focusKeywordsLoaded: false,
                        originalStatusText: r.status_text,
                        updatePublishDate: false,
                        customPrompt: '',
                        customPromptErrorShown: false,
                    });
                });
                state.categories = resp.data.categories || {};

                renderSeoPluginNotice(resp.data.seo_plugin);

                renderTable();
                $('#rb-url-input-area').hide();
                $('#rb-v8-info').hide();
                $('#rb-table-area').show();
                updateOptimizeButton();

                // Auto-fetch focus keywords for all rows in one bulk call
                fetchBulkFocusKeywords();
            });
        });
    }

    /* ════════════════════════════════════════════
       SEO plugin notice
       ════════════════════════════════════════════ */

    function renderSeoPluginNotice(info) {
        var $notice = $('#rb-seo-plugin-notice');
        if (info && info.supported === false && info.message) {
            $notice.html('⚠️ ' + info.message).show();
        } else {
            $notice.hide().empty();
        }
    }

    /* ════════════════════════════════════════════
       Table rendering
       ════════════════════════════════════════════ */

    function renderTable() {
        var $tbody = $('#rb-tbody').empty();
        var cats = state.categories;

        state.rows.forEach(function(row) {
            var $tr = $('<tr>').attr('data-idx', row.idx);

            // Checkbox — only for bulk edit, not for optimize queue
            var canSelect = row.status === 'ready' || row.status === 'limited';
            var $cb = $('<input type="checkbox">').prop('checked', row.selected).prop('disabled', !canSelect);
            $cb.on('change', function() {
                row.selected = this.checked;
                updateBulkBar();
            });
            $tr.append($('<td class="check-column">').append($cb));

            // URL
            $tr.append($('<td>').text(row.url));

            // Status
            var $status = $('<td>').addClass('rb-status-' + row.status);
            $status.text(row.status_text);
            if (row.focusKeywordsLoaded && (row.status === 'ready' || row.status === 'limited')) {
                var $kw;
                if (row.focusKeywords.length) {
                    $kw = $('<span class="rb-kw-count">').text(row.focusKeywords.length + ' keyword' + (row.focusKeywords.length > 1 ? 's' : ''));
                } else {
                    $kw = $('<span class="rb-kw-count">').text('Add focus keywords');
                }
                (function(r){ $kw.on('click', function(e){ e.stopPropagation(); openRowSettings(r); }); })(row);
                $status.append(' · ').append($kw);
            }
            $tr.append($status);

            // Action
            var $action = $('<td>');
            if (row.status === 'ready' || row.status === 'limited') {
                $action.append(buildActionCell(row, cats));
            }
            $tr.append($action);

            $tbody.append($tr);
        });
    }

    /* ════════════════════════════════════════════
       Bulk fetch focus keywords (single API call)
       ════════════════════════════════════════════ */

    function fetchBulkFocusKeywords() {
        // Collect URLs of rows that need keywords
        var targetRows = state.rows.filter(function(r) {
            return r.status === 'ready' || r.status === 'limited';
        });
        if (!targetRows.length) return;

        var urls = targetRows.map(function(r) { return r.url; });

        // Show spinner in status column for all target rows
        targetRows.forEach(function(r) {
            var $tr = $('#rb-tbody tr[data-idx="' + r.idx + '"]');
            $tr.find('td').eq(2)
                .html('<span class="rb-kw-loading"><span class="spinner is-active" style="float:none;margin:0 4px 0 0;"></span>Finding tracked keywords…</span>');
        });

        // Disable optimize button during keyword fetch
        $('.rb-optimize-btn').prop('disabled', true);

        $.post(rank_ajax_obj.ajax_url, {
            action: 'rank_booster_get_bulk_focus_keywords',
            nonce: rank_ajax_obj.nonce,
            urls: JSON.stringify(urls),
        }, function(resp) {
            var map = (resp.success && resp.data && resp.data.keywords_map) ? resp.data.keywords_map : {};
            targetRows.forEach(function(r) {
                var kws = map[r.url] || [];
                r.focusKeywords = kws.map(function(k) { return k.kw; }).slice(0, 3);
                r.focusKeywordsLoaded = true;
            });
            renderTable();
            updateOptimizeButton();
        }).fail(function() {
            targetRows.forEach(function(r) { r.focusKeywordsLoaded = true; });
            renderTable();
            updateOptimizeButton();
        });
    }

    function buildActionCell(row, cats) {
        var $cell = $('<div class="rb-action-cell">');
        var $main = $('<div class="rb-action-main">');
        var isLimited = row.status === 'limited';

        // Toggle group: Automatic / Choose Fixes
        var $group = $('<div class="rb-toggle-group">');

        if (isLimited) {
            // Limited rows: show disabled Automatic button + active manual
            var $autoBtn = $('<button class="rb-toggle-btn" disabled>Automatic</button>');
            $autoBtn.css({ opacity: 0.4, cursor: 'not-allowed' });
            var initText = row.selectedChecks.length > 0 ? 'Fixing: ' + row.selectedChecks.length : 'Choose fixes';
            var $manualBtn = $('<button class="rb-toggle-btn rb-manual-btn active">' + initText + '</button>');
            $manualBtn.attr('data-row-idx', row.idx);
            $manualBtn.on('click', function() {
                toggleDropdown(row, $manualBtn, cats);
            });
            $group.append($autoBtn, $manualBtn);
        } else {
            var $autoBtn = $('<button class="rb-toggle-btn' + (row.mode === 'automatic' ? ' active' : '') + '">Automatic</button>');
            var initText = row.mode === 'manual' && row.selectedChecks.length > 0 ? 'Fixing: ' + row.selectedChecks.length : 'Choose fixes';
            var $manualBtn = $('<button class="rb-toggle-btn rb-manual-btn' + (row.mode === 'manual' ? ' active' : '') + '">' + initText + '</button>');
            $manualBtn.attr('data-row-idx', row.idx);

            $autoBtn.on('click', function() {
                row.mode = 'automatic';
                row.selectedChecks = [];
                $autoBtn.addClass('active');
                $manualBtn.removeClass('active').text('Choose fixes');
                $cell.find('.rb-choose-fixes-dropdown').remove();
                refreshCustomPromptRow(row);
                updateOptimizeButton();
            });

            $manualBtn.on('click', function() {
                if (row.mode === 'manual') {
                    toggleDropdown(row, $manualBtn, cats);
                } else {
                    row.mode = 'manual';
                    $manualBtn.addClass('active');
                    $autoBtn.removeClass('active');
                    toggleDropdown(row, $manualBtn, cats);
                    updateOptimizeButton();
                }
            });

            $group.append($autoBtn, $manualBtn);
        }

        $main.append($group);

        // Settings button
        var $settingsBtn = $('<button class="rb-settings-btn" title="Page settings">⚙️</button>');
        $settingsBtn.on('click', function(e) {
            e.stopPropagation();
            openRowSettings(row);
        });
        $main.append($settingsBtn);

        // Remove row button
        var $removeBtn = $('<button class="rb-settings-btn rb-remove-row-btn" title="Remove URL">✕</button>');
        $removeBtn.css({ color: '#d63638' });
        (function(r) {
            $removeBtn.on('click', function(e) {
                e.stopPropagation();
                removeRow(r.idx);
            });
        })(row);
        $main.append($removeBtn);

        $cell.append($main);

        if (hasCustomPromptSelected(row)) {
            var $linkRow = buildCustomPromptLink(row);
            if ($linkRow) {
                $cell.append($linkRow);
            }
        }

        return $cell;
    }

    function hasCustomPromptSelected(row) {
        return row.selectedChecks.indexOf('custom_prompt') !== -1;
    }

    function buildCustomPromptLink(row) {
        var hasPrompt = (row.customPrompt || '').trim().length > 0;
        var validationError = getCustomPromptValidationError(row);
        var showError = row.customPromptErrorShown && validationError;

        if (hasPrompt && !showError) {
            return null;
        }

        var $wrap = $('<div class="rb-custom-prompt-row">');

        if (!hasPrompt) {
            var $link = $('<a href="#" class="rb-add-custom-prompt">Add custom prompt</a>');
            $link.on('click', function(e) {
                e.preventDefault();
                e.stopPropagation();
                openRowSettings(row, true);
            });
            $wrap.append($link);
        }

        if (showError) {
            $wrap.append($('<span class="rb-custom-prompt-error">').text(validationError));
        }

        return $wrap;
    }

    function getCustomPromptValidationError(row) {
        if (!hasCustomPromptSelected(row)) return '';
        var prompt = (row.customPrompt || '').trim();
        if (!prompt) return 'Custom instructions required';
        if (prompt.length > CUSTOM_PROMPT_MAX) return 'Must be 2000 characters or fewer';
        return '';
    }

    function refreshCustomPromptRow(row) {
        var $tr = $('#rb-tbody tr[data-idx="' + row.idx + '"]');
        var $cell = $tr.find('.rb-action-cell');
        $cell.find('.rb-custom-prompt-row').remove();
        if (!hasCustomPromptSelected(row)) return;
        var $linkRow = buildCustomPromptLink(row);
        if ($linkRow) {
            $cell.append($linkRow);
        }
    }

    function toggleDropdown(row, $anchor, cats) {
        // Close any existing
        $('.rb-choose-fixes-dropdown').remove();

        var $dd = $('<div class="rb-dropdown rb-choose-fixes-dropdown">');
        var allowed = row.allowedChecks;
        var rowIdx = row.idx;

        Object.keys(cats).forEach(function(slug) {
            // If this row has restricted allowed checks, skip slugs not in the list
            if (allowed && allowed.indexOf(slug) === -1) return;

            var checked = row.selectedChecks.indexOf(slug) !== -1;
            var $label = $('<label class="rb-dropdown-item">');
            var $cb = $('<input type="checkbox">').val(slug).prop('checked', checked);
            $cb.on('change', function() {
                if (this.checked) {
                    if (row.selectedChecks.indexOf(slug) === -1) row.selectedChecks.push(slug);
                } else {
                    row.selectedChecks = row.selectedChecks.filter(function(s) { return s !== slug; });
                    if (slug === 'custom_prompt') {
                        row.customPromptErrorShown = false;
                    }
                }
                // Update button label — find by data attribute for robustness
                var count = row.selectedChecks.length;
                var label = count > 0 ? 'Fixing: ' + count : 'Choose fixes';
                $('.rb-manual-btn[data-row-idx="' + rowIdx + '"]').text(label);
                refreshCustomPromptRow(row);
                updateOptimizeButton();
            });
            $label.append($cb, $('<span class="rb-dropdown-label">').text(cats[slug] + ' (2 credits)'));
            $dd.append($label);
        });

        // Append inside the action main row so positioning stays below the toggle
        var $cell = $anchor.closest('.rb-action-main, .rb-action-cell');
        if (!$cell.hasClass('rb-action-main')) {
            $cell = $cell.find('.rb-action-main');
        }
        $cell.css('position', 'relative');
        $dd.css({ position: 'absolute', top: '100%', right: 0, left: 'auto', zIndex: 100 });
        $cell.append($dd);

        // Close on outside click
        setTimeout(function() {
            $(document).one('click', function() { $dd.remove(); });
        }, 10);
        $dd.on('click', function(e) { e.stopPropagation(); });
    }

    /* ════════════════════════════════════════════
       Row selection
       ════════════════════════════════════════════ */

    function bindSelectAll() {
        $('#rb-select-all').on('change', function() {
            var checked = this.checked;
            state.rows.forEach(function(r) {
                if (r.status === 'ready' || r.status === 'limited') r.selected = checked;
            });
            renderTable();
            updateBulkBar();
        });
    }

    // Checked rows — for bulk edit only
    function getSelectedRows() {
        return state.rows.filter(function(r) { return r.selected && (r.status === 'ready' || r.status === 'limited'); });
    }

    // All optimizable rows — always included in optimization regardless of checkbox
    function getOptimizableRows() {
        return state.rows.filter(function(r) { return r.status === 'ready' || r.status === 'limited'; });
    }

    function updateBulkBar() {
        var sel = getSelectedRows();
        if (sel.length >= 1) {
            $('#rb-bulk-bar').show();
            $('#rb-selected-count').text(sel.length + ' selected');
        } else {
            $('#rb-bulk-bar').hide();
        }
    }

    /* ════════════════════════════════════════════
       Bulk edit
       ════════════════════════════════════════════ */

    function bindBulkEdit() {
        $('#rb-bulk-edit-btn').on('click', function(e) {
            e.stopPropagation();
            $('#rb-bulk-dropdown').toggle();
        });

        $(document).on('click', function() { $('#rb-bulk-dropdown').hide(); });
        $('#rb-bulk-dropdown').on('click', function(e) { e.stopPropagation(); });

        $('#rb-bulk-apply').on('click', function() {
            var selected = getSelectedRows();
            var isAuto = $('input[name="rb-bulk-mode"]:checked').val() === 'automatic';
            var bulkUpdatePublishDate = $('input[name="rb-bulk-update-publish-date"]').is(':checked');

            if (isAuto) {
                selected.forEach(function(r) {
                    r.mode = 'automatic';
                    r.selectedChecks = [];
                });
            } else {
                var checks = [];
                $('input[name="rb-bulk-check"]:checked').each(function() {
                    checks.push($(this).val());
                });
                selected.forEach(function(r) {
                    r.mode = 'manual';
                    r.selectedChecks = checks.slice();
                });
            }

            // Apply publish date setting to all selected rows
            selected.forEach(function(r) {
                r.updatePublishDate = bulkUpdatePublishDate;
            });

            $('#rb-bulk-dropdown').hide();
            renderTable();
            updateOptimizeButton();
        });

        // Bulk remove selected rows
        $('#rb-bulk-remove').on('click', function() {
            removeSelectedRows();
            $('#rb-bulk-dropdown').hide();
        });

        // Toggle between automatic radio and manual checkboxes
        $('input[name="rb-bulk-mode"]').on('change', function() {
            if ($(this).val() === 'automatic') {
                $('input[name="rb-bulk-check"]').prop('checked', false);
            }
        });
        $(document).on('change', 'input[name="rb-bulk-check"]', function() {
            if ($(this).is(':checked')) {
                $('input[name="rb-bulk-mode"]').prop('checked', false);
            }
        });
    }

    function removeSelectedRows() {
        state.rows = state.rows.filter(function(r) { return !r.selected; });
        // Re-index
        state.rows.forEach(function(r, i) { r.idx = i; });
        renderTable();
        updateBulkBar();
        updateOptimizeButton();
    }

    function removeRow(idx) {
        state.rows.splice(idx, 1);
        // Re-index
        state.rows.forEach(function(r, i) { r.idx = i; });
        renderTable();
        updateBulkBar();
        updateOptimizeButton();
    }

    /* ════════════════════════════════════════════
       Optimize button + credits
       ════════════════════════════════════════════ */

    function bindOptimizeButtons() {
        $('.rb-optimize-btn').on('click', function() {
            startOptimization();
        });
    }

    function updateOptimizeButton() {
        var rows = getOptimizableRows();
        var count = rows.length;
        var credits = 0;

        rows.forEach(function(r) {
            if (r.mode === 'automatic') {
                credits += 10;
            } else {
                credits += (r.selectedChecks.length || 0) * 2;
            }
        });

        var label = 'Optimize ' + count + ' page' + (count !== 1 ? 's' : '');
        var creditLabel = 'Total: ' + credits + ' credits';

        $('.rb-optimize-btn').text(label).prop('disabled', count === 0);
        $('.rb-total-credits').text(creditLabel);
    }

    /* ════════════════════════════════════════════
       Start optimization
       ════════════════════════════════════════════ */

    function startOptimization() {
        var optimizable = getOptimizableRows();
        if (optimizable.length === 0) return;

        // Validate manual rows have at least 1 check
        for (var i = 0; i < optimizable.length; i++) {
            if (optimizable[i].mode === 'manual' && optimizable[i].selectedChecks.length === 0) {
                alert('Please choose at least one fix for: ' + optimizable[i].url);
                return;
            }
            var promptError = getCustomPromptValidationError(optimizable[i]);
            if (promptError) {
                optimizable[i].customPromptErrorShown = true;
                refreshCustomPromptRow(optimizable[i]);
                alert(promptError + ' for: ' + optimizable[i].url);
                openRowSettings(optimizable[i], true);
                return;
            }
        }

        var rows = optimizable.map(function(r) {
            return {
                post_id: r.post_id,
                object_type: r.object_type || 'post',
                url: r.url,
                editor_type: r.editor_type,
                mode: r.mode,
                selected_checks: r.selectedChecks,
                focus_keywords: r.focusKeywords,
                update_publish_date: r.updatePublishDate ? 1 : 0,
                custom_prompt: hasCustomPromptSelected(r) ? (r.customPrompt || '').trim() : '',
            };
        });

        $('.rb-optimize-btn').prop('disabled', true).text('Starting…');

        $.post(rank_ajax_obj.ajax_url, {
            action: 'rank_booster_start_optimization',
            nonce: rank_ajax_obj.nonce,
            rows: JSON.stringify(rows),
        }, function(resp) {
            if (!resp.success) {
                // If rejected due to active session, jump to its processing view
                if (resp.data && resp.data.session_id) {
                    state.sessionId = resp.data.session_id;
                    $('#rb-table-area').hide();
                    $('#rb-processing-area').show();
                    RankBoosterProcessing.startPolling(resp.data.session_id);
                    return;
                }
                alert(resp.data ? resp.data.message : 'Error starting optimization');
                $('.rb-optimize-btn').prop('disabled', false);
                updateOptimizeButton();
                return;
            }

            state.sessionId = resp.data.session_id;

            // Lock table and show processing
            $('#rb-table-area').hide();
            $('#rb-processing-area').show();

            // Delegate to processing module
            RankBoosterProcessing.startPolling(resp.data.session_id);
        });
    }

    /* ════════════════════════════════════════════
       Settings modal
       ════════════════════════════════════════════ */

    function bindSettingsModal() {
        $(document).on('click', '.rb-modal-close', function() {
            $(this).closest('.rb-modal').hide();
        });

        // Close modal on overlay click
        $('.rb-modal').on('click', function(e) {
            if (e.target === this) $(this).hide();
        });
    }

    /* ════════════════════════════════════════════
       Row settings modal (focus keywords)
       ════════════════════════════════════════════ */

    function bindRowSettingsPopup() {
        // Add keyword on enter
        $('#rb-row-keyword-input').on('keydown', function(e) {
            if (e.key !== 'Enter') return;
            e.preventDefault();
            addKeywordToRow($(this).val().trim());
            $(this).val('');
        });

        // Add keyword on button click
        $('#rb-row-keyword-add').on('click', function() {
            var $input = $('#rb-row-keyword-input');
            addKeywordToRow($input.val().trim());
            $input.val('').focus();
        });

        $('#rb-row-custom-prompt').on('input', function() {
            if (state.activeRowIdx === null) return;
            var row = state.rows[state.activeRowIdx];
            row.customPrompt = $(this).val();
            if (!getCustomPromptValidationError(row)) {
                row.customPromptErrorShown = false;
            }
            updateCustomPromptCounter();
            updateCustomPromptModalError(row);
            refreshCustomPromptRow(row);
        });
    }

    function updateCustomPromptCounter() {
        var len = $('#rb-row-custom-prompt').val().length;
        $('#rb-row-custom-prompt-count').text(len + ' / ' + CUSTOM_PROMPT_MAX);
    }

    function updateCustomPromptModalError(row) {
        var $error = $('#rb-row-custom-prompt-error');
        if (!row.customPromptErrorShown) {
            $error.hide().text('');
            return;
        }
        var error = getCustomPromptValidationError(row);
        if (error) {
            $error.text(error).show();
        } else {
            $error.hide().text('');
        }
    }

    function openRowSettings(row, focusCustomPrompt) {
        state.activeRowIdx = row.idx;

        var $modal = $('#rb-row-settings');
        $modal.show();

        // Set update publish date checkbox
        $('#rb-row-update-publish-date').prop('checked', row.updatePublishDate);
        $('#rb-row-update-publish-date').off('change').on('change', function() {
            row.updatePublishDate = this.checked;
        });

        // Custom instructions section — only when Custom Prompt check is selected
        if (hasCustomPromptSelected(row)) {
            $('#rb-row-custom-prompt-section').show();
            $('#rb-row-custom-prompt').val(row.customPrompt || '');
            updateCustomPromptCounter();
            updateCustomPromptModalError(row);
            if (focusCustomPrompt) {
                setTimeout(function() {
                    $('#rb-row-custom-prompt').focus();
                }, 50);
            }
        } else {
            $('#rb-row-custom-prompt-section').hide();
            $('#rb-row-custom-prompt-error').hide().text('');
        }

        // Render existing keywords (already loaded by bulk fetch)
        renderKeywordTags(row);

        // Show loading hint only if bulk fetch is still in progress
        if (!row.focusKeywordsLoaded && (row.status === 'ready' || row.status === 'limited')) {
            $('#rb-row-keywords-api').show().html('<small>Loading keywords from Morningscore…</small>');
        } else {
            $('#rb-row-keywords-api').hide();
        }
    }

    function renderKeywordTags(row) {
        var $list = $('#rb-row-keywords-list').empty();

        row.focusKeywords.forEach(function(kw, i) {
            var $tag = $('<span class="rb-keyword-tag">');
            $tag.text(kw);
            var $remove = $('<button class="rb-keyword-remove">&times;</button>');
            $remove.on('click', function() {
                row.focusKeywords.splice(i, 1);
                renderKeywordTags(row);
            });
            $tag.append($remove);
            $list.append($tag);
        });

        // Disable input and add button if at max
        var atMax = row.focusKeywords.length >= 3;
        $('#rb-row-keyword-input').prop('disabled', atMax);
        $('#rb-row-keyword-add').prop('disabled', atMax);

        // Update keyword count in the table row
        var $kw = $('#rb-tbody tr[data-idx="' + row.idx + '"]').find('.rb-kw-count');
        if ($kw.length) {
            if (row.focusKeywords.length) {
                $kw.text(row.focusKeywords.length + ' keyword' + (row.focusKeywords.length > 1 ? 's' : ''));
            } else {
                $kw.text('Add focus keywords');
            }
        }
    }

    function addKeywordToRow(kw) {
        if (!kw || state.activeRowIdx === null) return;
        var row = state.rows[state.activeRowIdx];
        if (row.focusKeywords.length >= 3) return;
        if (row.focusKeywords.indexOf(kw) !== -1) return;

        row.focusKeywords.push(kw);
        renderKeywordTags(row);
    }

    /* ════════════════════════════════════════════
       Summary modal
       ════════════════════════════════════════════ */

    function renderSummaryBody(summaryHtml, customPrompt) {
        var $body = $('#rb-summary-body').empty();
        $body.html(summaryHtml || '<p>No summary available.</p>');

        var prompt = (customPrompt || '').trim();
        if (!prompt) return;

        var $box = $('<div class="rb-summary-custom-prompt">');
        $box.append($('<div class="rb-summary-custom-prompt-label">').text('Your instructions:'));
        $box.append($('<div class="rb-summary-custom-prompt-text">').text(prompt));
        $body.append($box);
    }

    RankBooster.renderSummaryBody = renderSummaryBody;

    /* ════════════════════════════════════════════
       History sub-tab
       ════════════════════════════════════════════ */

    var historyPage = 1;

    function loadHistory(page) {
        historyPage = page;
        $('#rb-history-loading').show();
        $('#rb-history-table, #rb-history-empty, #rb-history-pagination').hide();

        $.post(rank_ajax_obj.ajax_url, {
            action: 'rank_booster_get_optimized_pages',
            nonce: rank_ajax_obj.nonce,
            page: page,
            per_page: 20,
        }, function(resp) {
            $('#rb-history-loading').hide();
            if (!resp.success) return;

            var d = resp.data;
            if (!d.rows.length) {
                $('#rb-history-empty').show();
                return;
            }

            var $tbody = $('#rb-history-tbody').empty();
            d.rows.forEach(function(job) {
                var $tr = $('<tr>');
                $tr.append($('<td>').html('<a href="' + job.url + '" target="_blank">' + job.url + '</a>'));
                $tr.append($('<td>').text(job.updated_at));
                $tr.append($('<td>').text(job.mode));
                $tr.append($('<td>').text(
                    job.selected_checks.length ? job.selected_checks.length + ' checks' : 'Automatic'
                ));

                var statusText = job.status === 'pushed_live' ? 'Live' : (job.has_draft ? 'Draft ready' : job.status);
                $tr.append($('<td>').text(statusText));

                var $actions = $('<td class="rb-action-btns">');
                if (job.summary_html) {
                    var $sumBtn = $('<button class="button button-small">Summary</button>');
                    $sumBtn.on('click', function() {
                        renderSummaryBody(job.summary_html, job.custom_prompt);
                        $('#rb-summary-modal').show();
                    });
                    $actions.append($sumBtn);
                }
                if (job.has_draft && job.draft_content) {
                    var $contentBtn = $('<button class="button button-small">Content</button>');
                    $contentBtn.on('click', function() {
                        $('#rb-content-rendered').html(job.draft_content);
                        $('#rb-content-html').val(job.draft_content);
                        $('#rb-content-copy').text('Copy HTML');
                        $('#rb-content-modal').show();
                    });
                    $actions.append($contentBtn);
                }
                if (job.status === 'completed' && job.has_draft) {
                    if (job.object_type !== 'term') {
                        var $prevBtn = $('<button class="button button-small">Preview</button>');
                        $prevBtn.on('click', function() { previewJob(job.id); });
                        $actions.append($prevBtn);

                        // Edit Draft is unreliable for builders that load their
                        // tree outside post meta (Breakdance) or render from
                        // custom fields. Those use Preview + Push Live instead.
                        var noEditDraft = ['breakdance', 'customfields'];
                        if (noEditDraft.indexOf(job.editor_type) === -1) {
                            var $editBtn = $('<button class="button button-small" title="Opens the WP editor with AI draft loaded. Nothing is saved until you click Update.">Edit Draft</button>');
                            $editBtn.on('click', function() { editDraft(job.id, $editBtn, job.post_id, job.editor_type); });
                            $actions.append($editBtn);
                        }
                    }

                    var $pushBtn = $('<button class="button button-small button-primary">Push Live</button>');
                    $pushBtn.on('click', function() { pushLiveJob(job.id, $pushBtn, $tr); });
                    $actions.append($pushBtn);
                }
                if (job.status === 'pushed_live') {
                    $actions.append($('<a class="rb-live-link" href="' + job.url + '" target="_blank">View live →</a>'));
                }
                $tr.append($actions);
                $tbody.append($tr);
            });

            $('#rb-history-table').show();
            $('#rb-history-csv-wrap').show();
            if (d.total !== undefined) {
                $('#rb-history-description').text(d.total + ' pages that have been processed by Page Booster.');
            }

            // Pagination
            if (d.total_pages > 1) {
                $('#rb-history-page-info').text('Page ' + d.page + ' of ' + d.total_pages);
                $('#rb-history-prev').prop('disabled', d.page <= 1);
                $('#rb-history-next').prop('disabled', d.page >= d.total_pages);
                $('#rb-history-pagination').show();
            }
        });

        $('#rb-history-prev').off('click').on('click', function() { loadHistory(historyPage - 1); });
        $('#rb-history-next').off('click').on('click', function() { loadHistory(historyPage + 1); });
    }

    // CSV export
    $('#rb-history-csv-btn').on('click', function() {
        var $btn = $(this);
        $btn.prop('disabled', true).text('Exporting…');
        $.post(rank_ajax_obj.ajax_url, {
            action: 'rank_booster_export_csv',
            nonce: rank_ajax_obj.nonce,
        }, function(resp) {
            $btn.prop('disabled', false).html('<span class="dashicons dashicons-download" style="font-size:14px;width:14px;height:14px;line-height:1.5;"></span> CSV Export');
            if (!resp.success || !resp.data.rows.length) return;

            var rows = resp.data.rows;
            var header = ['URL', 'Optimized', 'Mode', 'Checks', 'Status', 'Created'];
            var lines = [header.join(',')];
            rows.forEach(function(r) {
                lines.push([
                    '"' + (r.url || '').replace(/"/g, '""') + '"',
                    '"' + (r.optimized || '') + '"',
                    '"' + (r.mode || '') + '"',
                    '"' + (r.checks || '').replace(/"/g, '""') + '"',
                    '"' + (r.status || '') + '"',
                    '"' + (r.created_at || '') + '"',
                ].join(','));
            });

            var blob = new Blob([lines.join('\n')], { type: 'text/csv;charset=utf-8;' });
            var link = document.createElement('a');
            link.href = URL.createObjectURL(blob);
            link.download = 'rank-booster-optimized-pages.csv';
            link.click();
        });
    });

    // Expose for processing module
    RankBooster.loadHistory = loadHistory;

    /* ════════════════════════════════════════════
       Preview / Push live helpers (shared)
       ════════════════════════════════════════════ */

    function previewJob(jobId) {
        $.post(rank_ajax_obj.ajax_url, {
            action: 'rank_booster_get_preview_url',
            nonce: rank_ajax_obj.nonce,
            job_id: jobId,
        }, function(resp) {
            if (resp.success) {
                window.open(resp.data.preview_url, '_blank');
            } else {
                alert(resp.data ? resp.data.message : 'Error generating preview');
            }
        });
    }

    function pushLiveJob(jobId, $btn, $tr) {
        $btn.prop('disabled', true).text('Pushing…');

        $.post(rank_ajax_obj.ajax_url, {
            action: 'rank_booster_push_live',
            nonce: rank_ajax_obj.nonce,
            job_id: jobId,
        }, function(resp) {
            if (resp.success) {
                // Remove all draft-related buttons, keep only Summary + Live link
                $tr.find('.button:contains("Preview")').remove();
                $tr.find('.button:contains("Edit Draft")').remove();
                $btn.replaceWith($('<a class="rb-live-link" href="' + resp.data.post_url + '" target="_blank">Live →</a>'));
                // Update status column
                $tr.find('td').eq(3).text('Live').css('color', '#00a32a');
            } else {
                $btn.prop('disabled', false).text('Push Live');
                alert(resp.data ? resp.data.message : 'Error pushing live');
            }
        });
    }

    function editDraft(jobId, $btn, postId, editorType) {
        // Elementor & Divi: need server-side processing before opening the editor.
        // Elementor: backup + store modified _elementor_data for editor filter.
        // Divi: store draft content in meta for VB the_post hook to inject.
        if (editorType === 'elementor' || editorType === 'divi' || editorType === 'wpbakery') {
            $btn.prop('disabled', true).text('Applying…');
            $.post(rank_ajax_obj.ajax_url, {
                action: 'rank_booster_edit_draft',
                nonce: rank_ajax_obj.nonce,
                job_id: jobId
            }, function(res) {
                $btn.prop('disabled', false).text('Edit Draft');
                if (res.success && res.data.edit_url) {
                    console.log('[Rank Booster] edit_draft response:', res.data);
                    window.open(res.data.edit_url, '_blank');
                } else {
                    console.error('[Rank Booster] edit_draft error:', res);
                    alert('Error: ' + (res.data && res.data.message ? res.data.message : 'Unknown error'));
                }
            }).fail(function() {
                $btn.prop('disabled', false).text('Edit Draft');
                alert('AJAX request failed.');
            });
            return;
        }

        // Classic / Gutenberg: build the edit URL client-side.
        // The enqueue_editor_inject() PHP hook detects rank_booster_inject param
        // and injects AI content into the editor state via editPost().
        var adminUrl = rank_ajax_obj.ajax_url.replace('/admin-ajax.php', '/post.php');
        var editUrl = adminUrl + '?post=' + postId + '&action=edit&rank_booster_inject=' + jobId;
        window.open(editUrl, '_blank');
    }

    // Expose helpers for processing module
    RankBooster.previewJob = previewJob;
    RankBooster.pushLiveJob = pushLiveJob;
    RankBooster.editDraft = editDraft;

})(jQuery);
