jQuery(document).ready(function($) {
    const adminLang = BizmartSettingsData.adminLang;
    const ajaxNonce = BizmartSettingsData.ajaxNonce;
    const ajaxUrl = BizmartSettingsData.ajaxUrl;
    const bizDetectedMetaKeys = BizmartSettingsData.bizDetectedMetaKeys;
    const editPostUrlBase = BizmartSettingsData.editPostUrlBase;
    const t = (en, fr, ar) => {
        if (adminLang === 'ar') {
            const dict = (window.BizmartI18n && BizmartI18n.ar) ? BizmartI18n.ar : null;
            return ar || (dict && dict[en]) || en;
        }
        return adminLang === 'fr' ? fr : en;
    };

    // Media Uploader for Logo
    (function($){
        var image_frame = null;
        $('#upload-logo-btn').on('click', function(e){
            e.preventDefault();
            if (typeof wp === 'undefined' || !wp.media) {
                alert('Media uploader is not available. Please refresh the page.');
                return;
            }
            if (image_frame) {
                image_frame.open();
                return;
            }
            image_frame = wp.media({
                title: t('Select or upload a logo', 'Selectionner ou telecharger un logo'),
                multiple: false,
                library: { type: 'image' }
            });

            // When media modal opens, hide/disable the floating save so it doesn't cover modal controls
            image_frame.on('open', function(){
                try { $('.biz-save-float').addClass('biz-media-open').hide(); } catch(e){}
            });

            image_frame.on('close', function(){
                try { $('.biz-save-float').removeClass('biz-media-open').show(); } catch(e){}
            });

            image_frame.on('select', function(){
                var attachment = image_frame.state().get('selection').first().toJSON();
                $('#logo-url-input').val(attachment.url);
                $('#logo-preview-img').attr('src', attachment.url).show();
                // close the modal after selecting to ensure clean state
                try { image_frame.close(); } catch(e){}
            });

            image_frame.open();
        });

        // Media Uploader for Login Logo
        var login_logo_frame = null;
        $('#upload-login-logo-btn').on('click', function(e){
            e.preventDefault();
            if (typeof wp === 'undefined' || !wp.media) {
                alert('Media uploader is not available. Please refresh the page.');
                return;
            }
            if (login_logo_frame) {
                login_logo_frame.open();
                return;
            }
            login_logo_frame = wp.media({
                title: t('Select or upload a login logo', 'Selectionner ou telecharger un logo de connexion'),
                multiple: false,
                library: { type: 'image' }
            });
            login_logo_frame.on('open', function(){
                try { $('.biz-save-float').addClass('biz-media-open').hide(); } catch(e){}
            });
            login_logo_frame.on('close', function(){
                try { $('.biz-save-float').removeClass('biz-media-open').show(); } catch(e){}
            });
            login_logo_frame.on('select', function(){
                var attachment = login_logo_frame.state().get('selection').first().toJSON();
                $('#login-logo-url-input').val(attachment.url);
                $('#login-logo-preview-img').attr('src', attachment.url).show();
                $('#remove-login-logo-btn').css('display', 'inline-flex');
                try { login_logo_frame.close(); } catch(e){}
            });
            login_logo_frame.open();
        });
        $('#remove-login-logo-btn').on('click', function(e){
            e.preventDefault();
            $('#login-logo-url-input').val('');
            $('#login-logo-preview-img').attr('src', '').hide();
            $(this).hide();
        });

        // Media Uploader for Login Background
        var login_bg_frame = null;
        $('#upload-login-bg-btn').on('click', function(e){
            e.preventDefault();
            if (typeof wp === 'undefined' || !wp.media) {
                alert('Media uploader is not available. Please refresh the page.');
                return;
            }
            if (login_bg_frame) {
                login_bg_frame.open();
                return;
            }
            login_bg_frame = wp.media({
                title: t('Select or upload a login background image', 'Selectionner ou telecharger une image de fond'),
                multiple: false,
                library: { type: 'image' }
            });
            login_bg_frame.on('open', function(){
                try { $('.biz-save-float').addClass('biz-media-open').hide(); } catch(e){}
            });
            login_bg_frame.on('close', function(){
                try { $('.biz-save-float').removeClass('biz-media-open').show(); } catch(e){}
            });
            login_bg_frame.on('select', function(){
                var attachment = login_bg_frame.state().get('selection').first().toJSON();
                $('#login-bg-url-input').val(attachment.url);
                $('#login-bg-preview-img').attr('src', attachment.url).show();
                $('#remove-login-bg-btn').css('display', 'inline-flex');
                try { login_bg_frame.close(); } catch(e){}
            });
            login_bg_frame.open();
        });
        $('#remove-login-bg-btn').on('click', function(e){
            e.preventDefault();
            $('#login-bg-url-input').val('');
            $('#login-bg-preview-img').attr('src', '').hide();
            $(this).hide();
        });
    })(jQuery);
    
    // Invoice Prefix Format Builder
    const prefixOutput = document.getElementById('prefix-output');
    const prefixSegmentsContainer = document.getElementById('prefix-segments-container');
    const prefixInput = document.getElementById('invoice-prefix-input');
    const modal = document.getElementById('invoice-preview-modal');

    // Manage segments as an ordered array to append left->right
    let segments = [];
    if (prefixInput && prefixInput.value) {
        segments = prefixInput.value.split('-').filter(s => s.trim());
    }

    function renderSegments() {
        prefixSegmentsContainer.innerHTML = '';
        segments.forEach(seg => {
            const tag = document.createElement('span');
            tag.className = 'prefix-segment-tag';
            let label = seg;
            if (seg === 'INV' || seg === 'INV-') label = 'INV';
            else if (seg === '{SUPPLIER}') label = '{SUPPLIER}';
            else if (seg === '{YYYY}') label = t('{YYYY}', '{AAAA}');
            else if (seg === '{YYMMDD}') label = t('{YYMMDD}', '{AAMMJJ}');
            else if (seg === '{$SEQUENCE}') label = '{$SEQUENCE}';
            tag.textContent = label.replace(/-$/, '');
            tag.title = seg;
            prefixSegmentsContainer.appendChild(tag);
        });
        prefixInput.value = segments.join('-');
        updatePreview();
    }

    function addSegment(segmentId) {
        const map = { 'INV':'INV', 'SUPPLIER':'{SUPPLIER}', 'YEAR':'{YYYY}', 'DATE':'{YYMMDD}', 'SEQUENCE':'{$SEQUENCE}' };
        const token = map[segmentId];
        if (!token) return;

        // Ensure only one sequence and that it's always at the end
        const hadSequence = segments.includes('{$SEQUENCE}');
        if (hadSequence) segments = segments.filter(s => s !== '{$SEQUENCE}');

        // Prevent duplicate non-sequence tokens
        if (token !== '{$SEQUENCE}' && !segments.includes(token)) {
            segments.push(token);
        }

        // If adding sequence, ensure it's last
        if (token === '{$SEQUENCE}') {
            // already removed earlier
            segments.push('{$SEQUENCE}');
        } else if (hadSequence) {
            segments.push('{$SEQUENCE}');
        }

        renderSegments();
    }

    function getPreviewNumber() {
        if (!segments || segments.length === 0) return '';
        const parts = segments.map(s => {
            if (s === 'INV') return 'INV';
            if (s === '{SUPPLIER}') return 'SUP01';
            if (s === '{YYYY}') return new Date().getFullYear();
            if (s === '{YYMMDD}') return '251209';
            if (s === '{$SEQUENCE}') return '00042';
            return s;
        });
        return parts.join('-');
    }

    function updatePreview() {
        prefixOutput.textContent = `${t('Example:', 'Exemple :')} ${getPreviewNumber()}`;
    }

    function showModal() {
        document.getElementById('invoice-number-display').textContent = getPreviewNumber();
        const footerVal = $('#footer-text-input').val();
        document.getElementById('invoice-footer-display').textContent = footerVal && footerVal.trim() ? footerVal : 'Invoice received from (supplier name) by our system Bizmart';
        const companyNameVal = $('#company-name-input').val();
        document.getElementById('invoice-company-name').textContent = companyNameVal || t('Company name', "Nom de l'Entreprise");
        document.getElementById('invoice-company-address').innerHTML = ($('#address-input').val() || t('Address not provided', 'Adresse non renseignee')).replace(/\n/g, '<br>');
        
        const regNumsText = "RC: " + ($('#rc-input').val() || 'N/A') + " | NIF: " + ($('#nif-input').val() || 'N/A') + " | NIS: " + ($('#nis-input').val() || 'N/A');
        document.getElementById('invoice-reg-numbers').textContent = regNumsText;
        
        const logoUrl = $('#logo-url-input').val();
        if (logoUrl) {
            $('#invoice-logo-preview').attr('src', logoUrl).show();
        } else {
            $('#invoice-logo-preview').hide();
        }
        
        // Footer preview fallback uses supplier-centric wording
        modal.style.display = 'flex';
    }

    function closeModal() {
        modal.style.display = 'none';
    }

    $('[data-segment]').on('click', function(e) {
        e.preventDefault();
        addSegment($(this).data('segment'));
    });
    
    $('#preview-test-invoice').on('click', function(e) {
        e.preventDefault();
        showModal();
    });

    $('#close-modal-btn').on('click', closeModal);
    
    $(modal).on('click', function(e) {
        if (e.target === modal) {
            closeModal();
        }
    });

    renderSegments();
    
    // Subcategories Management
    function updateSubcategoriesData() {
        const data = {};
        $('#subcategories-manager > div').each(function() {
            const category = $(this).data('category');
            const subs = [];
            $(this).find('.subcat-item').each(function() {
                const $text = $(this).find('.subcat-text');
                const raw = ($text.data('subcatValue') || '').toString().trim();
                subs.push(raw ? raw : $text.text().trim());
            });
            data[category] = subs;
        });
        $('#biz-subcategories-data').val(JSON.stringify(data));
    }
    
    // Add subcategory
    $(document).on('click', '.add-subcat-btn', function() {
        const category = $(this).data('category');
        const subcatName = prompt(t('Subcategory name:', 'Nom de la sous-categorie:'));
        if (!subcatName || !subcatName.trim()) return;
        
        const $container = $(this).closest('.biz-card').find('.subcategories-list');
        const newItem = `
            <div class="subcat-item" style="display: flex; align-items: center; gap: 8px; background: var(--bg-body); border: 1px solid var(--border-color); border-radius: 20px; padding: 6px 14px;">
                <span class="subcat-text" style="font-size: 13px;" data-subcat-value="${subcatName.trim()}">${subcatName.trim()}</span>
                <button type="button" class="delete-subcat-btn" style="border: none; background: none; color: var(--danger); cursor: pointer; font-size: 18px; line-height: 1;" title="${t('Delete', 'Supprimer')}">
                    <i class="fas fa-times"></i>
                </button>
            </div>
        `;
        $container.append(newItem);
        updateSubcategoriesData();
    });
    
    // Delete subcategory
    $(document).on('click', '.delete-subcat-btn', function() {
        if (confirm(t('Delete this subcategory?', 'Supprimer cette sous-categorie?'))) {
            $(this).closest('.subcat-item').remove();
            updateSubcategoriesData();
        }
    });
    
    // Initial data sync
    updateSubcategoriesData();

    // ----------------------------
    // Import panel actions
    // ----------------------------
    function showImportMessage(msg, type = 'info') {
        const $area = $('#biz-import-status');
        $area.text(msg);
        if (type === 'error') $area.css('color', 'red'); else $area.css('color', '');
    }

    function extractAjaxError(xhr) {
        try {
            const json = xhr && xhr.responseJSON ? xhr.responseJSON : null;
            if (json && json.data) {
                if (typeof json.data === 'string') return json.data;
                if (json.data.message) return json.data.message;
                return JSON.stringify(json.data);
            }
        } catch (e) {}
        const status = xhr && xhr.status ? xhr.status : 0;
        const text = xhr && xhr.responseText ? xhr.responseText : '';
        const snippet = text && text.length > 300 ? (text.substring(0, 300) + '...') : text;
        return (status ? ('HTTP ' + status + ': ') : '') + (snippet || 'Request failed');
    }

    function normalizeErrorData(data) {
        if (!data) return 'Error';
        if (typeof data === 'string') return data;
        if (data.message) return data.message;
        try { return JSON.stringify(data); } catch (e) { return 'Error'; }
    }

    window.bizSubmitDemoDataAction = function(action, button, confirmMessage) {
        const form = document.getElementById('biz-modern-form');
        if (!form || !action) return;
        if (confirmMessage && !window.confirm(confirmMessage)) return;

        const saveInput = document.getElementById('biz_save_settings_input');
        if (saveInput && saveInput.parentNode) {
            saveInput.parentNode.removeChild(saveInput);
        }

        let hiddenAction = document.getElementById('biz_demo_data_action_input');
        if (!hiddenAction) {
            hiddenAction = document.createElement('input');
            hiddenAction.type = 'hidden';
            hiddenAction.name = 'biz_demo_data_action';
            hiddenAction.id = 'biz_demo_data_action_input';
            form.appendChild(hiddenAction);
        }
        hiddenAction.value = action;

        const status = document.getElementById('biz-demo-data-inline-status');
        if (status) {
            status.textContent = action === 'cleanup' ? 'Deleting demo data...' : 'Importing demo data...';
        }

        ['biz-demo-import-btn', 'biz-demo-cleanup-btn'].forEach(function(id) {
            const node = document.getElementById(id);
            if (node) node.disabled = true;
        });

        form.submit();
    };

    function renderConflicts(job) {
        const conflicts = job && Array.isArray(job.conflicts) ? job.conflicts : [];
        const $area = $('#biz-import-conflicts-area');
        const $tbody = $('#biz-import-conflicts-body');
        $tbody.empty();

        if (!conflicts.length) {
            $area.hide();
            return;
        }

        conflicts.forEach(function(c) {
            const pid = c && c.id ? parseInt(c.id, 10) : 0;
            if (!pid) return;

            const title = (c.title || '').toString();
            const sku = (c.sku || '').toString();
            const type = (c.type || '').toString();
            const existing = (c.existing !== undefined && c.existing !== null) ? String(c.existing) : '';
            const source = (c.source !== undefined && c.source !== null) ? String(c.source) : ((c.source_normalized !== undefined && c.source_normalized !== null) ? String(c.source_normalized) : '');
            const selling = (c.selling !== undefined && c.selling !== null) ? String(c.selling) : '';
            const editUrl = (c.edit_url || (editPostUrlBase + '?post=' + pid + '&action=edit'));

            const label = title ? (title + ' (#' + pid + ')') : ('#' + pid);
            const row = `
                <tr class="border-b border-gray-100 text-sm">
                    <td class="py-2 px-3">
                        <div style="font-weight:600;"><a href="${editUrl}" target="_blank" rel="noopener">${$('<div/>').text(label).html()}</a></div>
                        <div style="font-size:12px;color:#6b7280;">${$('<div/>').text(type || '').html()}</div>
                    </td>
                    <td class="py-2 px-3">${$('<div/>').text(sku).html()}</td>
                    <td class="py-2 px-3">${$('<div/>').text(existing).html()}</td>
                    <td class="py-2 px-3">${$('<div/>').text(source).html()}</td>
                    <td class="py-2 px-3">${$('<div/>').text(selling).html()}</td>
                    <td class="py-2 px-3">
                        <label style="margin-right:10px;"><input type="radio" name="decision_${pid}" value="replace"> Replace</label>
                        <label><input type="radio" name="decision_${pid}" value="skip"> Skip</label>
                    </td>
                </tr>
            `;
            $tbody.append(row);
        });

        $area.show();
    }

    function renderPreview(job) {
        const items = job && Array.isArray(job.processed_preview) ? job.processed_preview : [];
        const $area = $('#biz-import-preview-area');
        const $tbody = $('#biz-import-preview-body');
        $tbody.empty();

        if (!items.length) {
            $area.hide();
            return;
        }

        // Show last 50 entries (already capped server-side but keep UI light)
        const slice = items.slice(Math.max(0, items.length - 50));
        slice.forEach(function(it) {
            const pid = it && it.id ? parseInt(it.id, 10) : 0;
            if (!pid) return;
            const title = (it.title || '').toString();
            const sku = (it.sku || '').toString();
            const type = (it.type || '').toString();
            const purchase = (it.purchase !== undefined && it.purchase !== null) ? String(it.purchase) : '';
            const existing = (it.prev_purchase !== undefined && it.prev_purchase !== null) ? String(it.prev_purchase) : ((it.existing_purchase !== undefined && it.existing_purchase !== null) ? String(it.existing_purchase) : '');
            const selling = (it.selling !== undefined && it.selling !== null) ? String(it.selling) : '';
            const action = (it.action || '').toString();
            const editUrl = (it.edit_url || (editPostUrlBase + '?post=' + pid + '&action=edit'));

            const label = title ? (title + ' (#' + pid + ')') : ('#' + pid);
            const badge = action ? `<span style="display:inline-block;padding:2px 8px;border-radius:999px;background:#eef2ff;color:#3730a3;font-size:12px;font-weight:600;">${$('<div/>').text(action).html()}</span>` : '';
            const row = `
                <tr class="border-b border-gray-100 text-sm">
                    <td class="py-2 px-3"><a href="${editUrl}" target="_blank" rel="noopener">${$('<div/>').text(label).html()}</a></td>
                    <td class="py-2 px-3">${$('<div/>').text(sku).html()}</td>
                    <td class="py-2 px-3">${$('<div/>').text(type).html()}</td>
                    <td class="py-2 px-3">${$('<div/>').text(purchase).html()}</td>
                    <td class="py-2 px-3">${$('<div/>').text(existing).html()}</td>
                    <td class="py-2 px-3">${$('<div/>').text(selling).html()}</td>
                    <td class="py-2 px-3">${badge}</td>
                </tr>
            `;
            $tbody.append(row);
        });

        $area.show();
    }

    function biz_get_count() {
        const meta = $('#import-meta-key').val() || '';
        if (!meta) { showImportMessage('Please enter a meta key', 'error'); return; }
        showImportMessage('Checking...');
        $.post(ajaxUrl, { action: 'bizmart_final_import_get_count', meta_key: meta, nonce: ajaxNonce }, function(r){
            if (!r || !r.success) { showImportMessage(normalizeErrorData(r && r.data), 'error'); return; }
            const d = r.data;
            const usedKey = d && d.used_meta_key ? (' Used key: ' + d.used_meta_key + '.') : '';
            showImportMessage('Found: ' + d.total_non_empty + ' (products: ' + d.products + ', variations: ' + d.variations + '). Total exists: ' + d.total_exists + '.' + usedKey);

            // Also fetch a sample list of matching products to make this useful.
            biz_preview_items(meta);
        }).fail(function(xhr){ showImportMessage(extractAjaxError(xhr), 'error'); });
    }

    function renderAvailableItems(payload) {
        const $area = $('#biz-import-available-area');
        const $tbody = $('#biz-import-available-body');
        const $note = $('#biz-import-available-note');
        $tbody.empty();

        const usedKey = payload && payload.used_meta_key ? payload.used_meta_key : '';
        const items = payload && Array.isArray(payload.items) ? payload.items : [];
        const limit = payload && payload.limit ? payload.limit : items.length;

        if (!items.length) {
            $area.hide();
            return;
        }

        $note.text('Showing ' + items.length + ' sample items (limit ' + limit + '). ' + (usedKey ? ('Used key: ' + usedKey) : ''));

        items.forEach(function(it){
            const pid = it && it.id ? parseInt(it.id, 10) : 0;
            if (!pid) return;
            const title = (it.title || '').toString();
            const sku = (it.sku || '').toString();
            const type = (it.type || '').toString();
            const raw = (it.source_raw !== undefined && it.source_raw !== null) ? String(it.source_raw) : '';
            const norm = (it.source_normalized !== undefined && it.source_normalized !== null) ? String(it.source_normalized) : '';
            const existing = (it.existing_purchase !== undefined && it.existing_purchase !== null) ? String(it.existing_purchase) : '';
            const selling = (it.selling !== undefined && it.selling !== null) ? String(it.selling) : '';
            const editUrl = (it.edit_url || (editPostUrlBase + '?post=' + pid + '&action=edit'));
            const label = title ? (title + ' (#' + pid + ')') : ('#' + pid);

            const row = `
                <tr class="border-b border-gray-100 text-sm">
                    <td class="py-2 px-3"><a href="${editUrl}" target="_blank" rel="noopener">${$('<div/>').text(label).html()}</a></td>
                    <td class="py-2 px-3">${$('<div/>').text(sku).html()}</td>
                    <td class="py-2 px-3">${$('<div/>').text(type).html()}</td>
                    <td class="py-2 px-3">${$('<div/>').text(raw).html()}</td>
                    <td class="py-2 px-3">${$('<div/>').text(norm).html()}</td>
                    <td class="py-2 px-3">${$('<div/>').text(existing).html()}</td>
                    <td class="py-2 px-3">${$('<div/>').text(selling).html()}</td>
                </tr>
            `;
            $tbody.append(row);
        });

        $area.show();
        applyAvailableFilter();
    }

    function applyAvailableFilter() {
        const q = ($('#biz-import-available-filter').val() || '').toString().trim().toLowerCase();
        const $rows = $('#biz-import-available-body tr');
        if (!q) { $rows.show(); return; }
        $rows.each(function(){
            const text = $(this).text().toLowerCase();
            $(this).toggle(text.indexOf(q) !== -1);
        });
    }

    $('#biz-import-available-filter').on('input', function(){ applyAvailableFilter(); });

    function biz_preview_items(meta) {
        meta = (meta || $('#import-meta-key').val() || '').toString();
        if (!meta) return;
        $.post(ajaxUrl, { action: 'bizmart_final_import_preview_items', meta_key: meta, limit: 30, nonce: ajaxNonce }, function(r){
            if (!r || !r.success) {
                $('#biz-import-available-area').hide();
                return;
            }
            renderAvailableItems(r.data);
        }).fail(function(){ $('#biz-import-available-area').hide(); });
    }

    function renderImportSummary(job) {
        const $wrap = $('#biz-import-summary');
        const $txt = $('#biz-import-summary-text');
        const $bar = $('#biz-import-progress-bar');
        const $pct = $('#biz-import-progress-left');
        const $frac = $('#biz-import-progress-right');

        if (!job) { $wrap.hide(); return; }
        const total = parseInt(job.total || 0, 10) || 0;
        const offset = parseInt(job.offset || 0, 10) || 0;
        const processed = parseInt(job.processed || 0, 10) || 0;
        const replaced = parseInt(job.replaced || 0, 10) || 0;
        const skipped = parseInt(job.skipped || 0, 10) || 0;
        const status = (job.status || 'unknown').toString();
        const dry = job.dry_run ? ' (dry-run)' : '';
        const pct = total > 0 ? Math.min(100, Math.round((offset / total) * 100)) : 0;

        $txt.text('Status: ' + status + dry + ' - processed: ' + processed + ', replaced: ' + replaced + ', skipped: ' + skipped);
        $bar.css('width', pct + '%');
        $pct.text(pct + '%');
        $frac.text(offset + ' / ' + total);
        $wrap.show();
    }

    const bizImportProgressState = {
        signature: '',
        stagnantPolls: 0,
        recoveryAttempts: 0,
    };

    function resetImportProgressState() {
        bizImportProgressState.signature = '';
        bizImportProgressState.stagnantPolls = 0;
        bizImportProgressState.recoveryAttempts = 0;
        window._biz_import_recovery_inflight = false;
    }

    function renderImportJob(job, customMessage) {
        if (!job) {
            resetImportProgressState();
            showImportMessage('No active job');
            renderImportSummary(null);
            biz_preview_items($('#import-meta-key').val() || '');
            $('#biz-import-json').val('');
            renderPreview(null);
            renderConflicts(null);
            $('#biz-import-resume-area').hide();
            return;
        }

        const status = (job.status || 'unknown').toString();
        let message = customMessage || ('Status: ' + status + ' - processed: ' + (job.processed || 0) + ' / ' + (job.total || 0));
        if (!customMessage && status === 'paused_for_confirmation') {
            message = 'Import paused. Review the conflicts below and choose how to continue.';
        } else if (!customMessage && status === 'completed') {
            message = 'Import completed successfully.';
        } else if (!customMessage && status === 'cancelled') {
            message = 'Import cancelled.';
        }

        $('#biz-import-json').val(JSON.stringify(job, null, 2));
        showImportMessage(message, status === 'cancelled' ? 'error' : 'info');
        renderImportSummary(job);
        biz_preview_items($('#import-meta-key').val() || (job.meta_key || ''));
        renderPreview(job);
        renderConflicts(job);
        $('#biz-import-resume-area').toggle(status === 'paused_for_confirmation');
    }

    function maybeRecoverStalledImport(job, interval) {
        const status = (job && job.status ? String(job.status) : '');
        if (['pending', 'running'].indexOf(status) === -1) {
            resetImportProgressState();
            return false;
        }

        const signature = [
            status,
            parseInt(job.offset || 0, 10) || 0,
            parseInt(job.processed || 0, 10) || 0,
            parseInt(job.replaced || 0, 10) || 0,
            parseInt(job.skipped || 0, 10) || 0,
            (job.updated_at || '').toString()
        ].join('|');

        if (bizImportProgressState.signature === signature) {
            bizImportProgressState.stagnantPolls += 1;
        } else {
            bizImportProgressState.signature = signature;
            bizImportProgressState.stagnantPolls = 0;
            bizImportProgressState.recoveryAttempts = 0;
        }

        if (bizImportProgressState.stagnantPolls < 2 || window._biz_import_recovery_inflight || bizImportProgressState.recoveryAttempts >= 3) {
            return false;
        }

        window._biz_import_recovery_inflight = true;
        bizImportProgressState.recoveryAttempts += 1;
        showImportMessage('Import looks stalled. Nudging the next batch...');

        $.post(ajaxUrl, { action: 'bizmart_final_run_import_batch_now', nonce: ajaxNonce }, function(r) {
            if (r && r.success) {
                renderImportJob(r.data, 'Recovery batch executed. Checking progress...');
            } else {
                showImportMessage(normalizeErrorData(r && r.data), 'error');
            }
        }).fail(function(xhr) {
            showImportMessage(extractAjaxError(xhr), 'error');
        }).always(function() {
            window._biz_import_recovery_inflight = false;
            window._biz_import_poll = setTimeout(function(){ pollImportStatus(interval); }, Math.max(1000, interval));
        });

        return true;
    }

    function biz_start_import() {
        const meta = $('#import-meta-key').val() || '';
        const policy = $('#import-policy').val() || 'prompt';
        if (!meta) { showImportMessage('Please enter a meta key', 'error'); return; }
        showImportMessage('Starting import...');
        $.post(ajaxUrl, { action: 'bizmart_final_start_import_job', meta_key: meta, policy: policy, nonce: ajaxNonce }, function(r){
            if (!r || !r.success) { showImportMessage(normalizeErrorData(r && r.data), 'error'); return; }
            resetImportProgressState();
            renderImportJob(r.data, (r.data && r.data.status === 'paused_for_confirmation')
                ? 'Import paused immediately because existing purchase prices need your decision.'
                : 'Import started - it will continue in the background even if you leave this page.');
            if (r.data && r.data.status && ['completed', 'cancelled'].indexOf(r.data.status) === -1) {
                pollImportStatus();
            }
        }).fail(function(xhr){
            const json = xhr && xhr.responseJSON ? xhr.responseJSON : null;
            const data = json && json.data ? json.data : null;
            if (data && data.job) {
                renderImportJob(data.job, normalizeErrorData(data));
                if (data.job.status && ['completed', 'cancelled'].indexOf(data.job.status) === -1) {
                    pollImportStatus();
                }
                return;
            }
            showImportMessage(extractAjaxError(xhr), 'error');
        });
    }

    function pollImportStatus(interval = 1500) {
        clearTimeout(window._biz_import_poll);
        $.post(ajaxUrl, { action: 'bizmart_final_get_import_job_status', nonce: ajaxNonce }, function(r){
            if (!r || !r.success) {
                renderImportJob(null);
                return;
            }
            const job = r.data;
            renderImportJob(job);

            if (job && maybeRecoverStalledImport(job, interval)) {
                return;
            }

            if (job.status && ['completed','cancelled'].indexOf(job.status) === -1) {
                window._biz_import_poll = setTimeout(function(){ pollImportStatus(interval); }, interval);
            }
        }).fail(function(xhr){ showImportMessage(extractAjaxError(xhr), 'error'); });
    }

    function biz_resume_import(action_choice, decisions) {
        const data = { action: 'bizmart_final_resume_import_job', action_choice: action_choice, nonce: ajaxNonce };
        if (decisions) data.decisions = JSON.stringify(decisions);
        $.post(ajaxUrl, data, function(r){
            if (!r || !r.success) { showImportMessage(normalizeErrorData(r && r.data), 'error'); return; }
            showImportMessage('Resumed. Polling...');
            pollImportStatus();
        }).fail(function(xhr){ showImportMessage(extractAjaxError(xhr), 'error'); });
    }

    // Cancel import UI removed; cancellation is not exposed to admins via the settings UI.

    /* Cleanup (delete source meta) client helpers */
    function renderCleanupSummary(job) {
        const $wrap = $('#biz-cleanup-summary');
        if (!job) { $wrap.hide(); return; }
        const total = parseInt(job.total || 0, 10) || 0;
        const offset = parseInt(job.offset || 0, 10) || 0;
        const processed = parseInt(job.processed || 0, 10) || 0;
        const status = (job.status || 'unknown').toString();
        const pct = total > 0 ? Math.min(100, Math.round((offset / total) * 100)) : 0;
        $('#biz-cleanup-status').text('Status: ' + status + ' - processed: ' + processed);
        $('#biz-cleanup-progress-bar').css('width', pct + '%');
        $('#biz-cleanup-pct').text(pct + '%');
        $('#biz-cleanup-fraction').text(offset + ' / ' + total);
        $wrap.show();
    }

    function biz_start_cleanup() {
        const meta = $('#import-meta-key').val() || '';
        if (!meta) { alert('Please enter a meta key to delete.'); return; }
        if (!confirm('Are you sure? This will permanently delete the chosen meta values for all products.')) return;
        $.post(ajaxUrl, { action: 'bizmart_final_start_cleanup_job', meta_key: meta, nonce: ajaxNonce }, function(r){
            if (!r || !r.success) { alert('Failed to start cleanup: ' + JSON.stringify(r && r.data)); return; }
            renderCleanupSummary(r.data);
            pollCleanupStatus();
        }).fail(function(xhr){ alert('Cleanup start failed: ' + extractAjaxError(xhr)); });
    }

    function downloadCsv(filename, text) {
        const blob = new Blob([text], { type: 'text/csv;charset=utf-8;' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = filename;
        document.body.appendChild(a);
        a.click();
        setTimeout(function(){ document.body.removeChild(a); URL.revokeObjectURL(url); }, 500);
    }

    function exportImportAudit() {
        $.post(ajaxUrl, { action: 'bizmart_final_export_import_audit', nonce: ajaxNonce }, function(r){
            if (!r || !r.success) { alert('No import audit available'); return; }
            const csv = r.data && r.data.csv ? r.data.csv : '';
            if (!csv) { alert('No audit data'); return; }
            downloadCsv('bizmart-import-audit.csv', csv);
        }).fail(function(xhr){ alert('Export failed: ' + extractAjaxError(xhr)); });
    }

    function exportCleanupAudit() {
        $.post(ajaxUrl, { action: 'bizmart_final_export_cleanup_audit', nonce: ajaxNonce }, function(r){
            if (!r || !r.success) { alert('No cleanup audit available'); return; }
            const csv = r.data && r.data.csv ? r.data.csv : '';
            if (!csv) { alert('No audit data'); return; }
            downloadCsv('bizmart-cleanup-audit.csv', csv);
        }).fail(function(xhr){ alert('Export failed: ' + extractAjaxError(xhr)); });
    }

    function pollCleanupStatus(interval = 2000) {
        clearTimeout(window._biz_cleanup_poll);
        $.post(ajaxUrl, { action: 'bizmart_final_get_cleanup_job_status', nonce: ajaxNonce }, function(r){
            if (!r || !r.success) { renderCleanupSummary(null); return; }
            const job = r.data;
            if (!job) { renderCleanupSummary(null); return; }
            renderCleanupSummary(job);
            if (job.status && ['completed','cancelled'].indexOf(job.status) === -1) {
                window._biz_cleanup_poll = setTimeout(function(){ pollCleanupStatus(interval); }, interval);
            }
        }).fail(function(){ renderCleanupSummary(null); });
    }

    // Cancel cleanup UI removed; cancellation not exposed via settings UI.

    // Bind UI
    $('#biz-get-import-count').on('click', function(e){ e.preventDefault(); biz_get_count(); });
    $('#biz-start-import').on('click', function(e){ e.preventDefault(); biz_start_import(); });
    // 'Cancel import' control removed from UI.
    $('#biz-resume-replace-all').on('click', function(e){ e.preventDefault(); biz_resume_import('replace_all'); });
    $('#biz-resume-skip-all').on('click', function(e){ e.preventDefault(); biz_resume_import('skip_all'); });
    $('#biz-start-cleanup').on('click', function(e){ e.preventDefault(); biz_start_cleanup(); });
    // 'Cancel cleanup' control removed from UI.
    $('#biz-export-import-audit').on('click', function(e){ e.preventDefault(); exportImportAudit(); });
    $('#biz-export-cleanup-audit').on('click', function(e){ e.preventDefault(); exportCleanupAudit(); });

    // Auto-resume: if a job is running in the background, show progress immediately
    pollImportStatus(1500);

    // Preset dropdown -> populate meta key
    $('#import-meta-preset').on('change', function() {
        const val = ($(this).val() || '').toString().trim();
        if (!val) return;
        if (val === '_custom') {
            $('#import-meta-key').val('');
            $('#import-meta-key').focus();
            updateDetectedIndicator('');
            return;
        }
        $('#import-meta-key').val(val);
        // Immediately show counts to confirm selection
        updateDetectedIndicator(val);
        biz_get_count();
    });

    // Update detected indicator when typing or selecting
    function updateDetectedIndicator(val) {
        val = (val || '').toString().trim();
        if (!val) { $('#biz-preset-detected-indicator').hide(); return; }
        if (Array.isArray(bizDetectedMetaKeys) && bizDetectedMetaKeys.indexOf(val) !== -1) {
            $('#biz-preset-detected-indicator').show();
        } else {
            $('#biz-preset-detected-indicator').hide();
        }
    }

    $('#import-meta-key').on('input', function() { updateDetectedIndicator($(this).val()); });

    $('#biz-submit-decisions').on('click', function(e){
        e.preventDefault();
        const jobText = $('#biz-import-json').val();
        let job = null;
        try { job = jobText ? JSON.parse(jobText) : null; } catch (err) { job = null; }
        const conflicts = job && Array.isArray(job.conflicts) ? job.conflicts : [];
        if (!conflicts.length) {
            showImportMessage('No conflicts to decide', 'error');
            return;
        }

        const decisions = {};
        conflicts.forEach(function(c) {
            const pid = c && c.id ? parseInt(c.id, 10) : 0;
            if (!pid) return;
            const val = $('input[name="decision_' + pid + '"]:checked').val();
            if (val === 'replace' || val === 'skip') decisions[String(pid)] = val;
        });

        if (Object.keys(decisions).length === 0) {
            showImportMessage('Select Replace/Skip for at least one item', 'error');
            return;
        }
        biz_resume_import('decide', decisions);
    });

    // Modern tab navigation
    jQuery(document).ready(function($) {
        // Tab switching
        $('.biz-nav-item').on('click', function() {
            const section = $(this).data('section');
            
            // Update nav items
            $('.biz-nav-item').removeClass('active');
            $(this).addClass('active');
            
            // Update sections
            $('.biz-section').removeClass('active');
            $('.biz-section[data-section="' + section + '"]').addClass('active');
            
            // Save to localStorage
            localStorage.setItem('bizmart_active_tab', section);
        });
        
        // Restore last tab
        const lastTab = localStorage.getItem('bizmart_active_tab');
        if (lastTab) {
            $('.biz-nav-item[data-section="' + lastTab + '"]').trigger('click');
        }
        
        // Toggle switches: render compact label + accessible toggle
        $('input[type="checkbox"]').each(function() {
            const checkbox = $(this);
            const name = checkbox.attr('name');

            // Skip converting seeder checkboxes and default payment expense setting
            if (name === 'biz_demo_components[]' || name === 'biz_payment_expense_default') {
                return;
            }

            const wrapper = $('<div class="biz-toggle-group"></div>');

            // Ensure the checkbox has an id so the label 'for' attribute can target it
            let cbId = checkbox.attr('id');
            if (!cbId) {
                cbId = 'biz-toggle-' + Math.random().toString(36).slice(2,9);
                checkbox.attr('id', cbId);
            }

            // Find the original label and extract its inner content (icon + text)
            const $originalLabel = checkbox.closest('.biz-field-group, div').find('.biz-field-label, label').first();
            const labelContent = $originalLabel.length ? $originalLabel.html() : checkbox.attr('name') || '';
            $originalLabel.hide(); // hide original to avoid duplicate text

            // Localized short note using admin language
            let noteText = BizmartSettingsData.labels.show_hide_invoice;
            if (name === 'biz_login_brand_enabled') {
                noteText = BizmartSettingsData.labels.enable_disable;
            }

            // Create clickable label element tied to the checkbox (main + note)
            const labelEl = $('<label class="biz-toggle-label" for="' + cbId + '"></label>');
            labelEl.html('<div class="biz-toggle-main">' + labelContent + '</div><div class="biz-toggle-note">' + noteText + '</div>');

            // Build a simple toggle with a knob for animation
            const toggle = $('<div class="biz-toggle" role="switch" aria-checked="' + (checkbox.is(':checked') ? 'true' : 'false') + '"></div>');
            const knob = $('<div class="biz-toggle-knob"></div>');
            toggle.append(knob);
            if (checkbox.is(':checked')) toggle.addClass('on');

            // Interaction: clicking label or toggle toggles the underlying checkbox
            const toggleAction = function() {
                checkbox.prop('checked', !checkbox.is(':checked')).trigger('change');
            };
            toggle.on('click', toggleAction);
            labelEl.on('click', function(e) {
                // allow native label behavior but ensure change event fires
                e.preventDefault();
                toggleAction();
            });

            // Keep toggle state synced when the checkbox value changes programmatically
            checkbox.on('change', function() {
                const on = checkbox.is(':checked');
                toggle.toggleClass('on', on);
                toggle.attr('aria-checked', on ? 'true' : 'false');
            });

            // Render: label then toggle for compact inline look
            wrapper.append(labelEl).append(toggle);
            checkbox.hide().before(wrapper);
        });
    });
});

// v3.0: Valuation radio card styling
(function(){
    function syncValCards() {
        document.querySelectorAll('.biz-val-radio').forEach(function(r) {
            var card = r.closest('label').querySelector('.biz-val-card');
            if (r.checked) {
                card.style.borderColor = 'var(--primary)';
                card.style.background = 'linear-gradient(135deg, #eff6ff, #dbeafe)';
                card.style.boxShadow = '0 0 0 3px rgba(79,70,229,0.15)';
            } else {
                card.style.borderColor = 'var(--gray-200)';
                card.style.background = 'white';
                card.style.boxShadow = 'none';
            }
        });
    }
    document.querySelectorAll('.biz-val-radio').forEach(function(r) {
        r.addEventListener('change', syncValCards);
    });
    syncValCards();
})();
