/* Pipeline Buster v1.2.6 — Admin JS */
/* global jQuery, PB */

(function ($) {
    'use strict';

    var state = {
        attachmentIds      : [],
        imageSizesMB       : {},           // { attachmentId: sizeMB } — cumulative size tracking
        attachmentUrls     : {},           // { attachmentId: thumbnailUrl }
        heroIndex          : 0,
        generated          : {},
        jobId              : null,
        pollTimer          : null,
        depth              : 'standard',
        tone               : 'professional',
        template           : 'none',
        inputMode          : 'standard',   // 'standard' | 'guide'
        existingProductId  : null,
        existingProductName: '',
        toneReferenceId    : null,
        toneReferenceName  : '',
        uiMode             : PIPEBU.ui_mode || 'simple',
        hasColors          : false,
        colors             : [],           // [{ attachmentId, name, price }]
        outputLanguage     : ''
    };

    // -------------------------------------------------------------------------
    // Init
    // -------------------------------------------------------------------------

    $(function () {
        bindUpload();
        bindPills();
        bindTemplates();
        bindInputMode();
        bindProductSearch();
        bindToneReference();
        bindColorCheckbox();
        bindLanguage();
        bindGenerate();
        bindReview();
        bindModeToggle();
    });

    // -------------------------------------------------------------------------
    // Input Mode toggle (Standard vs Guide Mode)
    // -------------------------------------------------------------------------

    function bindInputMode() {
        $('.pb-input-tab').on('click', function () {
            var mode = $(this).data('input-mode');
            if (mode === state.inputMode) return;

            $('.pb-input-tab').removeClass('active');
            $(this).addClass('active');
            state.inputMode = mode;

            if (mode === 'guide') {
                $('#pb-guide-product-wrap').slideDown(200);
                $('#pb-upload-heading').text('Upload Manual Pages or Photos');
                $('#pb-upload-hint').text('Upload photos of the product manual, instruction sheet, or packaging. AI will read them and write a How To guide.');
                $('#pb-dropzone-label').text('Drag & drop manual images here');
                $('#pb-hero-hint').hide();
                $('#pb-generate-btn').text('⚡ Analyze & Generate How To');
                $('#pb-colors-wrap').hide();
                // Color checkbox not applicable in guide mode — force off.
                if (state.hasColors) {
                    state.hasColors = false;
                    $('#pb-has-colors').prop('checked', false);
                    $('#pb-upload-hint').text('Upload photos of the product manual, instruction sheet, or packaging. AI will read them and write a How To guide.');
                }
            } else {
                $('#pb-guide-product-wrap').slideUp(200);
                $('#pb-upload-heading').text('Upload Product Images');
                $('#pb-upload-hint').text( state.hasColors
                    ? 'Upload one image per color. Max ' + PIPEBU.max_images + ' images, ' + PIPEBU.max_mb + 'MB total.'
                    : 'Include product photos, packaging, and manual pages. Max ' + PIPEBU.max_images + ' images, ' + PIPEBU.max_mb + 'MB total.' );
                $('#pb-dropzone-label').text('Drag & drop images here');
                $('#pb-hero-hint').show();
                $('#pb-generate-btn').text('⚡ Analyze & Generate Content');
                $('#pb-colors-wrap').show();
                clearProductSelection();
            }
        });
    }

    // -------------------------------------------------------------------------
    // Product search (Guide Mode)
    // -------------------------------------------------------------------------

    function bindProductSearch() {
        var searchTimer = null;

        $('#pb-product-search').on('input', function () {
            clearTimeout(searchTimer);
            var q = $(this).val().trim();
            if (q.length < 2) {
                $('#pb-product-results').hide().empty();
                return;
            }
            searchTimer = setTimeout(function () {
                $.post(PIPEBU.ajaxurl, {
                    action: 'pipebu_search_products',
                    nonce  : PIPEBU.nonce,
                    q      : q
                })
                .done(function (res) {
                    if (!res.success || !res.data.length) {
                        $('#pb-product-results').hide().empty();
                        return;
                    }
                    var html = '';
                    $.each(res.data, function (i, p) {
                        html += '<div class="pb-product-result-item" data-id="' + p.id + '" data-name="' + esc(p.name) + '">' + esc(p.name) + '</div>';
                    });
                    $('#pb-product-results').html(html).show();
                });
            }, 300);
        });

        // Select a result.
        $(document).on('click', '#pb-product-results .pb-product-result-item', function () {
            state.existingProductId   = $(this).data('id');
            state.existingProductName = $(this).data('name');
            $('#pb-product-search').val('').hide();
            $('#pb-product-results').hide().empty();
            $('#pb-product-selected-name').text(state.existingProductName);
            $('#pb-product-selected').show();
            $('#pb-guide-hint').text('How To post will be linked to: ' + state.existingProductName);
        });

        // Clear selection.
        $('#pb-product-clear').on('click', function () {
            clearProductSelection();
        });

        // Hide results on outside click.
        $(document).on('click', function (e) {
            if (!$(e.target).closest('#pb-product-results').length && !$(e.target).is('#pb-product-search')) {
                $('#pb-product-results').hide();
            }
        });
    }

    function clearProductSelection() {
        state.existingProductId   = null;
        state.existingProductName = '';
        $('#pb-product-selected').hide();
        $('#pb-product-selected-name').text('');
        $('#pb-product-search').val('').show();
        $('#pb-guide-hint').text('If linked, the How To post will be automatically connected to this product.');
    }

    // -------------------------------------------------------------------------
    // Tone Reference Selector
    // -------------------------------------------------------------------------

    function bindToneReference() {
        var refTimer = null;

        $('#pb-tone-ref-search').on('input', function () {
            clearTimeout(refTimer);
            var q = $(this).val().trim();
            if (q.length < 2) {
                $('#pb-tone-ref-results').hide().empty();
                return;
            }
            refTimer = setTimeout(function () {
                $.post(PIPEBU.ajaxurl, {
                    action: 'pipebu_search_posts',
                    nonce : PIPEBU.nonce,
                    q     : q
                })
                .done(function (res) {
                    if (!res.success || !res.data.length) {
                        $('#pb-tone-ref-results').hide().empty();
                        return;
                    }
                    var html = '';
                    $.each(res.data, function (i, p) {
                        html += '<div class="pb-product-result-item" data-id="' + p.id + '" data-name="' + esc(p.name) + '">' + esc(p.name) + '</div>';
                    });
                    $('#pb-tone-ref-results').html(html).show();
                });
            }, 300);
        });

        $(document).on('click', '#pb-tone-ref-results .pb-product-result-item', function () {
            state.toneReferenceId   = $(this).data('id');
            state.toneReferenceName = $(this).data('name');
            $('#pb-tone-ref-search').val('').hide();
            $('#pb-tone-ref-results').hide().empty();
            $('#pb-tone-ref-selected-name').text(state.toneReferenceName);
            $('#pb-tone-ref-selected').show();
            $('#pb-custom-guard').hide();
        });

        $('#pb-tone-ref-clear').on('click', function () {
            clearToneReference();
        });

        $(document).on('click', function (e) {
            if (!$(e.target).closest('#pb-tone-ref-results').length && !$(e.target).is('#pb-tone-ref-search')) {
                $('#pb-tone-ref-results').hide();
            }
        });
    }

    function clearToneReference() {
        state.toneReferenceId   = null;
        state.toneReferenceName = '';
        $('#pb-tone-ref-selected').hide();
        $('#pb-tone-ref-selected-name').text('');
        $('#pb-tone-ref-search').val('').show();
    }

    // -------------------------------------------------------------------------
    // Color variation checkbox
    // -------------------------------------------------------------------------

    function bindColorCheckbox() {
        $('#pb-has-colors').on('change', function () {
            state.hasColors = this.checked;
            $('#pb-upload-hint').text( this.checked
                ? 'Upload one image per color. Max ' + PIPEBU.max_images + ' images, ' + PIPEBU.max_mb + 'MB total.'
                : 'Include product photos, packaging, and manual pages. Max ' + PIPEBU.max_images + ' images, ' + PIPEBU.max_mb + 'MB total.'
            );
            $('#pb-colors-guide').toggle(this.checked);
        });
    }

    // -------------------------------------------------------------------------
    // Upload — drag/drop + browse
    // -------------------------------------------------------------------------

    function bindUpload() {
        var $dz    = $('#pb-dropzone');
        var $input = $('#pb-file-input');

        $dz.on('dragover dragenter', function (e) {
            e.preventDefault();
            $dz.addClass('over');
        });
        $dz.on('dragleave drop', function (e) {
            e.preventDefault();
            $dz.removeClass('over');
            if (e.type === 'drop') {
                handleFiles(e.originalEvent.dataTransfer.files);
            }
        });

        $input.on('change', function () {
            handleFiles(this.files);
            this.value = '';
        });
    }

    function handleFiles(files) {
        if (!files || !files.length) return;

        var pending = state.attachmentIds.length + files.length;
        if (pending > PIPEBU.max_images) { alert(PIPEBU.strings.too_many); return; }

        var newMB = 0;
        for (var i = 0; i < files.length; i++) newMB += files[i].size / (1024 * 1024);
        var usedMB = Object.keys(state.imageSizesMB).reduce(function (s, k) { return s + state.imageSizesMB[k]; }, 0);
        if (usedMB + newMB > PIPEBU.max_mb) { alert(PIPEBU.strings.too_large); return; }

        var fileArr  = Array.from(files);
        var total    = fileArr.length;
        var uploaded = 0;

        showUploadProgress(0, total);

        function uploadNext(idx) {
            if (idx >= total) {
                hideUploadProgress();
                updateSizeBar();
                if (state.attachmentIds.length > 0) {
                    $('#pb-generate-options').slideDown(200);
                    refreshThumbnailRoles();
                }
                return;
            }

            var fd = new FormData();
            fd.append('action', 'pipebu_upload_images');
            fd.append('nonce', PIPEBU.nonce);
            fd.append('images[0]', fileArr[idx]);

            setUploadStatus('Uploading image ' + (idx + 1) + ' of ' + total + '…', idx + 1, total);

            $.ajax({
                url: PIPEBU.ajaxurl, type: 'POST',
                data: fd, processData: false, contentType: false,
                success: function (res) {
                    if (res.success && res.data.images.length) {
                        var img = res.data.images[0];
                        state.attachmentIds.push(img.id);
                        state.imageSizesMB[img.id]  = fileArr[idx].size / (1024 * 1024);
                        state.attachmentUrls[img.id] = img.url;
                        addThumb(img.id, img.url);
                    }
                    uploadNext(idx + 1);
                },
                error: function () { uploadNext(idx + 1); }
            });
        }

        uploadNext(0);
    }

    function showUploadProgress(done, total) {
        $('#pb-dropzone').hide();
        $('#pb-upload-progress').show();
        setUploadStatus('Preparing upload…', done, total);
    }

    function hideUploadProgress() {
        $('#pb-upload-progress').hide();
        $('#pb-upload-fill').css('width', '0%');
        $('#pb-dropzone').show();
    }

    function setUploadStatus(msg, done, total) {
        $('#pb-upload-status').text(msg);
        var pct = total > 0 ? Math.round((done / total) * 100) : 0;
        $('#pb-upload-fill').css('width', pct + '%');
    }

    function refreshThumbnailRoles() {
        var $thumbs = $('#pb-preview-grid .pb-thumb');
        var n = $thumbs.length;
        // First = Hero (always locked)
        $thumbs.removeClass('hero');
        if (n > 0) { $thumbs.first().addClass('hero'); state.heroIndex = 0; }
        // Last = How To (when >1 images)
        $thumbs.removeClass('howto');
        if (n > 1) { $thumbs.last().addClass('howto'); }
        // Strip manual from first and last — fixed roles only
        $thumbs.first().removeClass('manual');
        if (n > 1) { $thumbs.last().removeClass('manual'); }
    }

    function addThumb(id, url) {
        var $t = $('<div class="pb-thumb" data-id="' + id + '">');
        $t.append('<img src="' + url + '" alt="">');
        $t.append('<span class="pb-hero-label">Hero</span>');
        $t.append('<span class="pb-howto-label">How To</span>');
        $t.append('<span class="pb-manual-label">Manual</span>');
        $t.append('<button class="pb-remove-thumb" data-id="' + id + '" title="Remove">&#215;</button>');
        $t.on('click', function (e) {
            if ($(e.target).hasClass('pb-remove-thumb')) return;
            var $thumbs = $('#pb-preview-grid .pb-thumb');
            var idx = $thumbs.index($t);
            var last = $thumbs.length - 1;
            // First and last are fixed roles — clicks do nothing there
            if (idx === 0 || idx === last) { return; }
            // Middle image: toggle manual tag
            $t.toggleClass('manual');
        });
        $t.find('.pb-remove-thumb').on('click', function (e) {
            e.stopPropagation();
            state.attachmentIds = state.attachmentIds.filter(function (i) { return i !== id; });
            delete state.imageSizesMB[id];
            $t.remove();
            updateSizeBar();
            refreshThumbnailRoles();
            if (state.attachmentIds.length === 0) {
                $('#pb-generate-options').slideUp(200);
                $('#pb-size-bar').hide();
            }
        });
        $('#pb-preview-grid').append($t);
        refreshThumbnailRoles();
        updateSizeBar();
    }

    function updateSizeBar() {
        var count  = state.attachmentIds.length;
        if (count === 0) {
            $('#pb-size-bar').hide();
            $('#pb-img-legend').hide();
            $('#pb-hero-hint').hide();
            $('#pb-file-input').prop('disabled', false);
            $('.pb-browse-btn').removeClass('disabled');
            return;
        }
        var usedMB = Object.keys(state.imageSizesMB).reduce(function (s, k) { return s + state.imageSizesMB[k]; }, 0);
        $('#pb-size-bar').show();
        $('#pb-img-legend').show();
        if (state.inputMode !== 'guide') { $('#pb-hero-hint').show(); }
        $('#pb-count-text').text(count + ' / ' + PIPEBU.max_images + ' images');
        $('#pb-size-text').text(usedMB.toFixed(1) + ' MB / ' + PIPEBU.max_mb + ' MB');
        if (count >= PIPEBU.max_images) {
            $('#pb-file-input').prop('disabled', true);
            $('.pb-browse-btn').addClass('disabled');
        } else {
            $('#pb-file-input').prop('disabled', false);
            $('.pb-browse-btn').removeClass('disabled');
        }
    }

    // -------------------------------------------------------------------------
    // Language dropdown
    // -------------------------------------------------------------------------

    var origLangStrings = {
        tip             : $('.pb-custom-style-tip').text(),
        tone_ref_or     : $('.pb-tone-ref-or').text(),
        tone_ref_search : $('#pb-tone-ref-search').attr('placeholder') || '',
        custom_style_ph : $('#pb-custom-style').attr('placeholder') || '',
        custom_pill     : $('#pb-tone-pills .pb-pill[data-value="custom"]').text().trim(),
        custom_desc     : (PIPEBU.tones['custom'] || '').split(' — ')[1] || ''
    };

    function applyLangStrings(code) {
        var s = (code && code !== 'en' && PIPEBU.lang_ui && PIPEBU.lang_ui[code])
            ? PIPEBU.lang_ui[code]
            : origLangStrings;
        $('.pb-custom-style-tip').text(s.tip);
        $('.pb-tone-ref-or').text(s.tone_ref_or);
        $('#pb-tone-ref-search').attr('placeholder', s.tone_ref_search);
        $('#pb-custom-style').attr('placeholder', s.custom_style_ph);
        var $customPill = $('#pb-tone-pills .pb-pill[data-value="custom"]');
        $customPill.text(s.custom_pill);
        if (state.tone === 'custom') {
            $('#pb-tone-desc').text(s.custom_desc);
        }
    }

    function bindLanguage() {
        $('#pb-output-language').on('change', function () {
            state.outputLanguage = $(this).val();
            applyLangStrings(state.outputLanguage);
        });
    }

    // -------------------------------------------------------------------------
    // Pills — depth + tone
    // -------------------------------------------------------------------------

    function bindPills() {
        $('#pb-depth-pills').on('click', '.pb-pill', function () {
            $('#pb-depth-pills .pb-pill').removeClass('active');
            $(this).addClass('active');
            state.depth = $(this).data('value');
            var label = PIPEBU.depths[state.depth] || '';
            $('#pb-depth-desc').text(label.split(' — ')[1] || '');
        });

        $('#pb-tone-pills').on('click', '.pb-pill', function () {
            $('#pb-tone-pills .pb-pill').removeClass('active');
            $(this).addClass('active');
            state.tone = $(this).data('value');
            var label = PIPEBU.tones[state.tone] || '';
            $('#pb-tone-desc').text(label.split(' — ')[1] || '');
            var isCustom = state.tone === 'custom';
            $('#pb-custom-style').toggle(isCustom);
            $('.pb-custom-style-tip').toggle(isCustom);
            $('#pb-tone-ref-wrap').toggle(isCustom);
            if (!isCustom) {
                $('#pb-custom-guard').hide();
                $('#pb-guard-actions').show();
                $('#pb-guard-upgrade').hide();
            }
        });
    }

    // -------------------------------------------------------------------------
    // Templates — skeleton card selection
    // -------------------------------------------------------------------------

    function bindTemplates() {
        $('#pb-template-cards').on('click', '.pb-template-card', function () {
            $('.pb-template-card').removeClass('active');
            $(this).addClass('active');
            state.template = $(this).data('value');
        });
    }

    // -------------------------------------------------------------------------
    // Generate (async job)
    // -------------------------------------------------------------------------

    function bindGenerate() {
        // Guard button: switch to Professional
        $('#pb-guard-use-pro').on('click', function () {
            $('#pb-custom-guard').hide();
            $('#pb-guard-actions').show();
            $('#pb-guard-upgrade').hide();
            $('#pb-tone-pills .pb-pill').removeClass('active');
            $('#pb-tone-pills .pb-pill[data-value="professional"]').addClass('active');
            state.tone = 'professional';
            $('#pb-custom-style').hide();
            $('#pb-tone-ref-wrap').hide();
            $('#pb-generate-btn').trigger('click');
        });

        // Guard button: scroll to tone ref search
        $('#pb-guard-add-ref').on('click', function () {
            $('#pb-custom-guard').hide();
            $('#pb-tone-ref-search').show().focus();
        });

        $('#pb-generate-btn').on('click', function () {
            if (state.attachmentIds.length === 0) { alert(PIPEBU.strings.no_images); return; }

            // Custom tone guard: warn if no style text and no reference post.
            if (state.tone === 'custom') {
                var customText = $('#pb-custom-style').val().trim();
                if (!customText && !state.toneReferenceId) {
                    $('#pb-guard-msg').text(PIPEBU.strings.custom_tone_empty);
                    $('#pb-custom-guard').show();
                    return;
                }
            }

            var customStyle = state.tone === 'custom' ? $('#pb-custom-style').val() : '';
            var isGuide     = state.inputMode === 'guide';

            $('#pb-panel-1 .pb-card').hide();
            $('#pb-processing').show();
            setStep(2);
            setProcessingMsg(PIPEBU.strings.queuing);

            $.ajax({
                url      : PIPEBU.ajaxurl,
                type     : 'POST',
                dataType : 'text',
                data     : {
                    action: 'pipebu_queue_job',
                    nonce             : PIPEBU.nonce,
                    attachment_ids    : JSON.stringify(state.attachmentIds),
                    depth             : state.depth,
                    tone              : state.tone,
                    custom_style      : customStyle,
                    guide_mode        : isGuide ? '1' : '0',
                    template          : state.template,
                    tone_reference_id : state.toneReferenceId || 0,
                    has_colors        : (!isGuide && state.hasColors) ? '1' : '0',
                    output_language   : state.outputLanguage || ''
                }
            })
            .done(function (raw) {
                var res;
                try { res = JSON.parse(raw); } catch (e) {
                    resetPanel1();
                    alert('Server response error. Check console (F12) for details.');
                    return;
                }
                if (!res.success) {
                    resetPanel1();
                    var code = res.data && res.data.code ? res.data.code : '';
                    if (code === 'quota_exceeded' || code === 'guide_mode_locked' || code === 'credits_exhausted') {
                        showQuotaWall(code, res.data.offer || null);
                    } else {
                        alert(res.data && res.data.message ? res.data.message : PIPEBU.strings.error);
                    }
                    return;
                }
                state.jobId = res.data.job_id;
                var procMsg = isGuide
                    ? PIPEBU.strings.processing_guide
                    : (state.hasColors ? PIPEBU.strings.processing_colors : PIPEBU.strings.processing);
                setProcessingMsg(procMsg);
                $('.pb-processing-sub').text('This typically takes 20–40 seconds. Hang tight.');
                startPolling();
            })
            .fail(function (xhr) {
                resetPanel1();
                alert('HTTP ' + xhr.status + ' error. Check console (F12) for details.');
            });
        });
    }

    function startPolling() {
        state.pollTimer = setInterval(function () {
            $.post(PIPEBU.ajaxurl, {
                action: 'pipebu_poll_job',
                nonce  : PIPEBU.nonce,
                job_id : state.jobId
            })
            .done(function (res) {
                if (!res.success) return;
                var poll = res.data;
                if (poll.status === 'done') {
                    stopPolling();
                    state.generated = poll.result;
                    showReview(poll.result);
                } else if (poll.status === 'failed') {
                    stopPolling();
                    resetPanel1();
                    alert(poll.error || PIPEBU.strings.error);
                } else if (poll.status === 'not_found') {
                    // Job was cleaned up before we could read it.
                    stopPolling();
                    resetPanel1();
                    reportFailure('job_not_found');
                    alert(PIPEBU.strings.error);
                } else if (poll.age && poll.age > 90 && poll.status === 'queued') {
                    // Cron never fired — server too busy to start the job.
                    stopPolling();
                    resetPanel1();
                    reportFailure('cron_miss');
                    alert(PIPEBU.strings.timeout);
                } else if (poll.age && poll.age > 300) {
                    // Job started but PHP process was killed before completion.
                    stopPolling();
                    resetPanel1();
                    reportFailure('process_killed');
                    alert(PIPEBU.strings.timeout);
                }
            });
        }, 5000);
    }

    function stopPolling() {
        if (state.pollTimer) {
            clearInterval(state.pollTimer);
            state.pollTimer = null;
        }
    }

    function reportFailure(type) {
        $.post(PIPEBU.ajaxurl, {
            action       : 'pipebu_report_failure',
            nonce        : PIPEBU.nonce,
            failure_type : type
        });
    }

    function reportFunnelEvent(event) {
        $.post(PIPEBU.ajaxurl, {
            action : 'pipebu_funnel_event',
            nonce  : PIPEBU.nonce,
            event  : event
        });
    }

    function showReview(data) {
        $('#pb-processing').hide();
        $('#pb-panel-1').hide();
        setStep(3);

        injectTemplatePreview();

        var isGuide = state.inputMode === 'guide';

        if (isGuide) {
            populateExpert(data);
            $('#pb-product-col').hide();
            $('#pb-review-grid').addClass('pb-guide-mode-grid');
            $('#pb-publish-expert-btn').text('🚀 Publish How To Post');
            if (state.existingProductId) {
                $('#pb-guide-product-badge-name').text(state.existingProductName);
                $('#pb-guide-product-badge').show();
            }
            $('#pb-panel-2-expert').show();
        } else if (state.uiMode === 'simple') {
            populateSimple(data);
            buildColorRows(data.colors || []);
            $('#pb-panel-2-simple').show();
        } else {
            populateExpert(data);
            buildColorRows(data.colors || []);
            $('#pb-panel-2-expert').show();
        }
    }

    function injectTemplatePreview() {
        var $src = $('.pb-template-card[data-value="' + state.template + '"]');
        if (!$src.length) return;

        // Full card — Expert / Guide review
        var $card = $src.clone().removeClass('active').addClass('pb-tcard-review');
        $('#pb-template-card-preview').html(
            '<p class="pb-tcard-review-label">&#128203; Format used</p>'
        ).append($card).show();

        // Badge — Simple review
        var name = $src.find('.pb-tcard-name').text();
        $('#pb-template-badge').html(
            '<p class="pb-tcard-review-label">Format used</p>' +
            '<span class="pb-tbadge">&#128203; ' + esc(name) + '</span>'
        ).show();
    }

    // -------------------------------------------------------------------------
    // Populate review panels
    // -------------------------------------------------------------------------

    function populateSimple(data) {
        $('#pb_name_s').val(data.product_name || '');

        var html = '';
        if (data.description) {
            html += '<div class="pb-ai-block"><strong>Description</strong><p class="pb-truncate">' +
                stripTags(data.description).substring(0, 200) + '…</p></div>';
        }
        if (data.howto_title) {
            html += '<div class="pb-ai-block"><strong>How To Post</strong><p>' + esc(data.howto_title) + '</p></div>';
        }
        if (data.yoast_focus_keyword) {
            html += '<div class="pb-ai-block"><strong>Focus Keyword</strong><p>' + esc(data.yoast_focus_keyword) + '</p></div>';
        }
        if (data.confidence_notes) {
            html += '<div class="pb-ai-block pb-ai-note"><strong>AI Notes</strong><p>' + esc(data.confidence_notes) + '</p></div>';
        }
        $('#pb-ai-summary-inner').html(html);
    }

    function populateExpert(data) {
        $('#pb_name_e').val(data.product_name || '');
        $('#pb_short_e').val(stripTags(data.short_description || ''));
        $('#pb_desc_e').val(data.description || '');
        $('#pb_kw_e').val(data.yoast_focus_keyword || '');
        $('#pb_meta_e').val(data.yoast_meta_description || '').trigger('input');
        $('#pb_howto_title_e').val(data.howto_title || '');
        $('#pb_howto_content_e').val(data.howto_content || '');
        $('#pb_howto_meta_e').val(data.howto_meta_description || '').trigger('input');
        $('#pb_howto_kw_e').val(data.yoast_focus_keyword || '');
        if (data.confidence_notes) {
            $('#pb-confidence').show();
            $('#pb-confidence-text').text(data.confidence_notes);
        }
    }

    // -------------------------------------------------------------------------
    // Color variation rows
    // -------------------------------------------------------------------------

    function buildColorRows(aiColors) {
        if (!state.hasColors || !aiColors.length) {
            $('#pb-color-rows-simple, #pb-color-rows-expert').hide().empty();
            return;
        }

        var basePrice = $('#pb_reg_s').val() || $('#pb_reg_e').val() || '';

        state.colors = aiColors.map(function (c) {
            var idx   = c.image_index >= 0 && c.image_index < state.attachmentIds.length
                ? c.image_index : 0;
            var attId = state.attachmentIds[idx] || 0;
            return { attachmentId: attId, name: c.name || '', price: basePrice };
        });

        renderColorRows();
    }

    function syncColorPriceFields() {
        $('#pb_reg_s').closest('.pb-field').show();
        $('#pb_sale_s').closest('.pb-field').show();
    }

    function renderColorRows() {
        if (!state.hasColors || !state.colors.length) {
            $('#pb-color-rows-simple, #pb-color-rows-expert').hide().empty();
            syncColorPriceFields();
            return;
        }

        var html = '<p class="pb-colors-price-hint">Set a price for each color &mdash; WooCommerce displays the range automatically on the product page.</p>' +
                   '<h3 class="pb-colors-heading">Color Variations</h3>' +
                   '<p class="pb-colors-stock-hint">&#9432; Stock quantities per variation: set in WP Admin &rarr; Products after publishing.</p>' +
                   '<div class="pb-color-rows">';

        state.colors.forEach(function (c, i) {
            var thumbUrl = c.attachmentId ? (state.attachmentUrls[c.attachmentId] || '') : '';
            html += '<div class="pb-color-row" data-idx="' + i + '">';
            html += '<span class="pb-color-label">Color ' + (i + 1) + '</span>';
            if (thumbUrl) {
                html += '<img src="' + thumbUrl + '" class="pb-color-thumb" alt="" />';
            } else {
                html += '<span class="pb-color-thumb-empty"></span>';
            }
            html += '<input type="text" class="pb-color-name" data-idx="' + i + '" value="' + esc(c.name) + '" placeholder="Color name" />';
            html += '<input type="number" class="pb-color-price" data-idx="' + i + '" value="' + esc(c.price) + '" placeholder="Price" step="0.01" min="0" />';
            html += '<button type="button" class="pb-color-remove" data-idx="' + i + '" title="Remove">&#215;</button>';
            html += '</div>';
        });

        html += '</div>';

        $('#pb-color-rows-simple, #pb-color-rows-expert').html(html).show();
        syncColorPriceFields();
    }

    // Live edit handlers — delegated, not re-bound on each render.
    $(document).on('input', '.pb-color-name', function () {
        var idx = parseInt($(this).data('idx'), 10);
        if (state.colors[idx] !== undefined) {
            state.colors[idx].name = $(this).val();
            // Sync the sibling panel's input (only the one that isn't this one).
            $('.pb-color-name[data-idx="' + idx + '"]').not(this).val($(this).val());
        }
    });

    $(document).on('input', '.pb-color-price', function () {
        var idx = parseInt($(this).data('idx'), 10);
        if (state.colors[idx] !== undefined) {
            state.colors[idx].price = $(this).val();
            $('.pb-color-price[data-idx="' + idx + '"]').not(this).val($(this).val());
        }
    });

    $(document).on('click', '.pb-color-remove', function () {
        var idx = parseInt($(this).data('idx'), 10);
        state.colors.splice(idx, 1);
        renderColorRows();
    });

    // -------------------------------------------------------------------------
    // SEO traffic light
    // -------------------------------------------------------------------------

    function updateSeoLight(dotId, length) {
        var $dot = $('#' + dotId);
        $dot.removeClass('pb-dot-red pb-dot-orange pb-dot-green');
        if (length === 0) {
            $dot.addClass('pb-dot-red');
        } else if (length < 120) {
            $dot.addClass('pb-dot-orange');
        } else if (length <= 155) {
            $dot.addClass('pb-dot-green');
        } else {
            $dot.addClass('pb-dot-red');
        }
    }

    // -------------------------------------------------------------------------
    // Review actions
    // -------------------------------------------------------------------------

    function bindReview() {
        $('#pb_meta_e').on('input', function () {
            var l = $(this).val().length;
            $('#pb-meta-count').text(l + '/155').toggleClass('over', l > 155);
            updateSeoLight('pb-meta-dot', l);
        });

        $('#pb_howto_meta_e').on('input', function () {
            updateSeoLight('pb-howto-meta-dot', $(this).val().length);
        });

        $('#pb-to-expert-btn').on('click', function () {
            populateExpert(state.generated);
            $('#pb_reg_e').val($('#pb_reg_s').val());
            $('#pb_sale_e').val($('#pb_sale_s').val());
            $('#pb_stock_e').val($('#pb_stock_s').val());
            $('.pb-cat-expert').prop('checked', false);
            $('.pb-cat-simple:checked').each(function () {
                $('.pb-cat-expert[value="' + $(this).val() + '"]').prop('checked', true);
            });
            renderColorRows();
            $('#pb-panel-2-simple').hide();
            $('#pb-panel-2-expert').show();
            state.uiMode = 'expert';
            $('.pb-mode-btn').removeClass('active');
            $('.pb-mode-btn[data-mode="expert"]').addClass('active');
            $('.pb-mode-desc').text('Full review — all fields visible.');
        });

        $('#pb-back-btn').on('click', function () {
            $('#pb-panel-2-expert').hide();
            if (state.inputMode === 'guide') {
                $('#pb-product-col').show();
                $('#pb-review-grid').removeClass('pb-guide-mode-grid');
                $('#pb-publish-expert-btn').text('🚀 Publish Product + How To Post');
                $('#pb-guide-product-badge').hide();
                $('#pb-panel-1 .pb-card').not('#pb-processing').show();
                $('#pb-panel-1').show();
                setStep(1);
            } else {
                // Carry Expert manual fields back to Simple before re-populating.
                var regVal   = $('#pb_reg_e').val();
                var saleVal  = $('#pb_sale_e').val();
                var stockVal = $('#pb_stock_e').val();
                var checkedCats = [];
                $('.pb-cat-expert:checked').each(function () { checkedCats.push($(this).val()); });
                populateSimple(state.generated);
                $('#pb_reg_s').val(regVal);
                $('#pb_sale_s').val(saleVal);
                $('#pb_stock_s').val(stockVal);
                $('.pb-cat-simple').prop('checked', false);
                $.each(checkedCats, function (i, v) {
                    $('.pb-cat-simple[value="' + v + '"]').prop('checked', true);
                });
                $('#pb-panel-2-simple').show();
                state.uiMode = 'simple';
                $('.pb-mode-btn').removeClass('active');
                $('.pb-mode-btn[data-mode="simple"]').addClass('active');
                $('.pb-mode-desc').text('Guided — essentials only.');
                setStep(3);
            }
        });

        $('#pb-simple-startover-btn').on('click', function () {
            $('#pb-panel-2-simple').hide();
            fullReset();
        });

        $('#pb-publish-simple-btn').on('click', function () {
            doPublish( collectSimple() );
        });

        $('#pb-publish-expert-btn').on('click', function () {
            doPublish( collectExpert() );
        });

        $('#pb-restart-btn').on('click', function () {
            fullReset();
        });
    }

    function collectSimple() {
        return {
            guide_mode           : '0',
            has_colors           : state.hasColors ? '1' : '0',
            colors               : JSON.stringify(state.colors.map(function (c) {
                return { attachment_id: c.attachmentId, name: c.name, price: c.price };
            })),
            existing_product_id  : 0,
            product_name         : $('#pb_name_s').val(),
            short_description    : state.generated.short_description || '',
            description          : state.generated.description || '',
            regular_price        : $('#pb_reg_s').val(),
            sale_price           : $('#pb_sale_s').val(),
            stock_quantity       : $('#pb_stock_s').val(),
            category_ids         : getCats('simple'),
            yoast_focus_keyword  : state.generated.yoast_focus_keyword || '',
            yoast_meta_description: state.generated.yoast_meta_description || '',
            howto_title          : state.generated.howto_title || '',
            howto_content        : state.generated.howto_content || '',
            howto_meta_description: '',
            attachment_ids       : state.attachmentIds,
            hero_index           : state.heroIndex,
            template             : state.template || 'none',
            has_tone_reference   : state.toneReferenceId ? '1' : '0',
            output_language      : state.outputLanguage || ''
        };
    }

    function collectExpert() {
        var isGuide = state.inputMode === 'guide';
        return {
            guide_mode            : isGuide ? '1' : '0',
            has_colors            : (!isGuide && state.hasColors) ? '1' : '0',
            colors                : JSON.stringify(state.colors.map(function (c) {
                return { attachment_id: c.attachmentId, name: c.name, price: c.price };
            })),
            existing_product_id   : isGuide ? (state.existingProductId || 0) : 0,
            product_name          : $('#pb_name_e').val(),
            short_description     : $('#pb_short_e').val(),
            description           : $('#pb_desc_e').val(),
            regular_price         : $('#pb_reg_e').val(),
            sale_price            : $('#pb_sale_e').val(),
            stock_quantity        : $('#pb_stock_e').val(),
            category_ids          : getCats('expert'),
            yoast_focus_keyword   : isGuide ? $('#pb_howto_kw_e').val() : $('#pb_kw_e').val(),
            yoast_meta_description: $('#pb_meta_e').val(),
            howto_title           : $('#pb_howto_title_e').val(),
            howto_content         : $('#pb_howto_content_e').val(),
            howto_meta_description: $('#pb_howto_meta_e').val(),
            attachment_ids        : state.attachmentIds,
            hero_index            : state.heroIndex,
            template               : state.template || 'none',
            has_tone_reference     : state.toneReferenceId ? '1' : '0',
            output_language        : state.outputLanguage || ''
        };
    }

    function getCats(mode) {
        var ids = [];
        $('.pb-cat-' + mode + ':checked').each(function () { ids.push($(this).val()); });
        return ids;
    }

    function doPublish(data) {
        var isGuide = data.guide_mode === '1';
        if (isGuide) {
            if (!data.howto_title.trim()) { alert(PIPEBU.strings.howto_title_required); return; }
        } else {
            if (!data.product_name.trim()) { alert(PIPEBU.strings.name_required); return; }
        }
        if (state.hasColors && state.colors.some(function (c) { return ('' + c.price).trim() === ''; })) {
            alert('Please set a price for each color variation before publishing.');
            return;
        }

        $('#pb-panel-2-simple, #pb-panel-2-expert').hide();
        $('#pb-panel-1').show();
        showProcessing(PIPEBU.strings.publishing);

        data.action = 'pipebu_publish';
        data.nonce  = PIPEBU.nonce;

        $.post(PIPEBU.ajaxurl, data)
        .done(function (res) {
            if (!res.success) {
                $('#pb-processing').hide();
                $('#pb-panel-1').hide();
                alert(res.data.message || PIPEBU.strings.error);
                return;
            }

            // Hold banner visible for 1.5s before revealing success panel
            setTimeout(function () {
                $('#pb-processing').hide();
                $('#pb-panel-1').hide();

                var d    = res.data;
                var html = '';
                if (d.product_url && !d.guide_mode)  html += '<a href="' + d.product_url + '" target="_blank">&#128722; View Product</a>';
                if (d.product_edit && !d.guide_mode) html += '<a href="' + d.product_edit + '" target="_blank">&#9998; Edit Product</a>';
                if (d.product_url && d.guide_mode && d.product_id)  html += '<a href="' + d.product_url + '" target="_blank">&#128722; View Linked Product</a>';
                if (d.howto_url)    html += '<a href="' + d.howto_url + '" target="_blank">&#128214; View How To</a>';
                if (d.howto_edit)   html += '<a href="' + d.howto_edit + '" target="_blank">&#9998; Edit How To</a>';

                var statusMsg = d.publish_status === 'draft'
                    ? '&#128221; Saved as Draft — review in WP Admin before publishing.'
                    : (d.guide_mode
                        ? '&#127881; How To post is live!'
                        : '&#127881; Live! Your product is published.');

                $('#pb-publish-status-msg').html(statusMsg);
                $('#pb-success-links').html(html);
                $('#pb-panel-success').show();
                setStep(4);
            }, 1500);
        })
        .fail(function () {
            $('#pb-processing').hide();
            alert(PIPEBU.strings.error);
        });
    }

    // -------------------------------------------------------------------------
    // Mode toggle (header — Simple/Expert review mode)
    // -------------------------------------------------------------------------

    function bindModeToggle() {
        var modeDescs = {
            simple : 'Guided — essentials only.',
            expert : 'Full review — all fields visible.'
        };
        $('.pb-mode-btn').on('click', function () {
            $('.pb-mode-btn').removeClass('active');
            $(this).addClass('active');
            state.uiMode = $(this).data('mode');
            $('.pb-mode-desc').text(modeDescs[state.uiMode] || '');
        });
    }

    // -------------------------------------------------------------------------
    // Step indicator
    // -------------------------------------------------------------------------

    function setStep(n) {
        for (var i = 1; i <= 4; i++) {
            var $s = $('#pb-step-' + i);
            $s.removeClass('active done');
            if (i < n)        $s.addClass('done');
            else if (i === n) $s.addClass('active');
        }
        // Review Mode pills: always visible; locked (non-interactive) from Step 2 onward.
        $('.pb-mode-row').show().toggleClass('pb-mode-row--locked', n >= 2);
    }

    // -------------------------------------------------------------------------
    // Processing overlay
    // -------------------------------------------------------------------------

    function showProcessing(msg) {
        $('#pb-panel-1 .pb-card').hide();
        $('#pb-processing').show();
        setProcessingMsg(msg);
    }

    function setProcessingMsg(msg) {
        $('#pb-processing-msg').text(msg);
    }

    function resetPanel1() {
        stopPolling();
        $('#pb-panel-1 .pb-card').not('#pb-processing').show();
        $('#pb-processing').hide();
        $('#pb-panel-1').show();
        setStep(1);
    }

    // -------------------------------------------------------------------------
    // Quota wall
    // -------------------------------------------------------------------------

    function buildOfferHtml(offer) {
        if (!offer) { return ''; }

        if (offer.enterprise) {
            return 'You\'re on our top-tier plan. Need more volume? ' +
                '<a href="' + offer.checkout_url + '" target="_blank" class="pb-offer-link">Contact us for Enterprise pricing &rarr;</a>';
        }

        var html = '';
        var now  = Math.floor(Date.now() / 1000);

        if (offer.sale_active) {
            html += '<strong>&#128293; Sale active</strong> &mdash; ';
        } else if (offer.expiry_ts > 0 && offer.expiry_ts > now) {
            var remaining = offer.expiry_ts - now;
            var days      = Math.floor(remaining / 86400);
            var hours     = Math.floor((remaining % 86400) / 3600);
            var timeStr   = days > 0
                ? (days + ' day' + (days !== 1 ? 's' : '') + (hours > 0 ? ' ' + hours + ' hr' : ''))
                : (hours > 0 ? hours + ' hr' + (hours !== 1 ? 's' : '') : 'less than 1 hr');
            html += '<strong>&#9201; Special offer &mdash; expires in ' + timeStr + '</strong> &mdash; ';
        }

        html += '<strong>' + offer.name + '</strong>: ';
        html += offer.credits + ' credit' + (offer.credits !== 1 ? 's' : '') + ' for <strong>$' + offer.price + '</strong>';
        if (offer.savings > 0) {
            html += ' &mdash; <span class="pb-offer-savings">save $' + offer.savings + ' vs. buying individually</span>';
        }

        return html;
    }

    function showQuotaWall(code, offer) {
        // Hide all panels, show the upgrade wall.
        $('.pb-panel').hide();
        $('#pb-steps').hide();
        // Tailor messaging to the specific block reason.
        if (code === 'guide_mode_locked') {
            $('#pb-panel-quota .pb-quota-wall-icon').html('&#128214;');
            $('#pb-panel-quota h2').text('Guide Mode is a paid feature');
            $('#pb-panel-quota p').first().text('Guide Mode (How To Only) is available on paid plans.');
            $('#pb-panel-quota .pb-quota-wall-sub').text('Upgrade to unlock Guide Mode and keep publishing without limits.');
            $('#pb-quota-upgrade-btn').html('Upgrade Pipeline Buster &rarr;');
        } else if (code === 'credits_exhausted') {
            $('#pb-panel-quota .pb-quota-wall-icon').html('&#9888;');
            $('#pb-panel-quota h2').text(PIPEBU.strings.credits_exhausted_title || 'Credits exhausted');
            $('#pb-panel-quota p').first().text(PIPEBU.strings.credits_exhausted_msg || 'You\'ve used all your product credits. Purchase more to keep publishing.');
            $('#pb-panel-quota .pb-quota-wall-sub').html(buildOfferHtml(offer));
            $('#pb-quota-upgrade-btn').html((offer && offer.enterprise) ? 'Contact Us &rarr;' : (PIPEBU.strings.credits_buy_more || 'Buy More Credits &rarr;'));
        } else {
            $('#pb-panel-quota .pb-quota-wall-icon').html('&#128640;');
            $('#pb-panel-quota h2').text(PIPEBU.strings.quota_title || 'Free limit reached');
            $('#pb-panel-quota p').first().text(PIPEBU.strings.quota_msg || '');
            $('#pb-panel-quota .pb-quota-wall-sub').html(buildOfferHtml(offer));
            $('#pb-quota-upgrade-btn').html('Get Credits &rarr;');
        }
        // Wire upgrade button — offer URL takes priority over static fallback.
        var checkoutUrl = (offer && offer.checkout_url) ? offer.checkout_url : (PIPEBU.quota.upgrade_url || '#');
        $('#pb-quota-upgrade-btn').attr('href', checkoutUrl);
        $('#pb-panel-quota').show();
    }

    $(document).on('click', '#pb-quota-later-btn', function () {
        // "Maybe later" — return to Step 1 so they can still use Guide Mode.
        reportFunnelEvent('quota_wall_later_click');
        $('#pb-panel-quota').hide();
        $('#pb-steps').show();
        fullReset();
    });

    $(document).on('click', '.pb-quota-upgrade-link', function (e) {
        e.preventDefault();
        reportFunnelEvent('quota_wall_upgrade_click');
        var url = $('#pb-quota-upgrade-btn').attr('href') || (PIPEBU.quota && PIPEBU.quota.upgrade_url ? PIPEBU.quota.upgrade_url : '#');
        if (url !== '#') { window.open(url, '_blank'); }
    });

    // -------------------------------------------------------------------------
    // Full reset
    // -------------------------------------------------------------------------

    function fullReset() {
        stopPolling();
        state.attachmentIds       = [];
        state.imageSizesMB        = {};
        state.attachmentUrls      = {};
        state.heroIndex           = 0;
        state.generated           = {};
        state.jobId               = null;
        state.inputMode           = 'standard';
        state.existingProductId   = null;
        state.existingProductName = '';
        state.toneReferenceId     = null;
        state.toneReferenceName   = '';
        state.template            = 'none';
        state.hasColors           = false;
        state.colors              = [];

        // Reset input mode UI.
        $('.pb-input-tab').removeClass('active');
        $('.pb-input-tab[data-input-mode="standard"]').addClass('active');
        $('#pb-guide-product-wrap').hide();
        clearProductSelection();
        $('#pb-upload-heading').text('Upload Product Images');
        $('#pb-upload-hint').text('Include product photos, packaging, and manual pages. Max ' + PIPEBU.max_images + ' images, ' + PIPEBU.max_mb + 'MB total.');
        $('#pb-dropzone-label').text('Drag & drop images here');
        $('#pb-generate-btn').text('⚡ Analyze & Generate Content');

        // Reset review mode to default.
        state.uiMode = PIPEBU.ui_mode || 'simple';
        $('.pb-mode-btn').removeClass('active');
        $('.pb-mode-btn[data-mode="' + state.uiMode + '"]').addClass('active');

        // Reset tone to Professional and clear custom field.
        state.tone = 'professional';
        $('#pb-tone-pills .pb-pill').removeClass('active');
        $('#pb-tone-pills .pb-pill[data-value="professional"]').addClass('active');
        $('#pb-tone-desc').text( (PIPEBU.tones['professional'] || '').split(' — ')[1] || '' );
        clearToneReference();
        $('#pb-custom-style').val('').hide();
        $('.pb-custom-style-tip').hide();
        $('#pb-tone-ref-wrap').hide();
        $('#pb-custom-guard').hide();

        // Reset language to Auto and restore UI strings.
        state.outputLanguage = '';
        $('#pb-output-language').val('');
        applyLangStrings('');

        // Reset review panels.
        $('#pb-product-col').show();
        $('#pb-review-grid').removeClass('pb-guide-mode-grid');
        $('#pb-publish-expert-btn').text('🚀 Publish Product + How To Post');
        $('#pb-guide-product-badge').hide();

        // Reset color checkbox + rows.
        $('#pb-has-colors').prop('checked', false);
        $('#pb-colors-guide').hide();
        $('#pb-colors-wrap').show();
        $('#pb-color-rows-simple, #pb-color-rows-expert').hide().empty();
        syncColorPriceFields();

        // Reset template cards to AI Decides.
        $('.pb-template-card').removeClass('active');
        $('.pb-template-card[data-value="none"]').addClass('active');
        state.template = 'none';

        $('#pb-template-card-preview').hide().empty();
        $('#pb-template-badge').hide().empty();

        $('#pb-preview-grid').empty();
        $('#pb-generate-options').hide();
        $('#pb-size-bar').hide();
        $('#pb-img-legend').hide();
        $('#pb-hero-hint').hide();
        $('#pb-file-input').prop('disabled', false);
        $('.pb-browse-btn').removeClass('disabled');
        $('#pb-panel-2-simple, #pb-panel-2-expert, #pb-panel-success').hide();
        $('#pb-panel-1 .pb-card').not('#pb-processing').show();
        $('#pb-processing').hide();
        $('#pb-panel-1').show();

        $( '#pb_name_s,#pb_name_e,#pb_reg_s,#pb_reg_e,#pb_sale_s,#pb_sale_e,' +
           '#pb_stock_s,#pb_stock_e,#pb_short_e,#pb_desc_e,#pb_kw_e,#pb_meta_e,' +
           '#pb_howto_title_e,#pb_howto_content_e,#pb_howto_meta_e,#pb_howto_kw_e' ).val('');
        $('.pb-cat-simple, .pb-cat-expert').prop('checked', false);
        $('#pb-confidence').hide();
        $('#pb-ai-summary-inner').empty();
        $('#pb-meta-count').text('0/155').removeClass('over');
        $('#pb-meta-dot, #pb-howto-meta-dot').removeClass('pb-dot-red pb-dot-orange pb-dot-green');

        setStep(1);
        window.scrollTo(0, 0);
    }

    // -------------------------------------------------------------------------
    // Helpers
    // -------------------------------------------------------------------------

    function stripTags(html) {
        var d = document.createElement('div');
        d.innerHTML = html;
        return d.textContent || d.innerText || '';
    }

    function esc(str) {
        return $('<div>').text(str).html();
    }

}(jQuery));

