/*!
 * Yatoon admin — Services screen.
 *
 * 4.6.1 V2: extracted from admin/views/services.php, where it lived as 1280 lines
 * inside a <script> tag. Inline admin JavaScript cannot be linted, minified or
 * cached by the browser, and it hid roughly 1280 lines of behaviour from
 * every tool that looks at .js files -- which is why an audit counted 74
 * wp_ajax actions with "no JavaScript caller" when in fact the callers were
 * right there in the PHP.
 *
 * Values that used to be interpolated by PHP now arrive through
 * wp_localize_script as `yatoonServicesData`.
 */
jQuery(function($){
    let serviceImageFrame  = null;
    let galleryImageFrame  = null;
    let galleryImages      = []; // [{url, caption}]
    const serviceCategories = yatoonServicesData.categories;
    const categoryNonce = yatoonServicesData.categoryNonce;

    function setCategoryField(category) {
        category = category || '';
        if (category && serviceCategories.indexOf(category) === -1) {
            $('#service-category-select').val('__new');
            $('#service-category-new').val(category).show();
        } else {
            $('#service-category-select').val(category);
            $('#service-category-new').val('').hide();
        }
        $('#service-category').val(category);
    }

    $('#service-category-select').on('change', function() {
        if ($(this).val() === '__new') {
            $('#service-category-new').show().focus();
            $('#service-category').val($('#service-category-new').val().trim());
        } else {
            $('#service-category-new').hide().val('');
            $('#service-category').val($(this).val() || '');
        }
    });

    $('#service-category-new').on('input', function() {
        $('#service-category').val($(this).val().trim());
    });

    $('#sbs-manage-categories').on('click', function() {
        $('#sbs-category-msg').text('').css('color', '');
        $('#sbs-category-modal').show();
    });

    $('#sbs-category-close').on('click', function() {
        $('#sbs-category-modal').hide();
    });

    $('#sbs-category-modal').on('click', function(e) {
        if (e.target === this) {
            $(this).hide();
        }
    });

    $(document).on('click', '.sbs-save-category', function() {
        const $row = $(this).closest('.sbs-category-manager-row');
        const oldName = String($row.data('category') || '');
        const newName = $row.find('.sbs-category-name-input').val().trim();
        if (!newName) {
            $('#sbs-category-msg').text('Category name cannot be empty.').css('color', '#c00');
            return;
        }
        const $btn = $(this).prop('disabled', true).text('Saving...');
        $.post(ajaxurl, {
            action: 'yatoon_rename_service_category',
            nonce: categoryNonce,
            old_category: oldName,
            new_category: newName
        }, function(resp) {
            if (resp.success) {
                location.reload();
            } else {
                $('#sbs-category-msg').text(resp.data || 'Failed to rename category.').css('color', '#c00');
                $btn.prop('disabled', false).text('Save');
            }
        });
    });

    $(document).on('click', '.sbs-delete-category', function() {
        const $row = $(this).closest('.sbs-category-manager-row');
        const category = String($row.data('category') || '');
        if (!confirm('Delete category "' + category + '"? Services using it will keep the service, but their category will be cleared.')) {
            return;
        }
        const $btn = $(this).prop('disabled', true).text('Deleting...');
        $.post(ajaxurl, {
            action: 'yatoon_delete_service_category',
            nonce: categoryNonce,
            category: category
        }, function(resp) {
            if (resp.success) {
                location.reload();
            } else {
                $('#sbs-category-msg').text(resp.data || 'Failed to delete category.').css('color', '#c00');
                $btn.prop('disabled', false).text('Delete');
            }
        });
    });

    // -- Gallery helpers ------------------------------------------------
    function renderGalleryGrid() {
        const $grid = $('#service-gallery-grid');
        if (!galleryImages.length) {
            $grid.html('<p style="color:#9ca3af;font-size:13px;margin:0;">No gallery images yet.</p>');
            return;
        }
        let html = '';
        galleryImages.forEach(function(img, i) {
            html += `<div class="sbs-gallery-item" data-index="${i}">
                <img src="${img.url}" alt="">
                <div class="sbs-gallery-item-actions">
                    <button type="button" class="sbs-gallery-remove" data-index="${i}" title="Remove">&times;</button>
                </div>
            </div>`;
        });
        $grid.html(html);
        // Make sortable
        if ($.fn.sortable) {
            $grid.sortable({
                items: '.sbs-gallery-item',
                cursor: 'grabbing',
                update: function() {
                    const newOrder = [];
                    $grid.find('.sbs-gallery-item').each(function() {
                        newOrder.push(galleryImages[parseInt($(this).data('index'))]);
                    });
                    galleryImages = newOrder;
                    renderGalleryGrid();
                }
            });
        }
    }

    function loadGalleryImages(serviceId) {
        if (!serviceId) { galleryImages = []; renderGalleryGrid(); return; }
        $.get(ajaxurl, {
            action: 'yatoon_get_service_images',
            nonce: yatoonServicesData.serviceNonce,
            service_id: serviceId
        }, function(resp) {
            galleryImages = resp.success ? resp.data.images.map(function(i){ return {url: i.image_url, caption: i.caption}; }) : [];
            renderGalleryGrid();
        });
    }

    function saveGalleryImages(serviceId, callback) {
        $.post(ajaxurl, {
            action: 'yatoon_save_service_images',
            nonce: yatoonServicesData.serviceNonce,
            service_id: serviceId,
            images: galleryImages
        }, function(resp) {
            if (callback) callback(resp);
        });
    }

    // Add gallery images
    $('#service-gallery-add').on('click', function(e) {
        e.preventDefault();
        if (galleryImageFrame) { galleryImageFrame.open(); return; }
        galleryImageFrame = wp.media({
            title: 'Choose Gallery Images',
            button: { text: 'Add to gallery' },
            library: { type: 'image' },
            multiple: true
        });
        galleryImageFrame.on('select', function() {
            const selected = galleryImageFrame.state().get('selection').toJSON();
            selected.forEach(function(att) {
                const url = att.sizes && att.sizes.large ? att.sizes.large.url : att.url;
                if (!galleryImages.find(function(g){ return g.url === url; })) {
                    galleryImages.push({ url: url, caption: '' });
                }
            });
            renderGalleryGrid();
        });
        galleryImageFrame.open();
    });

    // Remove gallery image
    $(document).on('click', '.sbs-gallery-remove', function() {
        const idx = parseInt($(this).data('index'));
        galleryImages.splice(idx, 1);
        renderGalleryGrid();
    });

    // -- Gallery CSS ---------------------------------------------------
    $('<style>')
        .text('.sbs-gallery-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(90px,1fr));gap:8px;padding:4px 0;}'
            + '.sbs-gallery-item{position:relative;border-radius:8px;overflow:hidden;aspect-ratio:1;background:#f3f4f6;cursor:grab;}'
            + '.sbs-gallery-item img{width:100%;height:100%;object-fit:cover;display:block;}'
            + '.sbs-gallery-item-actions{position:absolute;top:4px;right:4px;}'
            + '.sbs-gallery-remove{background:rgba(0,0,0,.55);color:#fff;border:none;border-radius:50%;width:22px;height:22px;font-size:14px;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;}'
            + '.sbs-gallery-remove:hover{background:#dc2626;}')
        .appendTo('head');

    function setServiceImage(url) {
        url = url || '';
        $('#service-image-url').val(url);
        if (url) {
            $('#service-image-preview').show().find('img').attr('src', url).attr('alt', $('#service-name').val() || 'Service image');
            $('#service-image-remove').show();
        } else {
            $('#service-image-preview').hide().find('img').attr('src', '').attr('alt', '');
            $('#service-image-remove').hide();
        }
    }

    $('#service-image-upload').on('click', function(e) {
        e.preventDefault();

        if (serviceImageFrame) {
            serviceImageFrame.open();
            return;
        }

        serviceImageFrame = wp.media({
            title: 'Choose Service Image',
            button: { text: 'Use this image' },
            library: { type: 'image' },
            multiple: false
        });

        serviceImageFrame.on('select', function() {
            const attachment = serviceImageFrame.state().get('selection').first().toJSON();
            const url = (attachment.sizes && attachment.sizes.medium ? attachment.sizes.medium.url : attachment.url);
            setServiceImage(url);
        });

        serviceImageFrame.open();
    });

    $('#service-image-remove').on('click', function(e) {
        e.preventDefault();
        setServiceImage('');
    });

    // Make table sortable with drag handle
    $('#sbs-sortable-services').sortable({
        handle: '.sbs-drag-handle',
        items: '> tr.sbs-main-service-row',
        axis: 'y',
        cursor: 'grabbing',
        placeholder: 'sbs-service-sort-placeholder',
        helper: function(e, tr) {
            const $originals = tr.children();
            const $helper = tr.clone();
            $helper.children().each(function(index) {
                $(this).width($originals.eq(index).width());
            });
            return $helper;
        },
        start: function(event, ui) {
            ui.placeholder.html('<td colspan="11"></td>');
            ui.placeholder.height(ui.item.outerHeight());
        },
        update: function(event, ui) {
            saveOrder(true);
        }
    });

    // Manual order input
    $(document).on('change', '.sbs-order-input', function(){
        saveOrder(false);
    });

    function saveOrder(useVisualOrder) {
        const order = [];
        $('#sbs-sortable-services tr.sbs-main-service-row').each(function(index){
            const id = $(this).data('id');
            const manualOrder = useVisualOrder ? index + 1 : (parseInt($(this).find('.sbs-order-input').val(), 10) || index + 1);
            if (useVisualOrder) {
                $(this).find('.sbs-order-input').val(manualOrder);
            }
            order.push({ id: id, sort_order: manualOrder });
        });

        $.post(ajaxurl, {
            action: 'yatoon_update_service_order',
            nonce: yatoonServicesData.orderNonce,
            order: order
        }, function(resp){
            if (resp.success) {
                // Update visual order numbers
                if (useVisualOrder) {
                    $('#sbs-sortable-services tr.sbs-main-service-row').each(function(i){
                        $(this).find('.sbs-order-input').val(i + 1);
                    });
                }
            }
        });
    }

    function updateSelectedServicesState() {
        const total = $('.sbs-svc-chk').length;
        const checked = $('.sbs-svc-chk:checked').length;
        const selectedRows = $('.sbs-svc-chk:checked').closest('tr.sbs-main-service-row');
        const oneSelected = checked === 1;
        $('#sbs-delete-selected-services').prop('disabled', checked === 0);
        $('#sbs-edit-selected-service, #sbs-add-addon-selected-service').prop('disabled', !oneSelected);
        if (checked === 0) {
            $('#sbs-selected-services-summary').text('Select a service or click a row to edit.');
        } else if (oneSelected) {
            $('#sbs-selected-services-summary').text('Selected: ' + (selectedRows.first().data('service-name') || '1 service'));
        } else {
            $('#sbs-selected-services-summary').text(checked + ' services selected');
        }
        $('#sbs-select-all-services-main')
            .prop('checked', total > 0 && checked === total)
            .prop('indeterminate', checked > 0 && checked < total);
        $('.sbs-svc-chk').each(function() {
            $(this).closest('tr.sbs-main-service-row').toggleClass('is-selected', $(this).is(':checked'));
        });
    }

    $('#sbs-select-all-services-main').on('change', function(e) {
        $('.sbs-svc-chk').prop('checked', $(this).is(':checked'));
        updateSelectedServicesState();
    });

    $(document).on('change', '.sbs-svc-chk', function(e) {
        // Reading offsetHeight does not reliably force Chromium/Edge to
        // repaint this checkbox's own check-mark when other DOM changes
        // happen in the same handler. Cloning the element and swapping it
        // in does force a correct repaint.
        const cb = this;
        const isChecked = cb.checked;
        const freshCb = cb.cloneNode(true);
        freshCb.checked = isChecked;
        cb.parentNode.replaceChild(freshCb, cb);
        updateSelectedServicesState();
    });

    $(document).on('click', '#sbs-services-table tbody tr.sbs-main-service-row td:first-child', function(e) {
        if ($(e.target).is('.sbs-svc-chk')) {
            return;
        }
        e.stopPropagation();
        const checkbox = $(this).find('.sbs-svc-chk');
        checkbox.prop('checked', !checkbox.prop('checked'));
        updateSelectedServicesState();
    });

    $('#sbs-edit-selected-service').on('click', function() {
        const row = $('.sbs-svc-chk:checked').closest('tr.sbs-main-service-row').first();
        if (!row.length) {
            return;
        }
        row.find('.sbs-edit-service').trigger('click');
    });

    $('#sbs-add-addon-selected-service').on('click', function() {
        const row = $('.sbs-svc-chk:checked').closest('tr.sbs-main-service-row').first();
        if (!row.length) {
            return;
        }
        row.find('.sbs-copy-addon-btn').first().trigger('click');
    });
    $(document).on('click', '#sbs-services-table tbody tr.sbs-main-service-row', function(e) {
        if ($(e.target).closest('input, button, select, textarea, a, .sbs-drag-handle, .yatoon-col-resizer, .sbs-switch, .sbs-slider, .sbs-status-toggle').length) {
            return;
        }
        $(this).find('.sbs-edit-service').trigger('click');
    });

    function applyServiceFilters() {
        const q = ($('#sbs-service-search').val() || '').toLowerCase().trim();
        const cat = ($('#sbs-service-category-filter').val() || '').toLowerCase();
        const status = ($('#sbs-service-status-filter').val() || '').toLowerCase();
        const designUpload = ($('#sbs-service-design-upload-filter').val() || '');

        $('#sbs-sortable-services tr.sbs-main-service-row').each(function() {
            const $row = $(this);
            const serviceId = $row.data('id');
            const matchesText = !q || String($row.data('search') || '').indexOf(q) !== -1;
            const matchesCat = !cat || String($row.data('category') || '') === cat;
            const matchesStatus = !status || String($row.data('status') || '') === status;
            const matchesDesignUpload = !designUpload || String($row.data('design-upload') || '0') === designUpload;
            const visible = matchesText && matchesCat && matchesStatus && matchesDesignUpload;
            $row.toggle(visible);
            if (!visible) {
                $('#sbs-sortable-services tr.sbs-options-row[data-service-id="' + serviceId + '"], #options-' + serviceId).hide();
            }
        });
    }

    $('#sbs-service-search, #sbs-service-category-filter, #sbs-service-status-filter, #sbs-service-design-upload-filter').on('input change', applyServiceFilters);
    $('#sbs-service-clear-filters').on('click', function() {
        $('#sbs-service-search').val('');
        $('#sbs-service-category-filter').val('');
        $('#sbs-service-status-filter').val('');
        $('#sbs-service-design-upload-filter').val('');
        applyServiceFilters();
    });

    $(document).on('click', '.sbs-delete-service', function(e) {
        e.stopPropagation();
        const id = parseInt($(this).data('id'), 10);
        if (!id) return;
        if (!confirm('Delete this service? This cannot be undone.')) return;

        const $btn = $(this);
        const originalText = $btn.text();
        $btn.prop('disabled', true).text('Deleting...');

        $.post(ajaxurl, {
            action: 'yatoon_delete_service',
            nonce: yatoonServicesData.adminNonce,
            service_id: id
        }, function(resp) {
            if (resp.success) {
                $('#sbs-sortable-services tr.sbs-main-service-row[data-id="' + id + '"]').fadeOut(200, function() { $(this).remove(); });
                $('#sbs-sortable-services tr.sbs-options-row[data-service-id="' + id + '"], #options-' + id).remove();
                if (window.YatoonToast) { window.YatoonToast('success', 'Service deleted.'); }
            } else {
                $btn.prop('disabled', false).text(originalText);
                alert(resp.data && resp.data.message ? resp.data.message : 'Failed to delete service.');
            }
        }).fail(function() {
            $btn.prop('disabled', false).text(originalText);
            alert('Network error. Please try again.');
        });
    });

    $('#sbs-delete-selected-services').on('click', function() {
        const ids = $('.sbs-svc-chk:checked').map(function() {
            return parseInt($(this).val(), 10);
        }).get().filter(Boolean);

        if (!ids.length) {
            return;
        }

        if (!confirm('Delete selected services? This cannot be undone.')) {
            return;
        }

        const $btn = $(this).prop('disabled', true).text('Deleting...');

        $.post(ajaxurl, {
            action: 'yatoon_delete_service',
            nonce: yatoonServicesData.adminNonce,
            service_ids: ids
        }, function(resp) {
            if (resp.success) {
                ids.forEach(function(id) {
                    $('#sbs-sortable-services tr.sbs-main-service-row[data-id="' + id + '"]').remove();
                    $('#sbs-sortable-services tr.sbs-options-row[data-service-id="' + id + '"], #options-' + id).remove();
                });
                updateSelectedServicesState();
                if (!$('.sbs-svc-chk').length) {
                    location.reload();
                }
            } else {
                alert(resp.data && resp.data.message ? resp.data.message : 'Failed to delete selected services.');
            }
        }).fail(function() {
            alert('Network error. Please try again.');
        }).always(function() {
            $btn.text('Delete Selected');
            updateSelectedServicesState();
        });
    });
    
    // Toggle options expand/collapse
    $(document).on('click', '.sbs-toggle-options', function() {
        const btn = $(this);
        const serviceId = btn.data('service-id');
        const optionsRow = $('.sbs-options-row[data-service-id="' + serviceId + '"]');
        const icon = btn.find('.dashicons');
        const textSpan = btn.find('.sbs-toggle-text');
        
        if (optionsRow.is(':visible')) {
            optionsRow.slideUp(200);
            icon.removeClass('dashicons-arrow-up-alt2').addClass('dashicons-arrow-down-alt2');
            textSpan.text('Show Options (' + optionsRow.find('tbody tr').length + ')');
        } else {
            optionsRow.slideDown(200);
            icon.removeClass('dashicons-arrow-down-alt2').addClass('dashicons-arrow-up-alt2');
            textSpan.text('Hide Options');
        }
    });
    
    $(document).on('input change', '.sbs-option-name, .sbs-option-duration, .sbs-option-price, .sbs-option-group, .sbs-option-badge', function() {
        const optionId = $(this).data('option-id');
        const row = $('tr.sbs-option-row[data-option-id="' + optionId + '"]');
        row.find('.sbs-option-save-state').removeClass('is-saved').addClass('is-dirty').text('Unsaved');
    });

    function updateInlineOptionCount(serviceId) {
        const optionsRow = $('.sbs-options-row[data-service-id="' + serviceId + '"]');
        const count = optionsRow.find('tbody tr.sbs-option-row').length;
        const toggle = $('.sbs-toggle-options[data-service-id="' + serviceId + '"] .sbs-toggle-text');
        if (toggle.length && !optionsRow.is(':visible')) {
            toggle.text('Show Options (' + count + ')');
        }
        if (count === 0) {
            optionsRow.find('tbody').append('<tr class="sbs-options-empty"><td colspan="7" style="padding:16px 8px; color:#6b7280; text-align:center;">No options yet. Use Add Add-on or edit the service to add one.</td></tr>');
        }
    }

    // Save option name, price and duration
    $(document).on('click', '.sbs-save-option', function() {
        const btn = $(this);
        const optionId = btn.data('option-id');
        const nameInput = $('.sbs-option-name[data-option-id="' + optionId + '"]');
        const priceInput = $('.sbs-option-price[data-option-id="' + optionId + '"]');
        const groupSelect = $('.sbs-option-group[data-option-id="' + optionId + '"]');
        const badgeSelect = $('.sbs-option-badge[data-option-id="' + optionId + '"]');
        const durationInput = $('.sbs-option-duration[data-option-id="' + optionId + '"]');
        const newName = nameInput.val().trim();
        const newPrice = parseFloat(priceInput.val());
        const groupName = groupSelect.length ? groupSelect.val() : '';
        const badgeLabel = badgeSelect.length ? badgeSelect.val() : '';
        const newDuration = parseInt(durationInput.val()) || 0;
        
        if (!newName) {
            alert('Option name cannot be empty');
            return;
        }
        
        if (isNaN(newPrice) || newPrice < 0) {
            alert('Please enter a valid price');
            return;
        }

        if (newDuration < 1) {
            alert('Duration must be at least 1 minute');
            return;
        }
        
        btn.prop('disabled', true).text('Saving...');
        
        const basePrice = parseFloat(priceInput.data('base-price')) || 0;
        // Add-on options stack on top of whatever Main option is selected, so their
        // modifier must be the flat amount to add - not relative to the base price
        // (which is only correct for Main options that replace/modify the base once).
        const priceModifier = (groupName === 'Add-on') ? newPrice : (newPrice - basePrice);
        $.post(ajaxurl, {
            action: 'yatoon_update_option',
            nonce: yatoonServicesData.optionNonce,
            option_id: optionId,
            name: newName,
            price: newPrice,
            price_modifier: priceModifier,
            group_name: groupName,
            badge_label: badgeLabel,
            duration_minutes: newDuration
        }, function(resp) {
            btn.prop('disabled', false).text('Save');
            
            if (resp.success) {
                // Show success notification
                nameInput.css('border-color', '#10B981');
                priceInput.css('border-color', '#10B981');
                durationInput.css('border-color', '#10B981');
                $('tr.sbs-option-row[data-option-id="' + optionId + '"] .sbs-option-save-state').removeClass('is-dirty').addClass('is-saved').text('Saved');
                setTimeout(function() {
                    nameInput.css('border-color', '');
                    priceInput.css('border-color', '');
                    durationInput.css('border-color', '');
                }, 1500);
            } else {
                alert('Failed to save: ' + (resp.data || 'Unknown error'));
                nameInput.css('border-color', '#dc2626');
                priceInput.css('border-color', '#dc2626');
                durationInput.css('border-color', '#dc2626');
            }
        });
    });

    $(document).on('click', '.sbs-delete-option', function() {
        const btn = $(this);
        const optionId = btn.data('option-id');
        const row = btn.closest('tr.sbs-option-row');
        const serviceId = row.closest('.sbs-options-sortable').data('service-id');

        if (!confirm('Delete this option? This cannot be undone.')) {
            return;
        }

        btn.prop('disabled', true).text('Deleting...');
        $.post(ajaxurl, {
            action: 'yatoon_delete_option',
            nonce: yatoonServicesData.optionNonce,
            option_id: optionId
        }, function(resp) {
            if (resp.success) {
                row.fadeOut(160, function() {
                    $(this).remove();
                    updateInlineOptionCount(serviceId);
                });
            } else {
                btn.prop('disabled', false).text('Delete');
                alert('Failed to delete: ' + (resp.data || 'Unknown error'));
            }
        }).fail(function() {
            btn.prop('disabled', false).text('Delete');
            alert('Network error. Please try again.');
        });
    });
    
    // -- Edit Service Modal: Options Manager ---------------------------------
    var modalOptionsNonce = yatoonServicesData.optionNonce;
    var yatoonAiDescNonce = yatoonServicesData.aiDescNonce;
    var modalOptionsServiceId = 0;
    var reusableOptionItems = [];

    function populateReusableOptionSelect(serviceId) {
        var select = $('#sbs-new-option-existing');
        select.empty().append($('<option>', {
            value: '',
            text: 'Manual - create a new option'
        }));
        var groups = {};
        reusableOptionItems.forEach(function(item) {
            if (parseInt(item.service_id, 10) === parseInt(serviceId, 10)) return;
            var groupLabel = item.group_label || 'Existing items';
            if (!groups[groupLabel]) {
                groups[groupLabel] = $('<optgroup>').attr('label', groupLabel);
                select.append(groups[groupLabel]);
            }
            groups[groupLabel].append($('<option>', {
                value: item.key,
                text: item.label + ' - ' + item.duration_minutes + ' min - $' + parseFloat(item.price || 0).toFixed(2)
            }));
        });
    }

    function loadReusableOptionItems(serviceId) {
        $.post(ajaxurl, {
            action: 'yatoon_get_addon_options',
            nonce: modalOptionsNonce
        }, function(resp) {
            if (resp.success) {
                reusableOptionItems = resp.data.items || [];
                populateReusableOptionSelect(serviceId);
            }
        });
    }

    $('#sbs-new-option-existing').on('change', function() {
        var key = String($(this).val() || '');
        var item = reusableOptionItems.find(function(candidate) {
            return String(candidate.key) === key;
        });
        $('#sbs-new-option-source-service, #sbs-new-option-source-option').val('');
        if (!item) {
            $('#sbs-new-option-link-note').text('Manual mode: enter a new name, duration, price, and type below.');
            return;
        }
        $('#sbs-new-option-name').val(item.name || '');
        $('#sbs-new-option-duration').val(parseInt(item.duration_minutes, 10) || 10);
        $('#sbs-new-option-price').val(parseFloat(item.price || 0).toFixed(2));
        $('#sbs-new-option-group').val('Add-on');
        if (item.source_type === 'service') {
            $('#sbs-new-option-source-service').val(item.source_id);
        } else {
            $('#sbs-new-option-source-option').val(item.source_id);
        }
        $('#sbs-new-option-link-note').text(
            item.shared_id
                ? 'Linked to shared ID: ' + item.shared_id + '. You may adjust the display name, duration, or price.'
                : 'This item has no shared ID yet. One will be created automatically when you add it.'
        );
    });

    // Add Service
    $('#sbs-add-service').on('click', function() {
        $('#sbs-modal-title').text('Add Service');
        $('#sbs-service-form')[0].reset();
        modalOptionsServiceId = 0;
        $('#sbs-modal-options-section').hide();
        $('#service-id').val('');
        $('#service-active').prop('checked', true);
        $('#service-require-policy').prop('checked', false);
        $('#service-require-consent').prop('checked', false);
        $('#service-allow-staff-select').prop('checked', true);
        $('#service-allow-design-upload').prop('checked', false);
        $('#service-is-featured').prop('checked', false);
        $('#service-buffer-before').val(0);
        $('#service-buffer-after').val(0);
        $('#service-lead-time').val(0);
        $('#service-estimated-cost').val(0);
        setCategoryField('');
        setServiceImage('');
        $('#yatoon-ai-desc-status').text("Uses this service's name, category, price, duration, and current description.");
        galleryImages = [];
        renderGalleryGrid();
        $('#sbs-service-modal').show();
    });

    $('#yatoon-ai-desc-btn').on('click', function() {
        const btn = $(this);
        const status = $('#yatoon-ai-desc-status');
        const serviceName = ($('#service-name').val() || '').trim();

        if (!serviceName) {
            status.text('Enter a service name first.');
            $('#service-name').focus();
            return;
        }

        btn.prop('disabled', true).text('Improving...');
        status.text('AI is writing a clearer customer-facing description...');

        $.post(ajaxurl, {
            action: 'yatoon_ai_service_description',
            nonce: yatoonAiDescNonce,
            service_name: serviceName,
            category: $('#service-category').val(),
            price: $('#service-price').val(),
            duration: $('#service-duration').val(),
            description: $('#service-description').val()
        }, function(resp) {
            if (resp && resp.success && resp.data && resp.data.description) {
                $('#service-description').val(resp.data.description);
                status.text('Description updated. Review it, then save the service.');
            } else {
                status.text((resp && resp.data && resp.data.message) ? resp.data.message : 'AI could not improve this description right now.');
            }
        }).fail(function() {
            status.text('AI request failed. Please try again.');
        }).always(function() {
            btn.prop('disabled', false).text('Improve with AI');
        });
    });
    
    // Edit Service
    $(document).on('click', '.sbs-edit-service', function() {
        const serviceId = $(this).data('id');
        
        $('#sbs-modal-title').text('Edit Service');
        $('#service-id').val(serviceId);
        
        $.post(ajaxurl, {
            action: 'yatoon_get_service',
            nonce: yatoonServicesData.serviceNonce,
            service_id: serviceId
        }, function(resp) {
            if (resp.success) {
                const s = resp.data;
                $('#service-name').val(s.name);
                $('#service-description').val(s.description || '');
                $('#yatoon-ai-desc-status').text("Uses this service's name, category, price, duration, and current description.");
                $('#service-duration').val(s.duration_minutes);
		                $('#service-price').val(s.price);
		                $('#service-tax-rate').val(s.tax_rate === null ? '' : s.tax_rate);
	                $('#service-estimated-cost').val(s.estimated_cost || 0);
                setCategoryField(s.category || '');
                $('#service-active').prop('checked', s.is_active == 1);
                $('#service-require-policy').prop('checked', s.require_policy == 1);
                $('#service-require-consent').prop('checked', s.require_consent == 1);
                $('#service-allow-staff-select').prop('checked', s.allow_staff_select != 0);
                $('#service-allow-design-upload').prop('checked', s.allow_design_upload == 1);
                $('#service-is-featured').prop('checked', s.is_featured == 1);
                $('#service-buffer-before').val(s.buffer_before_min || 0);
                $('#service-buffer-after').val(s.buffer_after_min || 0);
                $('#service-lead-time').val(s.min_lead_time_min || 0);
                setServiceImage(s.image_url || '');
                loadGalleryImages(serviceId);
                $('#sbs-modal-options-section').show();
                loadModalOptions(serviceId);
                $('#sbs-service-modal').show();
            } else {
                alert('Failed to load service data');
            }
        });
    });
    
    // Save Service (Add or Update)
    $('#sbs-service-form').on('submit', function(e) {
        e.preventDefault();
        
        const submitBtn = $(this).find('button[type="submit"]');
        submitBtn.prop('disabled', true).text('Saving...');
        
        $.post(ajaxurl, {
            action: 'yatoon_save_service',
            nonce: yatoonServicesData.serviceNonce,
            id: $('#service-id').val(),
            name: $('#service-name').val(),
            description: $('#service-description').val(),
            duration: $('#service-duration').val(),
		            price: $('#service-price').val(),
		            tax_rate: $('#service-tax-rate').val(),
	            estimated_cost: $('#service-estimated-cost').val(),
            category: $('#service-category').val(),
            is_active: $('#service-active').is(':checked') ? 1 : 0,
            require_policy: $('#service-require-policy').is(':checked') ? 1 : 0,
            require_consent: $('#service-require-consent').is(':checked') ? 1 : 0,
            allow_staff_select: $('#service-allow-staff-select').is(':checked') ? 1 : 0,
            allow_design_upload: $('#service-allow-design-upload').is(':checked') ? 1 : 0,
            is_featured: $('#service-is-featured').is(':checked') ? 1 : 0,
            buffer_before_min: $('#service-buffer-before').val(),
            buffer_after_min: $('#service-buffer-after').val(),
            min_lead_time_min: $('#service-lead-time').val(),
            image_url: $('#service-image-url').val()
        }, function(resp) {
            if (resp.success) {
                // Save gallery images then reload
                const savedId = resp.data.service_id || parseInt($('#service-id').val()) || 0;
                if (savedId && galleryImages.length > 0) {
                    saveGalleryImages(savedId, function() { location.reload(); });
                } else if (savedId && galleryImages.length === 0 && parseInt($('#service-id').val()) > 0) {
                    // Editing existing - still save (may be clearing images)
                    saveGalleryImages(savedId, function() { location.reload(); });
                } else {
                    location.reload();
                }
            } else {
                alert('Failed: ' + (resp.data || 'Unknown error'));
                submitBtn.prop('disabled', false).text('Save Service');
            }
        });
    });
    
    function setServiceStatusButton(btn, isActive) {
        btn.data('active', isActive ? 1 : 0)
            .attr('data-active', isActive ? 1 : 0)
            .attr('aria-pressed', isActive ? 'true' : 'false')
            .toggleClass('is-active', !!isActive)
            .toggleClass('is-hidden', !isActive)
            .text(isActive ? 'Active' : 'Hidden');
    }

    // Toggle Service Active/Inactive
    $(document).on('click', '.sbs-status-toggle', function(e) {
        e.preventDefault();
        e.stopPropagation();
        const btn = $(this);
        if (btn.hasClass('is-saving')) { return; }
        const serviceId = btn.data('id');
        const previousActive = parseInt(btn.attr('data-active'), 10) === 1;
        const nextActive = !previousActive;
        setServiceStatusButton(btn, nextActive);
        btn.addClass('is-saving').prop('disabled', true);

        $.post(ajaxurl, {
            action: 'yatoon_toggle_service',
            nonce: yatoonServicesData.serviceNonce,
            service_id: serviceId,
            is_active: nextActive ? 1 : 0
        }, function(resp) {
            btn.removeClass('is-saving').prop('disabled', false);
            if (!resp.success) {
                setServiceStatusButton(btn, previousActive);
                alert('Failed to update status');
                return;
            }
            btn.closest('tr.sbs-main-service-row').attr('data-status', nextActive ? 'active' : 'inactive').data('status', nextActive ? 'active' : 'inactive');
            applyServiceFilters();
        }).fail(function() {
            btn.removeClass('is-saving').prop('disabled', false);
            setServiceStatusButton(btn, previousActive);
            alert('Failed to update status');
        });
    });
    
    // Close modal when clicking outside
    $('#sbs-service-modal').on('click', function(e) {
        if (e.target === this) {
            $(this).hide();
        }
    });

    // Close modal via the X button or Cancel button
    $('.sbs-service-modal-close, .sbs-service-modal-cancel').on('click', function(e) {
        e.preventDefault();
        $('#sbs-service-modal').hide();
    });

    function loadModalOptions(serviceId) {
        modalOptionsServiceId = serviceId;
        loadReusableOptionItems(serviceId);
        $.post(ajaxurl, {
            action: 'yatoon_get_service_options',
            nonce: modalOptionsNonce,
            service_id: serviceId
        }, function(resp) {
            var $tbody = $('#sbs-modal-options-body');
            $tbody.empty();
            if (resp.success && resp.data.options && resp.data.options.length > 0) {
                var basePrice = parseFloat($('#service-price').val()) || 0;
                $.each(resp.data.options, function(i, opt) {
                    var groupName = opt.group_name ? opt.group_name : '';
                    // Add-on modifier is already the flat add-on amount; Main modifier
                    // is relative to the base service price.
                    var absPrice = (groupName === 'Add-on' ? parseFloat(opt.price_modifier) : (parseFloat(opt.price_modifier) + basePrice)).toFixed(2);
                    var safeName = String(opt.name || '').replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/'/g, '&#039;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
                    var row = '' +
                        '<tr class="sbs-modal-option-row" data-option-id="' + opt.id + '" style="border-bottom:1px solid #f0f0f0;">' +
                        '<td style="padding:6px 4px;">' +
                            '<input type="number" class="sbs-modal-option-order" min="0" value="' + i + '" style="width:52px; padding:6px 4px; border:1px solid #d1d5db; border-radius:6px; text-align:center;" title="Lower numbers show first. Press Enter or click away to save.">' +
                        '</td>' +
                        '<td style="padding:6px 8px;">' +
                            '<input type="text" class="sbs-modal-option-name" value="' + safeName + '" style="width:100%; min-width:170px; padding:6px 8px; border:1px solid #d1d5db; border-radius:6px;">' +
                        '</td>' +
                        '<td style="padding:6px 8px;">' +
                            '<input type="number" class="sbs-modal-option-duration" min="1" step="1" value="' + (parseInt(opt.duration_minutes, 10) || 10) + '" style="width:74px; padding:6px 8px; border:1px solid #d1d5db; border-radius:6px;">' +
                        '</td>' +
                        '<td style="padding:6px 8px;">' +
                            '<input type="number" class="sbs-modal-option-price" min="0" step="0.01" value="' + absPrice + '" style="width:86px; padding:6px 8px; border:1px solid #d1d5db; border-radius:6px;">' +
                        '</td>' +
                        '<td style="padding:6px 8px;">' +
                            '<select class="sbs-modal-option-group" style="width:120px; padding:6px 8px; border:1px solid #d1d5db; border-radius:6px;">' +
                                '<option value=""' + (groupName === '' ? ' selected' : '') + '>Main (single)</option>' +
                                '<option value="Add-on"' + (groupName === 'Add-on' ? ' selected' : '') + '>Add-on (multi)</option>' +
                            '</select>' +
                        '</td>' +
                        '<td style="padding:6px 8px; text-align:right; white-space:nowrap;">' +
                            '<button type="button" class="button button-small sbs-modal-save-option" data-option-id="' + opt.id + '">Save</button> ' +
                            '<button type="button" class="button button-small sbs-modal-delete-option" data-option-id="' + opt.id + '" style="color:#c00; border-color:#c00;">Delete</button>' +
                            '<div class="sbs-modal-option-state" style="font-size:11px; color:#6b7280; margin-top:4px; min-height:14px;"></div>' +
                        '</td></tr>';
                    $tbody.append(row);
                });
            } else {
                $tbody.append('<tr id="sbs-modal-options-empty"><td colspan="6" style="padding:18px 8px; color:#6b7280; text-align:center;">No options yet. Add one below, or reuse an existing option from another service.</td></tr>');
            }
        });
    }

    $(document).on('change', '.sbs-modal-option-order', function() {
        if (!modalOptionsServiceId) return;
        var $changedInput = $(this);
        var $tbody = $('#sbs-modal-options-body');
        var $rows = $tbody.find('tr.sbs-modal-option-row').get();
        $rows.sort(function(a, b) {
            return (parseInt($(a).find('.sbs-modal-option-order').val(), 10) || 0)
                 - (parseInt($(b).find('.sbs-modal-option-order').val(), 10) || 0);
        });
        $.each($rows, function(i, row) {
            $tbody.append(row);
            $(row).find('.sbs-modal-option-order').val(i);
        });
        var order = $.map($rows, function(row) { return $(row).data('option-id'); });
        var $state = $changedInput.closest('tr.sbs-modal-option-row').find('.sbs-modal-option-state');
        $state.css('color', '#6b7280').text('Saving order...');
        $.post(ajaxurl, {
            action: 'yatoon_reorder_options',
            nonce: modalOptionsNonce,
            service_id: modalOptionsServiceId,
            order: JSON.stringify(order)
        }, function(resp) {
            if (resp.success) {
                $state.css('color', '#16a34a').text('Order saved');
                setTimeout(function() { $state.text(''); }, 1800);
            } else {
                $state.css('color', '#c00').text('Order not saved');
                if (window.YatoonToast) {
                    window.YatoonToast('error', resp.data || 'Failed to save order.');
                } else {
                    alert('Failed to save order: ' + (resp.data || ''));
                }
            }
        }).fail(function() {
            $state.css('color', '#c00').text('Order not saved');
            if (window.YatoonToast) {
                window.YatoonToast('error', 'Network error while saving order. Please try again.');
            } else {
                alert('Network error while saving order. Please try again.');
            }
        });
    });

    $(document).on('input change', '.sbs-modal-option-name, .sbs-modal-option-duration, .sbs-modal-option-price, .sbs-modal-option-group', function() {
        $(this).closest('tr.sbs-modal-option-row').find('.sbs-modal-option-state').css('color', '#b45309').text('Unsaved');
    });

    $(document).on('click', '.sbs-modal-save-option', function() {
        var btn = $(this);
        var row = btn.closest('tr.sbs-modal-option-row');
        var optionId = btn.data('option-id');
        var name = row.find('.sbs-modal-option-name').val().trim();
        var duration = parseInt(row.find('.sbs-modal-option-duration').val(), 10) || 0;
        var price = parseFloat(row.find('.sbs-modal-option-price').val());
        var group = row.find('.sbs-modal-option-group').val();
        var basePrice = parseFloat($('#service-price').val()) || 0;
        var state = row.find('.sbs-modal-option-state');

        if (!name) {
            state.css('color', '#c00').text('Name is required');
            return;
        }
        if (!duration || duration < 1) {
            state.css('color', '#c00').text('Duration is required');
            return;
        }
        if (isNaN(price) || price < 0) {
            state.css('color', '#c00').text('Price is required');
            return;
        }

        btn.prop('disabled', true).text('Saving...');
        state.css('color', '#6b7280').text('Saving');
        $.post(ajaxurl, {
            action: 'yatoon_update_option',
            nonce: modalOptionsNonce,
            option_id: optionId,
            name: name,
            duration_minutes: duration,
            price: price,
            price_modifier: (group === 'Add-on' ? price : (price - basePrice)).toFixed(2),
            group_name: group
        }, function(resp) {
            btn.prop('disabled', false).text('Save');
            if (resp.success) {
                state.css('color', '#047857').text('Saved');
                setTimeout(function(){ state.text(''); }, 1800);
            } else {
                state.css('color', '#c00').text(resp.data || 'Failed');
            }
        }).fail(function() {
            btn.prop('disabled', false).text('Save');
            state.css('color', '#c00').text('Failed');
        });
    });
    // Add new option from modal
    $('#sbs-modal-add-option-btn').on('click', function() {
        var name = $('#sbs-new-option-name').val().trim();
        var duration = parseInt($('#sbs-new-option-duration').val()) || 10;
        var price = parseFloat($('#sbs-new-option-price').val()) || 0;
        var group = $('#sbs-new-option-group').val();
        var basePrice = parseFloat($('#service-price').val()) || 0;
        var $msg = $('#sbs-modal-option-msg');

        if (!name) {
            $msg.text('Warning: Option name is required.').css('color','#c00').show();
            return;
        }
        if (!modalOptionsServiceId) {
            $msg.text('Warning: Please save the service first.').css('color','#c00').show();
            return;
        }

        var btn = $(this);
        btn.prop('disabled', true).text('Adding...');
        $msg.hide();

        $.post(ajaxurl, {
            action: 'yatoon_add_option',
            nonce: modalOptionsNonce,
            service_id: modalOptionsServiceId,
            name: name,
            duration_minutes: duration,
            price_modifier: (group === 'Add-on' ? price : (price - basePrice)).toFixed(2),
            group_name: group,
            square_id: '',
            source_service_id: parseInt($('#sbs-new-option-source-service').val(), 10) || 0,
            source_option_id: parseInt($('#sbs-new-option-source-option').val(), 10) || 0
        }, function(resp) {
            btn.prop('disabled', false).text('Add');
            if (resp.success) {
                $msg.text('Option added.').addClass('yatoon-inline-status').show();
                $('#sbs-new-option-name').val('');
                $('#sbs-new-option-price').val('0');
                $('#sbs-new-option-existing').val('');
                $('#sbs-new-option-source-service, #sbs-new-option-source-option').val('');
                $('#sbs-new-option-link-note').text('Choose an existing service option to reuse its shared ID, or enter a new option manually below.');
                loadModalOptions(modalOptionsServiceId);
                setTimeout(function(){ $msg.hide(); }, 2000);
            } else {
                $msg.text('Warning: ' + (resp.data || 'Failed')).css('color','#c00').show();
            }
        });
    });

    // Delete option from modal
    $(document).on('click', '.sbs-modal-delete-option', function() {
        var optionId = $(this).data('option-id');
        if (!confirm('Delete this option?')) return;
        var btn = $(this);
        var originalText = btn.text();
        btn.prop('disabled', true).text('Deleting...');
        $.post(ajaxurl, {
            action: 'yatoon_delete_option',
            nonce: modalOptionsNonce,
            option_id: optionId
        }, function(resp) {
            if (resp.success) {
                btn.closest('tr').fadeOut(200, function(){ $(this).remove(); });
            } else {
                btn.prop('disabled', false).text(originalText);
                alert('Failed: ' + (resp.data || 'Unknown error'));
            }
        }).fail(function() {
            btn.prop('disabled', false).text(originalText);
            alert('Network error. Please try again.');
        });
    });


    var addonAllOptions = [];   // all option rows from server
    var addonTargetServiceId = 0;
    var addonNonce = yatoonServicesData.optionNonce;

    // Open modal
    $(document).on('click', '.sbs-copy-addon-btn', function() {
        addonTargetServiceId = parseInt($(this).data('service-id'));
        var svcName = $(this).data('service-name');
        $('#sbs-addon-target-name').text(svcName);
        $('#sbs-addon-msg').text('');
        $('#sbs-addon-confirm').prop('disabled', true);
        $('#sbs-addon-option-preview').hide();
        $('#sbs-addon-options-list').hide();
        $('#sbs-addon-source-empty').hide();
        $('#sbs-addon-name').val('');
        $('#sbs-addon-duration').val('');
        $('#sbs-addon-price').val('');
        $('#sbs-addon-sq-id-display').text('(optional; copied when available)');

        // Load all options if not yet loaded
        if (addonAllOptions.length === 0) {
            $.post(ajaxurl, { action: 'yatoon_get_addon_options', nonce: addonNonce }, function(resp) {
                if (resp.success) {
                    addonAllOptions = resp.data.options;
                    populateAddonServiceSelect();
                }
            });
        } else {
            populateAddonServiceSelect();
        }
        $('#sbs-copy-addon-modal').show();
    });

    function populateAddonServiceSelect() {
        var $sel = $('#sbs-addon-source-service');
        $sel.empty().append('<option value="">-- Select source service --</option>');
        // Group by service
        var seen = {};
        var count = 0;
        addonAllOptions.forEach(function(o) {
            if (!seen[o.service_id]) {
                seen[o.service_id] = true;
                // Don't show the target service itself
                if (o.service_id != addonTargetServiceId) {
                    $sel.append('<option value="' + o.service_id + '">' + o.service_name + '</option>');
                    count++;
                }
            }
        });
        $('#sbs-addon-source-empty').toggle(count === 0);
        validateAddonManualFields();
    }

    function validateAddonManualFields() {
        var name = $('#sbs-addon-name').val().trim();
        var duration = parseInt($('#sbs-addon-duration').val(), 10);
        var priceRaw = $('#sbs-addon-price').val();
        var price = parseFloat(priceRaw);
        var valid = !!name && duration > 0 && priceRaw !== '' && !isNaN(price) && price >= 0;
        $('#sbs-addon-confirm').prop('disabled', !valid);
        return valid;
    }

    $('#sbs-addon-name, #sbs-addon-duration, #sbs-addon-price').on('input', validateAddonManualFields);

    // When source service changes, populate option list
    $('#sbs-addon-source-service').on('change', function() {
        var svcId = parseInt($(this).val());
        var $optSel = $('#sbs-addon-source-option');
        $optSel.empty().append('<option value="">-- Select option --</option>');
        $('#sbs-addon-option-preview').hide();
        validateAddonManualFields();
        if (!svcId) { $('#sbs-addon-options-list').hide(); return; }

        addonAllOptions.forEach(function(o) {
            if (o.service_id == svcId) {
                $optSel.append('<option value="' + o.option_id + '">' + o.option_name + ' (' + o.duration_minutes + 'min, $' + parseFloat(o.price_modifier >= 0 ? o.price_modifier : 0).toFixed(2) + ')</option>');
            }
        });
        $('#sbs-addon-options-list').show();
    });

    // When option selected, fill preview fields
    $('#sbs-addon-source-option').on('change', function() {
        var optId = parseInt($(this).val());
        if (!optId) { $('#sbs-addon-option-preview').hide(); validateAddonManualFields(); return; }
        var opt = addonAllOptions.find(function(o){ return o.option_id == optId; });
        if (!opt) return;
        $('#sbs-addon-name').val(opt.option_name);
        $('#sbs-addon-duration').val(opt.duration_minutes);
        $('#sbs-addon-price').val(parseFloat(opt.price_modifier >= 0 ? opt.price_modifier : 0).toFixed(2));
        $('#sbs-addon-sq-id-display').text(opt.square_id || '(no Square ID)');
        var preview = 'Source: ' + opt.service_name + ' -> ' + opt.option_name;
        if (opt.square_id) preview += ' | Square ID: ' + opt.square_id;
        $('#sbs-addon-option-preview').text(preview).show();
        validateAddonManualFields();
        if (!opt.square_id) {
            $('#sbs-addon-msg').text('This option has no Square ID, so it will be added as a local Add-on.').css('color','#666');
        } else {
            $('#sbs-addon-msg').text('').css('color','');
        }
    });

    // Confirm add
    $('#sbs-addon-confirm').on('click', function() {
        var optId = parseInt($('#sbs-addon-source-option').val());
        var opt = addonAllOptions.find(function(o){ return o.option_id == optId; });

        var name     = $('#sbs-addon-name').val().trim() || (opt ? opt.option_name : '');
        var duration = parseInt($('#sbs-addon-duration').val()) || (opt ? opt.duration_minutes : 0);
        var price    = parseFloat($('#sbs-addon-price').val()) || 0;

        if (!name || duration <= 0 || price < 0) {
            $('#sbs-addon-msg').text('Enter an Add-on name, duration, and price.').css('color','#c00');
            validateAddonManualFields();
            return;
        }

        $(this).prop('disabled', true).text('Adding...');
        $('#sbs-addon-msg').text('').css('color','');

        $.post(ajaxurl, {
            action:           'yatoon_add_option',
            nonce:            addonNonce,
            service_id:       addonTargetServiceId,
            name:             name,
            duration_minutes: duration,
            price_modifier:   price,
            group_name:       'Add-on',
            square_id:        opt && opt.square_id ? opt.square_id : '',
            square_version:   opt && opt.square_version ? opt.square_version : '',
        }, function(resp) {
            if (resp.success) {
                $('#sbs-addon-msg').text('Added successfully. Refreshing...').css('color','green');
                // Reload after 1.2s
                setTimeout(function(){ location.reload(); }, 1200);
            } else {
                $('#sbs-addon-msg').text(resp.data || 'Failed to add').css('color','#c00');
                $('#sbs-addon-confirm').prop('disabled', false).text('Add');
            }
        });
    });

    // Close modal
    $('#sbs-addon-cancel').on('click', function() {
        $('#sbs-copy-addon-modal').hide();
    });
    $(document).on('click', '#sbs-copy-addon-modal', function(e) {
        if ($(e.target).is('#sbs-copy-addon-modal')) $('#sbs-copy-addon-modal').hide();
    });


    // -- Option row drag-sort ------------------------------------------------
    function initOptionSortable($tbody) {
        $tbody.sortable({
            handle: '.sbs-option-drag-handle',
            axis: 'y',
            items: 'tr',
            placeholder: 'ui-state-highlight',
            tolerance: 'pointer',
            stop: function(e, ui) {
                var serviceId = $tbody.data('service-id');
                var order = [];
                $tbody.find('tr[data-option-id]').each(function(i) {
                    order.push(parseInt($(this).data('option-id')));
                });
                $.post(ajaxurl, {
                    action: 'yatoon_reorder_options',
                    nonce:      yatoonServicesData.optionNonce,
                    service_id: serviceId,
                    order:      JSON.stringify(order),
                }, function(resp) {
                    if (!resp.success) alert('Failed to save order: ' + (resp.data || ''));
                });
            }
        });
    }

    // Init all visible option sortables
    $('.sbs-options-sortable').each(function() { initOptionSortable($(this)); });

    // Also init when options are shown (toggle)
    $(document).on('click', '.sbs-toggle-options', function() {
        var serviceId = $(this).data('service-id');
        setTimeout(function() {
            var $tbody = $('.sbs-options-sortable[data-service-id="' + serviceId + '"]');
            if ($tbody.length && !$tbody.hasClass('ui-sortable')) {
                initOptionSortable($tbody);
            }
        }, 100);
    });

});
