jQuery(document).ready(function ($) {

    let currentRequest = null;
    let currentBulkRequest = null;

    /* --------------------------------------------------------------
   RESET INDIVIDUAL PANEL
   -------------------------------------------------------------- */
    function resetIndividualPanel() {
        $('#short-desc-panel, #full-desc-panel, #category-desc-panel, #tag-descs-panel, #brand-desc-panel')
            .val('');
        $('#generatedAccordion').addClass('hidden');
        $('#descgpt-regenerate-btn, #descgpt-save-btn').addClass('hidden');
        $('#content-stats').addClass('hidden').text('Words: 0 | Characters: 0');
        $('#descgpt-content-warning').addClass('hidden').empty();
        $('#generatedAccordion [id$="-body"]').addClass('hidden');
        $('#generatedAccordion button[aria-expanded="true"]')
            .attr('aria-expanded', 'false')
            .find('svg').removeClass('rotate-180');
    }

    $(function () {
        $('#descgpt-content-type').on('change', function () {
            resetIndividualPanel();
            $('#descgpt-item-select')
                .empty()
                .append('Select an item');
        });

        $('#descgpt-item-select').on('change', resetIndividualPanel);
    });

    $(function () {
        function setActiveTab($tab) {
            $('.descgpt-tab')
                .removeClass('text-blue-600 border-blue-600')
                .addClass('text-gray-500');

            // Add active styles to the clicked tab
            $tab.addClass('text-blue-600 border-b-4 border-blue-600')
                .removeClass('text-gray-500');

            const panelId = $tab.is('#descgpt-tab-individual')
                ? '#descgpt-individual-panel'
                : '#descgpt-bulk-panel';

            $('#descgpt-individual-panel, #descgpt-bulk-panel').addClass('hidden');
            $(panelId).removeClass('hidden');

            // Reset the panel that is about to be shown
            if ($tab.is('#descgpt-tab-individual')) {
                resetIndividualPanel();
            } else {
                resetBulkPanel();
            }
        }

        $(document).on('click', '#descgpt-tab-individual, #descgpt-tab-bulk', function (e) {
            e.preventDefault();
            setActiveTab($(this));
        });

        setActiveTab($('#descgpt-tab-individual'));
    });

    // Show toast notification
    function showToast(message, isError = false) {
        const toast = $('#descgpt-toast');
        $('#descgpt-toast-message').text(message);
        toast.removeClass('hidden').addClass('show').toggleClass('error', isError);
        setTimeout(() => {
            toast.removeClass('show').addClass('hidden');
        }, 3000);
    }

    // Tab switching
    $('#descgpt-tab-individual').addClass('active');
    $('#descgpt-tab-individual').on('click', function () {
        $(this).addClass('active').siblings().removeClass('active');
        $('#descgpt-individual-panel').removeClass('hidden');
        $('#descgpt-bulk-panel').addClass('hidden');
    });

    $('#descgpt-tab-bulk').on('click', function () {
        $(this).addClass('active').siblings().removeClass('active');
        $('#descgpt-bulk-panel').removeClass('hidden');
        $('#descgpt-individual-panel').addClass('hidden');
    });

    // Show relevant accordion panels based on content type
    $('#descgpt-content-type').on('change', function () {
        const type = $(this).val();

        $('#descgpt-individual-panel #generatedAccordion > div').addClass('hidden');

        $('#descgpt-bulk-accordion').empty().addClass('hidden');
        $('#descgpt-save-bulk-btn').addClass('hidden');

        // Show only relevant accordion parent divs for the selected type in individual panel
        if (type === 'product') {
            $('#accordion-short-desc-heading').parent().removeClass('hidden');
            $('#accordion-full-desc-heading').parent().removeClass('hidden');
        } else if (type === 'category') {
            $('#accordion-category-desc-heading').parent().removeClass('hidden');
        } else if (type === 'tag') {
            $('#accordion-tag-descs-heading').parent().removeClass('hidden');
        } else if (type === 'brand') {
            $('#accordion-brand-desc-heading').parent().removeClass('hidden');
        }

        // Populate items based on content type
        var isTaxonomy = type !== 'product';
        $('#descgpt-item-select').prop('multiple', isTaxonomy).html('<option>Loading...</option>');
        $.post(descgptwSettings.ajaxurl, {
            action: 'descgpt_fetch_items',
            type: type,
            nonce: descgptwSettings.nonce
        }, function (res) {
            if (res.success) {
                var html = '<option value="">Select ' + (isTaxonomy ? 'items' : 'an item') + '</option>';
                $.each(res.data, function (i, item) {
                    html += '<option value="' + item.id + '">' + item.name + '</option>';
                });
                $('#descgpt-item-select').html(html);
            } else {
                showToast('Failed to fetch items: ' + (res.data || 'Unknown error'), true);
                $('#descgpt-item-select').html('<option value="">Select an item</option>');
            }
            // Trigger selection summary update
            $('#descgpt-item-select').trigger('change');
        });
        if (!isTaxonomy) fetchLastGenerated();
        else {
            $('#last-generated').addClass('hidden');
            $('#descgpt-selection-summary').addClass('empty');
        }
    }).trigger('change');

    // Update selection summary and trigger timestamp fetch
    $('#descgpt-item-select').on('change', function () {
        const selectedOptions = $(this).find('option:selected');
        const count = selectedOptions.length;
        const summary = count > 0
            ? `<?php _e('Selected', 'mg-ai-product-rec'); ?>: ${count} item${count > 1 ? 's' : ''}`
            : 'No items selected';
        $('#descgpt-selection-summary span').text(summary);
        $('#descgpt-selection-summary').toggleClass('empty', count === 0);
        $('#descgpt-feedback-area').toggleClass('empty', count === 0 && $('#last-generated').hasClass('hidden'));
        fetchLastGenerated();
    });

    // Highlight active accordion
    $('#generatedAccordion button').on('click', function () {
        $('#generatedAccordion h3').removeClass('active');
        $(this).parent().addClass('active');
    });

    // Fetch last generated timestamp
    function fetchLastGenerated() {
        var type = $('#descgpt-content-type').val();
        var ids = $('#descgpt-item-select').val();

        // Handle single or multiple IDs (use first ID for timestamp)
        var id = Array.isArray(ids) ? ids[0] : ids;

        if (!type || !id) {
            $('#last-generated').addClass('hidden');
            $('#descgpt-feedback-area').toggleClass('empty', $('#descgpt-selection-summary').hasClass('empty'));
            return;
        }

        $('#last-generated-loading').removeClass('hidden');
        $('#last-generated-timestamp').text('');

        $.post(descgptwSettings.ajaxurl, {
            action: 'descgpt_get_last_generated',
            type: type,
            id: id,
            nonce: descgptwSettings.nonce
        }, function (res) {
            $('#last-generated-loading').addClass('hidden');
            if (res.success && res.data.timestamp) {
                $('#last-generated-timestamp').text(res.data.timestamp);
                $('#last-generated').removeClass('hidden').addClass('animate__animated animate__fadeIn');
                $('#descgpt-feedback-area').removeClass('empty');
            } else {
                $('#last-generated').addClass('hidden');
                $('#descgpt-feedback-area').toggleClass('empty', $('#descgpt-selection-summary').hasClass('empty'));
            }
        }).fail(function () {
            $('#last-generated-loading').addClass('hidden');
            $('#last-generated').addClass('hidden');
            $('#descgpt-feedback-area').toggleClass('empty', $('#descgpt-selection-summary').hasClass('empty'));
            showToast('Failed to fetch last generated timestamp.', true);
        });
    }

    // Trigger on content type or item change
    $('#descgpt-content-type, #descgpt-item-select').on('change', fetchLastGenerated);

    // ======================== INDIVIDUAL GENERATION SUPPORT ======================== //
    function generateContent(regenerate = false) {
        var type = $('#descgpt-content-type').val();
        var ids = $('#descgpt-item-select').val();
        var limitType = $('#descgpt-limit-type').val();
        var limitValue = $('#descgpt-limit-value').val();

        // Validation
        if (!type || !ids || !ids.length) {
            showToast('Select type and item(s)', true);
            return finishIndividualRequest();
        }
        if (!limitValue || limitValue < 50 || limitValue > 1000) {
            showToast('Enter a limit value between 50 and 1000', true);
            return;
        }
        if (!$('#descgpt-enable-products').is(':checked') && type === 'product') {
            showToast('AI for products is disabled', true);
            return finishIndividualRequest();
        }
        if (!$('#descgpt-enable-taxonomies').is(':checked') && type !== 'product') {
            showToast('AI for taxonomies is disabled', true);
            return finishIndividualRequest();
        }

        // Display buttons state
        $('#descgpt-loading-spinner').removeClass('hidden');
        $('#descgpt-generate-btn, #descgpt-regenerate-btn').addClass('processing').prop('disabled', true);
        $('#descgpt-cancel-btn').removeClass('hidden');

        if (currentRequest) currentRequest.abort();

        currentRequest = $.post(descgptwSettings.ajaxurl, {
            action: 'descgpt_generate_description',
            type: type,
            ids: ids,
            limit_type: limitType,
            limit_value: limitValue,
            regenerate: regenerate ? 1 : 0,
            nonce: descgptwSettings.nonce
        }, function (res) {

            finishIndividualRequest();

            if (!res.success || !res.data.content || res.data.content.length === 0) {
                resetIndividualPanel();
                showToast('No content generated', true);
                return;
            }

            $('#descgpt-generate-btn, #descgpt-regenerate-btn').removeClass('processing').prop('disabled', false);

            if (res.success && res.data.content && res.data.content.length > 0) {
                var item = res.data.content[0];
                lastTokensUsed = item.tokens_used || 0;
                lastOutputTokens = item.output_tokens || 0;
                var parsed = item.parsed_content;
                var raw = item.content;
                var type = $('#descgpt-content-type').val();

                lastTokensUsed = parseInt(item.tokens_used) || 0;
                lastOutputTokens = parseInt(item.output_tokens) || 0;

                // Clear all
                $('#short-desc-panel, #full-desc-panel, #category-desc-panel, #tag-descs-panel, #brand-desc-panel').val('');

                let savedContent = '';
                if (type === 'product') {
                    $('#short-desc-panel').val(parsed.short_description || '');
                    $('#full-desc-panel').val(parsed.full_description || '');
                }
                else if (type === 'category') {
                    $('#category-desc-panel').val(parsed.category_description || '');
                    savedContent = parsed.category_description || '';
                }
                else if (type === 'tag') {
                    $('#tag-descs-panel').val(parsed.tag_description || '');
                    savedContent = parsed.tag_description || '';
                }
                else if (type === 'brand') {
                    $('#brand-desc-panel').val(parsed.brand_description || '');
                    savedContent = parsed.brand_description || '';
                }

                // NOW update stats
                updateContentStats();

                // === ADD THIS BLOCK HERE ===
                const panelMap = {
                    product: '#accordion-full-desc-body',
                    category: '#accordion-category-desc-body',
                    tag: '#accordion-tag-descs-body',
                    brand: '#accordion-brand-desc-body'
                };
                const target = panelMap[type];
                if (target) {
                    $(target).removeClass('hidden');
                    // Auto-scroll to the panel
                    $('html, body').animate({
                        scrollTop: $(target).offset().top - 120
                    }, 600);
                }

                $('#generatedAccordion').removeClass('hidden').addClass('animate__animated animate__fadeIn');
                $('#descgpt-regenerate-btn, #descgpt-save-btn').removeClass('hidden');
                checkContentSafety(raw);

                // saveGeneratedContent([item.id], [savedContent], type, true);
                showToast('Content generated successfully!');
                fetchLastGenerated();
            } else {
                const msg = res.data || 'Unknown error';
                showToast('Failed to generate content: ' + msg, true);
            }
        }).fail(function (xhr) {
            finishIndividualRequest();

            if (xhr.statusText !== 'abort') {
                showToast('AJAX error: ' + (xhr.responseText || 'Request failed'), true);
            }

            showToast('AJAX error: ' + (xhr.responseText || 'Request failed'), true);
        });
    }

    function saveGeneratedContent(ids, contents, type, force = false) {
        if (ids.length !== contents.length) return;

        ids.forEach(function (id, index) {
            $.post(descgptwSettings.ajaxurl, {
                action: 'descgpt_save_to_item',
                type: type,
                ids: [id],
                content: contents[index],
                language: descgptwSettings.language || 'English',
                enable: $('#descgpt-enable-ai').is(':checked') ? 1 : 0,
                force: force ? 1 : 0,
                nonce: descgptwSettings.nonce
            });
        });
    }

    function finishIndividualRequest() {
        $('#descgpt-loading-spinner').addClass('hidden');
        $('#descgpt-generate-btn, #descgpt-regenerate-btn')
            .removeClass('processing').prop('disabled', false);
        $('#descgpt-cancel-btn').addClass('hidden');
        currentRequest = null;
    }

    $('#descgpt-cancel-btn').on('click', function () {
        if (currentRequest) {
            currentRequest.abort();
            showToast('Generation cancelled', true);
        }
    });

    $('#descgpt-generate-btn').on('click', function () {
        $(this).addClass('processing').prop('disabled', true);
        generateContent(false);
    });

    $('#descgpt-regenerate-btn').on('click', function () {
        $(this).addClass('processing').prop('disabled', true);
        generateContent(true);
    });

    let lastTokensUsed = 0;
    let lastOutputTokens = 0;

    function updateContentStats() {
        const limitType = $('#descgpt-limit-type').val();
        const limitValue = parseInt($('#descgpt-limit-value').val()) || 0;
        const contentType = $('#descgpt-content-type').val();

        let content = '';
        let count = 0;
        let unit = 'Words';
        let isEstimate = false;

        // === GET CONTENT BASED ON TYPE ===
        if (contentType === 'product') {
            const short = $('#short-desc-panel').val() || '';
            const full = $('#full-desc-panel').val() || '';
            content = (short + ' ' + full).trim();
        }
        else if (contentType === 'category') {
            content = $('#category-desc-panel').val() || '';
        }
        else if (contentType === 'tag') {
            content = $('#tag-descs-panel').val() || '';
        }
        else if (contentType === 'brand') {
            content = $('#brand-desc-panel').val() || '';
        }

        // === COUNT BASED ON LIMIT TYPE ===
        if (limitType === 'words') {
            count = content.split(/\s+/).filter(w => w.length > 0).length;
            unit = 'Words';
        }
        else if (limitType === 'tokens') {
            // Use only the OUTPUT tokens!
            count = lastOutputTokens > 0 ? lastOutputTokens : 0;
            unit = 'Tokens';

            // Show estimate only if no real value yet
            if (count === 0 && content.length > 0) {
                count = '~' + Math.ceil(content.length / 3.8);
                $('#content-stats span').addClass('italic opacity-70');
            } else {
                $('#content-stats span').removeClass('italic opacity-70');
            }
        }

        // === COLOR LOGIC ===
        const ratio = limitValue > 0 ? count / limitValue : 0;
        let color = 'text-green-600';

        if (ratio < 0.7 || ratio > 1.0) {
            color = 'text-yellow-600';
        }

        const displayCount = (typeof count === 'string' && count.startsWith('~')) ? count : count;

        $('#content-stats')
            .html(`${unit}: <span class="${color} font-semibold">${displayCount}</span> / ${limitValue}`)
            .removeClass('hidden');
    }

    // Display in panels
    function displaySections(content) {
        var parsed = parseContent(content);
        $('#short-desc-panel').val(parsed.short_description || '');
        $('#full-desc-panel').val(parsed.full_description || '');
        $('#category-desc-panel').val(parsed.category_description || '');
        $('#tag-descs-panel').val(parsed.tag_descriptions || '');
        $('#brand-desc-panel').val(parsed.brand_description || parsed.brand_story || '');
        $('#generatedAccordion').removeClass('hidden');
    }

    function parseContent(content) {
        var parsed = {};
        var match = content.match(/Short Description:\s*(.*?)(?:\n\nFull Description:\s*(.*))?/s);
        if (match) {
            parsed.short_description = match[1].trim();
            parsed.full_description = (match[2] || '').trim();
        } else {
            // Fallback similar to PHP
            var parts = content.split("\n\n");
            parsed.short_description = parts[1] ? parts[1].trim() : parts[0].trim();
            parsed.full_description = parts[2] ? parts[2].trim() : '';
        }
        // Remove trailing opening bracket from both fields
        if (parsed.short_description)
            parsed.short_description = parsed.short_description.replace(/\s*\[\s*$/, '');
        if (parsed.full_description)
            parsed.full_description = parsed.full_description.replace(/\s*\[\s*$/, '');
        return parsed;
    }

    // Content safety check
    function checkContentSafety(content) {
        $.post(descgptwSettings.ajaxurl, {
            action: 'descgpt_check_safety',
            content: Array.isArray(content) ? JSON.stringify(content) : content,
            nonce: descgptwSettings.nonce
        }, function (res) {
            if (res.success && res.data.warning) {
                $('#descgpt-content-warning').text(res.data.warning).removeClass('hidden').addClass('animate__animated animate__shakeX');
            } else {
                $('#descgpt-content-warning').addClass('hidden');
            }
        });
    }

    // Save content to item
    $('#descgpt-save-btn').on('click', function () {
        var type = $('#descgpt-content-type').val();
        var ids = $('#descgpt-item-select').val();
        var content = '';
        var language = descgptwSettings.language || 'English';

        if (type === 'product') {
            var shortDesc = $('#short-desc-panel').val();
            var fullDesc = $('#full-desc-panel').val();
            content = (shortDesc || '') + (fullDesc ? '\n\n' + fullDesc : '');
        } else if (type === 'category') {
            content = $('#category-desc-panel').val();
        } else if (type === 'tag') {
            content = $('#tag-descs-panel').val();
        } else if (type === 'brand') {
            content = $('#brand-desc-panel').val();
        }

        if (!content.trim()) {
            showToast('No content to save.', true);
            return;
        }

        if (!confirm('Are you sure you want to save this generated content to the selected item(s)? This will overwrite existing descriptions.')) {
            return;
        }

        var btn = $(this);
        btn.addClass('processing').prop('disabled', true).text('Saving...');

        $.post(descgptwSettings.ajaxurl, {
            action: 'descgpt_save_to_item',
            type: type,
            ids: ids,
            content: content,
            language: language,
            enable: $('#descgpt-enable-ai').is(':checked') ? 1 : 0,
            force: 1,
            nonce: descgptwSettings.nonce
        }, function (res) {
            btn.removeClass('processing').prop('disabled', false).text('Save to Item');
            if (res.success) {
                showToast(res.data.message || 'Content saved successfully!');
                if (type === 'product' || ids.length === 1) fetchLastGenerated();
            } else {
                showToast('Failed to save content: ' + res.data, true);
            }
        });
    });

    // ======================== BULK GENERATION SUPPORT ======================== //
    function resetBulkPanel() {
        $('#descgpt-bulk-accordion').empty().addClass('hidden');

        $('#descgpt-bulk-log').addClass('hidden');
        $('#descgpt-bulk-status').empty();
        $('#descgpt-bulk-list').empty();
        $('#descgpt-save-bulk-btn').addClass('hidden');
        $('.bulk-stats').remove();
    }

    $(function () {
        /* ------------------------------------------------------------------
           Content type – clears both panels (bulk + individual)
           ------------------------------------------------------------------ */
        $('#descgpt-content-type').on('change', function () {
            resetIndividualPanel();   // already exists
            resetBulkPanel();

            $('#descgpt-item-select')
                .empty()
                .append('Select an item');
        });

        /* ------------------------------------------------------------------
           Limit type / value
           ------------------------------------------------------------------ */
        $('#descgpt-limit-type, #descgpt-limit-value').on('change input', function () {
            resetIndividualPanel();
            resetBulkPanel();
        });

        /* ------------------------------------------------------------------
           Enable toggles
           ------------------------------------------------------------------ */
        $('#descgpt-enable-products, #descgpt-enable-taxonomies').on('change', function () {
            resetIndividualPanel();
            resetBulkPanel();
        });

        /* ------------------------------------------------------------------
           Tab switch – clean the panel that is about to be shown
           ------------------------------------------------------------------ */
        $('#descgpt-tab-individual').on('click', function () {
            resetIndividualPanel();
        });

        $('#descgpt-tab-bulk').on('click', function () {
            resetBulkPanel();
        });
    });

    $(document).on('input', '#descgpt-bulk-accordion textarea', function () {
        const $txt = $(this);
        const type = $('#descgpt-content-type').val();
        const enable = $('#descgpt-enable-ai').is(':checked');
        const $item = $txt.closest('[data-item-id]');
        const id = $item.data('item-id');
        const content = $txt.val();

        if (!content || !id) return;

        // ---- 1. live stats -------------------------------------------------
        updateBulkContentStats($txt);

        // ---- 2. auto-save --------------------------------------------------
        $.post(descgptwSettings.ajaxurl, {
            action: 'descgpt_save_to_item',
            type: type,
            ids: [id],
            content: content,
            language: descgptwSettings.language || 'English',
            enable: enable ? 1 : 0,
            nonce: descgptwSettings.nonce
        }, function (res) {
            if (res.success) {
                showToast(`Content auto-saved for ID ${id}!`);
                fetchLastGenerated();
            } else {
                showToast(`Failed to auto-save ID ${id}.`, true);
            }
        });
    });

    // Bulk generation
    function generateBulk(regenerate = false) {
        var type = $('#descgpt-content-type').val();
        var limitType = $('#descgpt-limit-type').val();
        var limitValue = $('#descgpt-limit-value').val();

        // Validation
        if (!type) {
            showToast('Please select a content type.', true);
            return;
        }
        if (!limitValue || limitValue < 50 || limitValue > 1000) {
            showToast('Please enter a limit value between 50 and 1000.', true);
            return;
        }
        if (!$('#descgpt-enable-products').is(':checked') && type === 'product') {
            showToast('AI for products is disabled.', true);
            return;
        }
        if (!$('#descgpt-enable-taxonomies').is(':checked') && type !== 'product') {
            showToast('AI for taxonomies is disabled.', true);
            return;
        }

        lastOutputTokens = 0;

        $('#descgpt-loading-spinner-bulk').removeClass('hidden');
        $('#descgpt-generate-bulk-btn, #descgpt-regenerate-bulk-btn').addClass('processing').prop('disabled', true);
        $('#descgpt-cancel-bulk-btn').removeClass('hidden');
        $('#descgpt-bulk-log').removeClass('hidden').find('#descgpt-bulk-status').text('Processing...');
        $('#descgpt-bulk-list').empty();
        $('#descgpt-bulk-accordion').empty().addClass('hidden');
        $('#descgpt-save-bulk-btn').addClass('hidden');

        if (currentBulkRequest) currentBulkRequest.abort();

        currentBulkRequest = $.ajax({
            url: descgptwSettings.ajaxurl,
            type: 'POST',
            data: {
                action: 'descgpt_generate_description',
                type: type,
                limit_type: limitType,
                limit_value: limitValue,
                bulk: 1,
                regenerate: regenerate ? 1 : 0,
                nonce: descgptwSettings.nonce
            },
            success: function (res) {

                finishBulkRequest();

                $('#descgpt-loading-spinner-bulk').addClass('hidden');
                $('#descgpt-generate-bulk-btn, #descgpt-regenerate-bulk-btn').removeClass('processing').prop('disabled', false);

                if (res.success) {
                    $('#descgpt-bulk-status').text('Bulk generation complete.');

                    if (res.data.summary) {
                        res.data.summary.forEach(function (item) {
                            $('#descgpt-bulk-list').append('<li>' + item + '</li>');
                        });
                    }

                    if (res.data.content && res.data.content.length > 0) {

                        const type = $('#descgpt-content-type').val();               // ← needed for panel map
                        let descType = '';
                        if (type === 'category') descType = 'Category Description';
                        else if (type === 'tag') descType = 'Tag Description';
                        else if (type === 'brand') descType = 'Brand Description';
                        else descType = 'Product Description';

                        let accordionHtml = '';
                        res.data.content.forEach(function (item, idx) {
                            let content = '';
                            if (type === 'category') content = item.parsed_content.category_description || '';
                            else if (type === 'tag') content = item.parsed_content.tag_description || '';
                            else if (type === 'brand') content = item.parsed_content.brand_description || '';
                            else content = (item.parsed_content.short_description || '') + '\n\n' +
                                (item.parsed_content.full_description || '');

                            // Strip a possible "Category Description:" header that the model sometimes adds
                            content = content.replace(new RegExp('^' + descType.replace(/\s/g, '') + ':', 'i'), '').trim();

                            const panelId = `bulk-accordion-${item.id}`;
                            accordionHtml += `
                            <div data-item-id="${item.id}">
                                <h3 id="${panelId}-heading" class="bg-gray-100 rounded-lg shadow p-3 cursor-pointer">
                                    <button type="button"
                                            class="flex items-center justify-between w-full font-medium text-gray-700"
                                            data-accordion-target="#${panelId}-body"
                                            aria-expanded="false"
                                            aria-controls="${panelId}-body">
                                        <span>${descType} for ${item.name} (ID: ${item.id})</span>
                                        <svg class="w-4 h-4 transform transition-transform duration-200" aria-hidden="true" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
                                        </svg>
                                    </button>
                                </h3>

                                <div id="${panelId}-body" class="hidden" aria-labelledby="${panelId}-heading">
                                    <div class="p-3 border border-t-0 border-gray-200 rounded-b-lg bulk-item-container">
                                        <textarea class="w-full p-2 border rounded-lg focus:ring-2 focus:ring-blue-500 bulk-textarea" rows="4" data-output-tokens="${parseInt(item.output_tokens) || 0}">${content}</textarea>
                                    </div>
                                </div>
                            </div>`;
                        });

                        const $accordion = $('#descgpt-bulk-accordion').html(accordionHtml).removeClass('hidden');
                        $('#descgpt-save-bulk-btn').removeClass('hidden');

                        /* --------------------------------------------------------------
                           1. Initialise stats for every textarea (first render)
                           -------------------------------------------------------------- */
                        $accordion.find('.bulk-textarea').each(function () {
                            const $textarea = $(this);
                            const realTokens = parseInt($textarea.data('output-tokens')) || 0;
                            const prev = lastOutputTokens;
                            lastOutputTokens = realTokens;
                            updateBulkContentStats($textarea);
                            lastOutputTokens = prev;
                        });

                        /* --------------------------------------------------------------
                           2. Auto-open the **first** item and scroll to it
                           -------------------------------------------------------------- */
                        const firstPanel = $accordion.find('> div').first().find('[data-accordion-target]').attr('data-accordion-target');
                        if (firstPanel) {
                            $(firstPanel).removeClass('hidden');
                            $('html, body').animate({
                                scrollTop: $(firstPanel).offset().top - 120
                            }, 600);
                        }

                        /* --------------------------------------------------------------
                           3. Accordion toggle (same as you already had)
                           -------------------------------------------------------------- */
                        $accordion.off('click', 'button[data-accordion-target]')
                            .on('click', 'button[data-accordion-target]', function () {
                                const target = $(this).attr('data-accordion-target');
                                const $body = $(target);
                                const expanded = $(this).attr('aria-expanded') === 'true';
                                $body.toggleClass('hidden');
                                $(this).attr('aria-expanded', !expanded);
                                $(this).closest('h3').toggleClass('active');
                            });

                        showToast('Bulk generation completed successfully!');
                        fetchLastGenerated();
                    } else {
                        resetBulkPanel();
                        showToast('No new content generated. All items may have existing content or were skipped. Try regenerating.', true);
                        $('#descgpt-bulk-status').text('No new content generated.');
                    }
                } else {
                    showToast('Failed to generate bulk content: ' + (res.data || 'Unknown error'), true);
                    $('#descgpt-bulk-status').text('Failed to process: ' + (res.data || 'Unknown error'));
                }
            },
            error: function (xhr, status, error) {
                finishBulkRequest();

                if (xhr.statusText !== 'abort') {
                    const err = xhr.responseJSON && xhr.responseJSON.data
                        ? xhr.responseJSON.data
                        : 'AJAX request failed: ' + error;
                    showToast('Failed to generate bulk content: ' + err, true);
                    $('#descgpt-bulk-status').text('Failed: ' + err);
                }
            }
        });
    }

    function finishBulkRequest() {
        $('#descgpt-loading-spinner-bulk').addClass('hidden');
        $('#descgpt-generate-bulk-btn, #descgpt-regenerate-bulk-btn')
            .removeClass('processing').prop('disabled', false);
        $('#descgpt-cancel-bulk-btn').addClass('hidden');
        currentBulkRequest = null;
    }

    $('#descgpt-cancel-bulk-btn').on('click', function () {
        if (currentBulkRequest) {
            currentBulkRequest.abort();
            showToast('Bulk generation cancelled', true);
        }
    });

    function estimateTokens(text) {
        if (!text) return 0;

        // Clean and normalize exactly like OpenAI does.
        const cleaned = text
            .replace(/\n+/g, '\n')     // collapse multiple newlines.
            .replace(/\s+/g, ' ')      // collapse spaces.
            .trim();

        const chars = cleaned.length;
        const words = (cleaned.match(/\b\w+\b/g) || []).length;

        // Within ±3% of real cl100k_base tokenizer.
        return Math.round(chars / 4.0 + words * 0.05);
    }

    // Bulk content stats count.
    function updateBulkContentStats($textarea) {
        const limitType = $('#descgpt-limit-type').val();
        const limitValue = parseInt($('#descgpt-limit-value').val()) || 0;

        const content = ($textarea.val() || '').toString().trim();
        let count = 0;
        let unit = 'Words';
        let isEstimate = false;

        // Accurate token estimation function
        function estimateTokens(text) {
            if (!text) return 0;
            const cleaned = text.replace(/\s+/g, ' ').trim();
            const chars = cleaned.length;
            const words = (cleaned.match(/\b\w+\b/g) || []).length;
            const lines = (cleaned.match(/\n/g) || []).length;
            return Math.ceil(chars / 3.95 + words * 0.25 + lines * 0.5);
        }

        if (limitType === 'words') {
            const words = content.match(/\b[\w’'-]+\b/g) || [];
            count = words.length;
            unit = 'Words';
        }
        else if (limitType === 'tokens') {
            if (lastOutputTokens > 0) {
                count = lastOutputTokens;
            } else if (content.length > 0) {
                count = estimateTokens(content);
                isEstimate = true;
            }
            unit = 'Tokens';
        }

        const ratio = limitValue > 0 ? count / limitValue : 0;
        let color = 'text-green-600';

        if (ratio < 0.7 || ratio > 1.0) {
            color = 'text-yellow-600';
        }

        const displayCount = isEstimate ? '~' + count : count;

        let $container = $textarea.closest('.p-3.border');
        if (!$container.length) $container = $textarea.parent();

        let $stats = $container.find('.bulk-stats');
        if (!$stats.length) {
            $stats = $('<p class="bulk-stats text-xs mt-2 text-right opacity-80"></p>');
            $container.append($stats);
        }

        $stats.html(`
        ${unit}: 
        <span class="${color} font-semibold ${isEstimate ? 'italic' : ''}" 
              title="${isEstimate ? 'Estimated (real count after generation)' : 'Exact from OpenAI'}">
            ${displayCount}
        </span> 
        / ${limitValue}
    `);

        $stats.find('span').toggleClass('opacity-70', isEstimate);
    }

    $('#descgpt-generate-bulk-btn').on('click', function () {
        $(this).addClass('processing').prop('disabled', true);
        generateBulk(false);
    });
    $('#descgpt-regenerate-bulk-btn').on('click', function () {
        $(this).addClass('processing').prop('disabled', true);
        generateBulk(true);
    });

    // Save bulk content to items
    $('#descgpt-save-bulk-btn').on('click', function () {
        const type = $('#descgpt-content-type').val();
        const enable = $('#descgpt-enable-ai').is(':checked');
        const $items = $('#descgpt-bulk-accordion > div');

        if (!$items.length) {
            showToast('No items to save.', true);
            return;
        }

        if (!confirm('Are you sure you want to save the generated content for all items? This will overwrite existing descriptions.')) {
            return;
        }

        const btn = $(this);
        btn.addClass('processing').prop('disabled', true).text('Saving...');

        let saveCount = 0;
        const total = $items.length;

        $items.each(function () {
            const $item = $(this);
            const id = $item.data('item-id');
            const $textarea = $item.find('textarea');
            const content = $textarea.val().trim();

            if (!content) {
                saveCount++;
                if (saveCount === total) finish();
                return;
            }

            // No header prefix — send clean content
            $.post(descgptwSettings.ajaxurl, {
                action: 'descgpt_save_to_item',
                type: type,
                ids: [id],
                content: content,  // Clean content only
                language: descgptwSettings.language || 'English',
                enable: enable ? 1 : 0,
                nonce: descgptwSettings.nonce
            }, function (res) {
                saveCount++;
                if (!res.success) {
                    showToast(`Failed to save ID ${id}: ${res.data || 'Error'}`, true);
                }
                if (saveCount === total) finish();
            }).fail(function (xhr) {
                saveCount++;
                const msg = xhr.responseJSON?.data || 'Network error';
                showToast(`Failed to save ID ${id}: ${msg}`, true);
                if (saveCount === total) finish();
            });
        });

        function finish() {
            btn.removeClass('processing').prop('disabled', false).text('Save to Items');
            showToast(`Bulk save complete: ${total} item(s) processed.`);
            fetchLastGenerated();
        }
    });

});