// =========================================================================
// GSC Settings Panel
// =========================================================================
(function ($) {
    'use strict';

    // Save selected site.
    $(document).on('click', '#pb-gsc-save-site-btn', function () {
        var url = $('#pb_gsc_site').val();
        if (!url) return;
        var $btn = $(this).prop('disabled', true).text('Saving…');
        $.post(PIPEBU.ajaxurl, {
            action: 'pb_gsc_set_site',
            nonce: PIPEBU.nonce,
            site_url: url
        }, function (res) {
            $btn.prop('disabled', false).text('Save');
            if (res.success) {
                $('#pb-gsc-site-saved').fadeIn().delay(2000).fadeOut();
            }
        });
    });

    // Take / update baseline.
    $(document).on('click', '#pb-gsc-baseline-btn', function () {
        var $btn     = $(this).prop('disabled', true);
        var $spinner = $('#pb-gsc-baseline-spinner').show();
        var $msg     = $('#pb-gsc-baseline-msg').hide();

        $.post(PIPEBU.ajaxurl, {
            action: 'pb_gsc_take_baseline',
            nonce: PIPEBU.nonce
        }, function (res) {
            $btn.prop('disabled', false);
            $spinner.hide();
            if (res.success) {
                var d = res.data;
                $msg.html(
                    '<strong>Baseline saved (' + d.date + ')</strong><br>' +
                    'Impressions: ' + d.impressions.toLocaleString() + ' &nbsp;|&nbsp; ' +
                    'Clicks: ' + d.clicks.toLocaleString() + ' &nbsp;|&nbsp; ' +
                    'Keywords: ' + d.keywords.toLocaleString() + ' &nbsp;|&nbsp; ' +
                    'Avg Position: ' + d.position
                ).css('color', '#46b450').show();
                setTimeout(function () { location.reload(); }, 1800);
            } else {
                $msg.html(res.data || 'Error retrieving data.').css('color', '#dc3232').show();
            }
        });
    });

    // Disconnect.
    $(document).on('click', '#pb-gsc-disconnect-btn', function () {
        if (!confirm('Disconnect Google Search Console? Baseline data will be cleared.')) return;
        var $btn = $(this).prop('disabled', true);
        $.post(PIPEBU.ajaxurl, {
            action: 'pb_gsc_disconnect',
            nonce: PIPEBU.nonce
        }, function (res) {
            if (res.success) {
                location.reload();
            } else {
                $btn.prop('disabled', false);
            }
        });
    });

    // Security log — clear button
    $(document).on('click', '.pb-sec-clear-btn', function () {
        if ( ! confirm( PIPEBU.strings.sec_clear_confirm ) ) return;
        var btn = this;
        btn.disabled = true;
        fetch( ajaxurl, {
            method  : 'POST',
            headers : { 'Content-Type': 'application/x-www-form-urlencoded' },
            body    : 'action=pipebu_clear_sec_log&nonce=' + encodeURIComponent( btn.dataset.nonce )
        } )
        .then( r => r.json() )
        .then( d => { if ( d.success ) location.reload(); else btn.disabled = false; } );
    } );

}(jQuery));
