/**
 * Custom Schema by SCHEMAFY - Meta Tags Manager
 * Version: 1.1.0
 * Manage meta titles and descriptions independently
 */

(function($) {
    'use strict';

    // Guard: schemafy_ajax must be loaded before this module (schemafy-schema-admin-v2 dependency).
    // If it is missing, bail early with a clear console error instead of throwing cryptic
    // "schemafy_ajax is not defined" errors on every interaction.
    if (typeof schemafy_ajax === 'undefined') {
        console.error('[SCHEMAFY Meta Tags] schemafy_ajax is not defined. ' +
            'Ensure schemafy-schema-admin-v2 is loaded before admin-meta-tags.js. ' +
            'Meta tags save/load will not work.');
        return;
    }

    window.SCHEMAFY = window.SCHEMAFY || {};
    window.SCHEMAFY.MetaTags = {};

    let currentPageUrl = null;
    let initialized = false;
    let cachedSelectHTML = null; // Cache for cross-browser option filtering
    let pageLoadToken = 0;
    let metaLoadRequest = null;
    let metaLoadToken = 0;
    let saveRequest = null;
    let clearRequest = null;
    const META_TITLE_MAX = 200;
    const META_DESCRIPTION_MAX = 500;

    function i18n() {
        return (typeof schemafy_ajax !== 'undefined' && schemafy_ajax.i18n) ? schemafy_ajax.i18n : {};
    }

    function text(key, fallback) {
        const strings = i18n();
        return strings[key] || fallback;
    }

    /**
     * Initialize Meta Tags Manager
     */
    window.SCHEMAFY.MetaTags.init = function() {
        if (initialized) return;


        // Load pages into selector
        loadPages();

        // Event listeners
        $('#schemafy-meta-page-search').on('input', filterPages);
        $('#schemafy-meta-page-select').on('change', handlePageSelection);

        // Custom URL list click — bypasses native select for reliability
        $(document).on('click', '.schemafy-mtm-url-item', function() {
            const postId = String($(this).data('post-id'));
            const url    = $(this).data('url');
            if (!postId || !url) return;

            openEditorForPage(postId, url);
        });

        // Character counters with SEO indicators (use event delegation for reliability)
        $(document).off('input', '#schemafy-meta-custom-title').on('input', '#schemafy-meta-custom-title', updateTitleCounter);
        $(document).off('input', '#schemafy-meta-custom-desc').on('input', '#schemafy-meta-custom-desc', updateDescriptionCounter);

        // Live preview (use event delegation)
        $(document).off('input', '#schemafy-meta-custom-title, #schemafy-meta-custom-desc').on('input', '#schemafy-meta-custom-title, #schemafy-meta-custom-desc', updateGooglePreview);

        // Initialize counters with current values
        updateTitleCounter();
        updateDescriptionCounter();

        // Device toggle for preview
        $(document).on('click', '.schemafy-device-btn', handleDeviceToggle);

        // Form submission
        $('#schemafy-meta-form').on('submit', saveMetaTags);

        // Clear button
        $('#schemafy-meta-clear').on('click', clearMetaTags);

        initialized = true;
    };

    /**
     * Load pages and posts into the selector
     */
    function loadPages() {
        cachedSelectHTML = null; // Invalidate filter cache on reload
        const token = ++pageLoadToken;
        const $selector = $('#schemafy-meta-page-select');

        $selector.html('<option value="" disabled selected>' + escapeHtml(text('loading_pages', 'Loading pages...')) + '</option>');
        $('#schemafy-mtm-url-list').html(
            '<div style="padding:24px 16px;text-align:center;">' +
                '<div class="schemafy-spinner-v2" style="margin:0 auto 10px;"></div>' +
                '<p style="color:#a1a1aa;font-size:12px;margin:0;">' + escapeHtml(text('loading_pages', 'Loading pages...')) + '</p>' +
            '</div>'
        );

        const groups = [
            { postType: 'page', label: text('pages_label', 'Pages') },
            { postType: 'post', label: text('posts_label', 'Posts') },
            { postType: 'product', label: text('products_label', 'Products') }
        ];
        const loaded = [];
        let remaining = groups.length;

        groups.forEach(function(group) {
            $.ajax({
                url: schemafy_ajax.ajax_url,
                type: 'POST',
                data: {
                    action: 'schemafy_get_urls_for_meta',
                    nonce: schemafy_ajax.nonce,
                    post_type: group.postType
                }
            }).done(function(response) {
                loaded.push({
                    label: group.label,
                    postType: group.postType,
                    items: response && response.success && response.data ? response.data : [],
                    failed: !(response && response.success)
                });
            }).fail(function(xhr) {
                loaded.push({
                    label: group.label,
                    postType: group.postType,
                    items: [],
                    failed: true,
                    message: getAjaxErrorMessage(xhr, text('error_loading_pages', 'Error loading pages'))
                });
            }).always(function() {
                remaining--;

                if (remaining > 0 || token !== pageLoadToken) {
                    return;
                }

                renderLoadedPageGroups(loaded, $selector);
            });
        });
    }

    /**
     * Build the custom URL list from scratch (Pages group)
     */
    function buildCustomList(group, items) {
        const $list = $('#schemafy-mtm-url-list');
        $list.empty();
        if (!items || !items.length) return;
        appendToCustomList(group, items);
    }

    /**
     * Append a group of items to the custom URL list
     */
    function appendToCustomList(group, items) {
        if (!items || !items.length) return;
        const $list = $('#schemafy-mtm-url-list');
        $list.append('<div class="schemafy-mtm-url-group">' + escapeHtml(group) + '</div>');
        items.forEach(function(item) {
            const urlShort = (item.url || '').replace(/^https?:\/\//, '').replace(/\/$/, '');
            $list.append(
                '<div class="schemafy-mtm-url-item" data-post-id="' + escapeHtml(String(item.id || 0)) + '" ' +
                'data-url="' + escapeHtml(item.url) + '" data-title="' + escapeHtml(item.title) + '">' +
                '<span class="schemafy-mtm-url-item-title">' + escapeHtml(item.title) + '</span>' +
                '<span class="schemafy-mtm-url-item-url">' + escapeHtml(urlShort) + '</span>' +
                '</div>'
            );
        });
    }

    function renderLoadedPageGroups(groups, $selector) {
        const ordered = groups.sort(function(a, b) {
            const order = { page: 0, post: 1, product: 2 };
            return (order[a.postType] || 99) - (order[b.postType] || 99);
        });
        const hasItems = ordered.some(function(group) {
            return group.items && group.items.length;
        });
        const failedGroups = ordered.filter(function(group) {
            return group.failed;
        });

        if (!hasItems) {
            $selector.html('<option value="">' + escapeHtml(text('no_pages_found', 'No pages found')) + '</option>');
            $('#schemafy-mtm-url-list').html('<p style="padding:16px;color:#a1a1aa;font-size:12px;text-align:center;">' + escapeHtml(text('no_pages_found', 'No pages found')) + '</p>');

            if (failedGroups.length) {
                showNotification(failedGroups[0].message || text('error_loading_pages', 'Error loading pages'), 'error');
            }
            return;
        }

        let options = '<option value="" disabled selected>' + escapeHtml(text('select_page_placeholder', 'Select a page')) + '</option>';
        $('#schemafy-mtm-url-list').empty();

        ordered.forEach(function(group) {
            if (!group.items || !group.items.length) {
                return;
            }

            if (group.postType === 'page') {
                group.items.forEach(function(item) {
                    options += renderOption(item);
                });
            } else {
                options += '<optgroup label="' + escapeHtml(group.label) + '">';
                group.items.forEach(function(item) {
                    options += renderOption(item);
                });
                options += '</optgroup>';
            }

            appendToCustomList(group.label, group.items);
        });

        $selector.html(options);
        cachedSelectHTML = $selector.html();

        if (failedGroups.length) {
            showNotification(text('some_meta_sources_failed', 'Some content sources could not be loaded.'), 'warning');
        }
    }

    function renderOption(item) {
        return '<option value="' + escapeHtml(String(item.id || 0)) + '" data-url="' + escapeHtml(item.url || '') + '" data-title="' + escapeHtml(item.title || '') + '">' +
            escapeHtml(item.title || item.url || '') +
            '</option>';
    }

    /**
     * Filter pages based on search input.
     * Uses DOM rebuild instead of show/hide because hiding <option> elements
     * is not reliable across all browsers (Chrome/Safari ignore display:none).
     */
    function filterPages() {
        const searchTerm = $(this).val().toLowerCase().trim();
        const $select = $('#schemafy-meta-page-select');

        // Cache the fully-loaded HTML on first filter call
        if (!cachedSelectHTML) {
            cachedSelectHTML = $select.html();
        }

        // Restore full list before filtering
        $select.html(cachedSelectHTML);

        if (!searchTerm) return;

        // Remove non-matching options and empty optgroups
        $select.find('optgroup').each(function() {
            let matched = 0;
            $(this).find('option').each(function() {
                const title = $(this).text().toLowerCase();
                const url = ($(this).attr('data-url') || '').toLowerCase();
                if (!title.includes(searchTerm) && !url.includes(searchTerm)) {
                    $(this).remove();
                } else {
                    matched++;
                }
            });
            if (matched === 0) $(this).remove();
        });

        // Handle bare options outside optgroups (keep placeholder)
        $select.children('option').each(function() {
            if (!$(this).val()) return;
            const title = $(this).text().toLowerCase();
            const url = ($(this).attr('data-url') || '').toLowerCase();
            if (!title.includes(searchTerm) && !url.includes(searchTerm)) {
                $(this).remove();
            }
        });

        // Also filter the custom visual list
        $('.schemafy-mtm-url-item').each(function() {
            const title = (($(this).data('title') || '') + '').toLowerCase();
            const url   = (($(this).data('url')   || '') + '').toLowerCase();
            $(this).toggle(!searchTerm || title.includes(searchTerm) || url.includes(searchTerm));
        });
        // Hide group headers with no visible items
        $('.schemafy-mtm-url-group').each(function() {
            const $items = $(this).nextUntil('.schemafy-mtm-url-group', '.schemafy-mtm-url-item');
            $(this).toggle($items.filter(':visible').length > 0);
        });
    }

    /**
     * Handle page selection
     */
    function handlePageSelection() {
        const $selected = $(this).find('option:selected');
        const postId = $selected.val();
        const url = $selected.data('url');

        if (postId === '' || postId === undefined || !url) return;

        openEditorForPage(postId, url);
    }

    function openEditorForPage(postId, url) {
        currentPageUrl = url;
        postId = String(postId || '');

        $('#schemafy-meta-page-select').val(postId);
        setActiveListItem(postId, url);

        // Show editor and divider, hide empty state
        $('#schemafy-meta-editor').css('display', '');
        $('#schemafy-meta-divider').show();
        $('#schemafy-meta-empty-state').hide();

        // Update sidebar
        $('#schemafy-meta-sidebar-url').text(url);
        $('#schemafy-meta-sidebar-visit').attr('href', url);

        // Store URL in hidden inputs
        $('#schemafy-meta-page-url').val(url);
        $('#schemafy-meta-visit-page').val(url);
        $('#schemafy-meta-current-url').val(url);

        // Reset fields + preview while loading the selected page.
        $('#schemafy-meta-custom-title').val('');
        $('#schemafy-meta-custom-desc').val('');
        updateTitleCounter();
        updateDescriptionCounter();
        updateGooglePreview();

        // Load current meta tags
        loadCurrentMetaTags(url, postId);
    }

    function setActiveListItem(postId, url) {
        const normalizedUrl = String(url || '').replace(/\/$/, '');

        $('.schemafy-mtm-url-item').removeClass('mtm-active').each(function() {
            const itemPostId = String($(this).data('post-id'));
            const itemUrl = String($(this).data('url') || '').replace(/\/$/, '');

            if ((postId && itemPostId === postId) || (normalizedUrl && itemUrl === normalizedUrl)) {
                $(this).addClass('mtm-active');
            }
        });
    }

    /**
     * Load current meta tags for selected page
     */
    function loadCurrentMetaTags(url, postId) {
        const requestToken = ++metaLoadToken;

        if (metaLoadRequest && metaLoadRequest.readyState !== 4) {
            metaLoadRequest.abort();
        }

        // Show loading state
        $('#schemafy-current-meta-title').html('<span style="color:#999;">' + escapeHtml(text('loading_label', 'Loading...')) + '</span>');
        $('#schemafy-current-meta-desc').html('<span style="color:#999;">' + escapeHtml(text('loading_label', 'Loading...')) + '</span>');
        $('#schemafy-seo-plugin-name').text(text('detecting_seo_plugin', 'Detecting SEO plugin...'));

        metaLoadRequest = $.ajax({
            url: schemafy_ajax.ajax_url,
            type: 'POST',
            data: {
                action: 'schemafy_get_meta_tags',
                nonce: schemafy_ajax.nonce,
                url: url,
                post_id: postId
            },
            success: function(response) {
                if (requestToken !== metaLoadToken) {
                    return;
                }

                if (response.success && response.data) {
                    const data = response.data;

                    // Display current values
                    setTextOrEmpty('#schemafy-current-meta-title', data.current_title, text('no_title_detected', 'No title detected'));
                    setTextOrEmpty('#schemafy-current-meta-desc', data.current_description, text('no_description_detected', 'No description detected'));

                    // Show detected SEO plugin
                    $('#schemafy-seo-plugin-name').text(data.title_source || text('wordpress_default', 'WordPress Default'));

                    if (data.url) {
                        currentPageUrl = data.url;
                        $('#schemafy-meta-page-url').val(data.url);
                        $('#schemafy-meta-visit-page').val(data.url);
                        $('#schemafy-meta-current-url').val(data.url);
                        $('#schemafy-meta-sidebar-url').text(data.url);
                        $('#schemafy-meta-sidebar-visit').attr('href', data.url);
                    }

                    if (typeof data.post_id !== 'undefined') {
                        $('#schemafy-meta-page-select').val(String(data.post_id));
                        setActiveListItem(String(data.post_id), data.url || url);
                    }

                    // Set custom values if they exist
                    $('#schemafy-meta-custom-title').val(data.custom_title || '');
                    $('#schemafy-meta-custom-desc').val(data.custom_description || '');

                    // Update counters and preview
                    updateTitleCounter();
                    updateDescriptionCounter();
                    updateGooglePreview();
                } else {
                    showNotification(getResponseMessage(response, text('error_loading_meta', 'Error loading meta tags')), 'error');
                }
            },
            error: function(xhr, status) {
                if (status === 'abort' || requestToken !== metaLoadToken) {
                    return;
                }

                showNotification(getAjaxErrorMessage(xhr, text('error_loading_meta', 'Error loading meta tags')), 'error');
            }
        });
    }

    /**
     * Update title character counter with SEO indicator
     */
    function updateTitleCounter() {
        const $input = $('#schemafy-meta-custom-title');
        const length = $input.val().length;
        const $counter = $('#schemafy-meta-title-count');
        const $indicator = $('#schemafy-meta-title-indicator');
        const $status = $indicator.find('.schemafy-seo-status');
        const $icon = $indicator.find('.dashicons');

        $counter.text(length);

        // Remove all status classes
        $indicator.removeClass('schemafy-seo-good schemafy-seo-warning schemafy-seo-bad');
        $icon.removeClass('dashicons-yes-alt dashicons-warning dashicons-dismiss');

        const i18n = (typeof schemafy_ajax !== 'undefined' && schemafy_ajax.i18n) ? schemafy_ajax.i18n : {};
        if (length === 0) {
            // Empty - neutral
            $indicator.addClass('schemafy-seo-warning');
            $icon.addClass('dashicons-warning');
            $status.text(i18n.empty_will_use_default || 'Empty (will use default)');
        } else if (length >= 50 && length <= 60) {
            // Optimal length
            $indicator.addClass('schemafy-seo-good');
            $icon.addClass('dashicons-yes-alt');
            $status.text(i18n.perfect_length || 'Perfect length!');
        } else if (length < 50) {
            // Too short
            $indicator.addClass('schemafy-seo-warning');
            $icon.addClass('dashicons-warning');
            $status.text(i18n.too_short_title || 'Too short (aim for 50-60)');
        } else if (length > 60 && length <= 70) {
            // Slightly too long
            $indicator.addClass('schemafy-seo-warning');
            $icon.addClass('dashicons-warning');
            $status.text(i18n.a_bit_long || 'A bit long');
        } else {
            // Way too long
            $indicator.addClass('schemafy-seo-bad');
            $icon.addClass('dashicons-dismiss');
            $status.text(i18n.too_long_cutoff || 'Too long! Will be cut off');
        }
    }

    /**
     * Update description character counter with SEO indicator
     */
    function updateDescriptionCounter() {
        const $input = $('#schemafy-meta-custom-desc');
        const length = $input.val().length;
        const $counter = $('#schemafy-meta-desc-count');
        const $indicator = $('#schemafy-meta-desc-indicator');
        const $status = $indicator.find('.schemafy-seo-status');
        const $icon = $indicator.find('.dashicons');

        $counter.text(length);

        // Remove all status classes
        $indicator.removeClass('schemafy-seo-good schemafy-seo-warning schemafy-seo-bad');
        $icon.removeClass('dashicons-yes-alt dashicons-warning dashicons-dismiss');

        const i18nDesc = (typeof schemafy_ajax !== 'undefined' && schemafy_ajax.i18n) ? schemafy_ajax.i18n : {};
        if (length === 0) {
            // Empty - neutral
            $indicator.addClass('schemafy-seo-warning');
            $icon.addClass('dashicons-warning');
            $status.text(i18nDesc.empty_will_use_default || 'Empty (will use default)');
        } else if (length >= 120 && length <= 160) {
            // Optimal length
            $indicator.addClass('schemafy-seo-good');
            $icon.addClass('dashicons-yes-alt');
            $status.text(i18nDesc.perfect_length || 'Perfect length!');
        } else if (length < 120) {
            // Too short
            $indicator.addClass('schemafy-seo-warning');
            $icon.addClass('dashicons-warning');
            $status.text(i18nDesc.too_short_desc || 'Too short (aim for 120-160)');
        } else {
            // Too long
            $indicator.addClass('schemafy-seo-bad');
            $icon.addClass('dashicons-dismiss');
            $status.text(i18nDesc.too_long_cutoff || 'Too long! Will be cut off');
        }
    }

    /**
     * Handle device toggle (Desktop/Mobile)
     */
    function handleDeviceToggle(e) {
        e.preventDefault();
        const $btn = $(e.currentTarget);
        const device = $btn.data('device');

        // Update active button
        $('.schemafy-device-btn').removeClass('active');
        $btn.addClass('active');

        // Show/hide corresponding preview
        $('.schemafy-google-preview-container').removeClass('active');
        $(`.schemafy-device-${device}`).addClass('active');
    }

    /**
     * Update Google SERP Preview (Desktop + Mobile)
     */
    function updateGooglePreview() {
        const customTitle = $('#schemafy-meta-custom-title').val();
        const customDesc  = $('#schemafy-meta-custom-desc').val();
        const currentTitle = $('#schemafy-current-meta-title').text();
        const currentDesc  = $('#schemafy-current-meta-desc').text();

        const displayTitle = customTitle || currentTitle || text('serp_title_placeholder', 'Your Page Title Will Appear Here');
        const displayDesc  = customDesc  || currentDesc  || text('serp_description_placeholder', 'Your meta description will appear here. Make it compelling to improve click-through rates from search results.');

        // URL parts
        let sitename    = 'example.com';
        let breadcrumbD = 'example.com › page';
        let breadcrumbM = 'example.com';
        let faviconUrl  = '';

        if (currentPageUrl) {
            try {
                const parsed = new URL(currentPageUrl);
                sitename    = parsed.hostname;
                const parts = parsed.pathname.split('/').filter(function(p) { return p; });
                breadcrumbD = parts.length ? parsed.hostname + ' › ' + parts.join(' › ') : parsed.hostname;
                breadcrumbM = parsed.hostname;
                faviconUrl  = 'https://www.google.com/s2/favicons?sz=32&domain_url=' + encodeURIComponent(currentPageUrl);
            } catch (e) { /* invalid URL, keep defaults */ }
        }

        // Truncated query text for the fake search bar
        const queryText = displayTitle.length > 42 ? displayTitle.slice(0, 42) + '…' : displayTitle;

        // Desktop
        $('#schemafy-google-preview-title-desktop').text(displayTitle);
        $('#schemafy-google-preview-desc-desktop').text(displayDesc);
        $('#schemafy-serp-sitename-desktop').text(sitename);
        $('#schemafy-google-preview-url-desktop').text(breadcrumbD);
        $('#schemafy-serp-query-desktop').text(queryText);

        // Mobile
        $('#schemafy-google-preview-title-mobile').text(displayTitle);
        $('#schemafy-google-preview-desc-mobile').text(displayDesc);
        $('#schemafy-serp-sitename-mobile').text(sitename);
        $('#schemafy-google-preview-url-mobile').text(breadcrumbM);
        $('#schemafy-serp-query-mobile').text(queryText);

        // Favicon — load via Google's favicon service; show globe on failure
        if (faviconUrl) {
            ['desktop', 'mobile'].forEach(function(device) {
                var $img    = $('#schemafy-serp-favicon-' + device);
                var $circle = $('#schemafy-serp-fav-circle-' + device);
                $img.off('load error')
                    .on('load',  function() { $circle.addClass('has-favicon'); })
                    .on('error', function() { $circle.removeClass('has-favicon'); })
                    .attr('src', faviconUrl);
            });
        } else {
            $('#schemafy-serp-fav-circle-desktop, #schemafy-serp-fav-circle-mobile').removeClass('has-favicon');
        }
    }

    /**
     * Save meta tags
     */
    function saveMetaTags(e) {
        e.preventDefault();

        if (saveRequest && saveRequest.readyState !== 4) {
            showNotification(text('meta_save_in_progress', 'Schemafy is already saving these meta tags. Please wait a moment.'), 'info');
            return;
        }

        const $form = $(this);
        const $submitBtn = $form.find('button[type="submit"]');
        const $clearBtn = $('#schemafy-meta-clear');
        const originalHtml = $submitBtn.html();
        const url = $('#schemafy-meta-page-url').val();

        // Validation
        if (!url) {
            showNotification(text('please_select_page', 'Please select a page first'), 'error');
            return;
        }

        // Get values
        const postId = $('#schemafy-meta-page-select').val();
        const metaTitle = $('#schemafy-meta-custom-title').val().trim();
        const metaDescription = $('#schemafy-meta-custom-desc').val().trim();

        // Check if there's anything to save
        if (!metaTitle && !metaDescription) {
            showNotification(text('please_enter_title_or_desc', 'Please enter at least a title or description'), 'warning');
            return;
        }

        if (metaTitle.length > META_TITLE_MAX) {
            showNotification(formatMessage(text('meta_title_too_long_max', 'Meta title is too long. Maximum length is {max} characters.'), { max: META_TITLE_MAX }), 'error');
            return;
        }

        if (metaDescription.length > META_DESCRIPTION_MAX) {
            showNotification(formatMessage(text('meta_description_too_long_max', 'Meta description is too long. Maximum length is {max} characters.'), { max: META_DESCRIPTION_MAX }), 'error');
            return;
        }

        // Disable both buttons during save
        $submitBtn.prop('disabled', true).attr('aria-busy', 'true').html('<span class="dashicons dashicons-image-rotate spin" aria-hidden="true"></span> ' + escapeHtml(text('saving', 'Saving...')));
        $clearBtn.prop('disabled', true);

        saveRequest = $.ajax({
            url: schemafy_ajax.ajax_url,
            type: 'POST',
            data: {
                action: 'schemafy_save_meta_tags',
                nonce: schemafy_ajax.nonce,
                url: url,
                post_id: postId,
                meta_title: metaTitle,
                meta_description: metaDescription
            },
            success: function(response) {
                if (response.success) {
                    const data = response.data || {};
                    const savedUrl = data.url || url;
                    const savedPostId = typeof data.post_id !== 'undefined' ? data.post_id : postId;

                    currentPageUrl = savedUrl;
                    $('#schemafy-meta-page-url').val(savedUrl);
                    $('#schemafy-meta-visit-page').val(savedUrl);
                    $('#schemafy-meta-current-url').val(savedUrl);

                    showNotification(getResponseMessage(response, text('meta_saved', 'Meta tags saved successfully!')), 'success');
                    // Reload current values to show updated data
                    loadCurrentMetaTags(savedUrl, savedPostId);
                } else {
                    showNotification(getResponseMessage(response, text('error_saving_meta', 'Error saving meta tags')), 'error');
                }
            },
            error: function(jqXHR) {
                showNotification(getAjaxErrorMessage(jqXHR, text('error_saving_meta', 'Error saving meta tags')), 'error');
                console.error('Save error:', jqXHR);
            },
            complete: function() {
                saveRequest = null;
                // Re-enable both buttons
                $submitBtn.prop('disabled', false).attr('aria-busy', 'false').html(originalHtml);
                $clearBtn.prop('disabled', false);
            }
        });
    }

    /**
     * Clear/Reset meta tags
     */
    function clearMetaTags(e) {
        e.preventDefault();

        const url = $('#schemafy-meta-page-url').val();
        const postId = $('#schemafy-meta-page-select').val();

        // Validation
        if (!url) {
            showNotification(text('please_select_page', 'Please select a page first'), 'error');
            return;
        }

        if (clearRequest && clearRequest.readyState !== 4) {
            showNotification(text('meta_clear_in_progress', 'Schemafy is already clearing these meta tags. Please wait a moment.'), 'info');
            return;
        }

        // Check if there's anything to clear
        const hasCustomTitle = $('#schemafy-meta-custom-title').val().trim().length > 0;
        const hasCustomDesc = $('#schemafy-meta-custom-desc').val().trim().length > 0;

        if (!hasCustomTitle && !hasCustomDesc) {
            showNotification(text('no_custom_meta', 'No custom meta tags to clear'), 'info');
            return;
        }

        const confirmMessage = text('confirm_clear_meta', 'Are you sure you want to clear the custom meta tags and revert to the default SEO plugin values?');

        // Use modern confirm dialog if available
        if (window.SCHEMAFY && window.SCHEMAFY.confirm) {
            window.SCHEMAFY.confirm(
                confirmMessage,
                () => performClearMetaTags(url, postId)
            );
        } else {
            // Fallback to native confirm
            if (confirm(confirmMessage)) {
                performClearMetaTags(url, postId);
            }
        }
    }

    /**
     * Perform the actual clear operation
     */
    function performClearMetaTags(url, postId) {
        const $clearBtn = $('#schemafy-meta-clear');
        const $submitBtn = $('button[type="submit"]', '#schemafy-meta-form');
        const originalHtml = $clearBtn.html();

        // Disable both buttons during clear
        $clearBtn.prop('disabled', true).attr('aria-busy', 'true').html('<span class="dashicons dashicons-image-rotate spin" aria-hidden="true"></span> ' + escapeHtml(text('clearing', 'Clearing...')));
        $submitBtn.prop('disabled', true);

        clearRequest = $.ajax({
            url: schemafy_ajax.ajax_url,
            type: 'POST',
            data: {
                action: 'schemafy_delete_meta_tags',
                nonce: schemafy_ajax.nonce,
                url: url,
                post_id: postId
            },
            success: function(response) {
                if (response.success) {
                    const data = response.data || {};
                    const clearedUrl = data.url || url;
                    const clearedPostId = typeof data.post_id !== 'undefined' ? data.post_id : postId;

                    showNotification(getResponseMessage(response, text('meta_cleared', 'Meta tags cleared successfully')), 'success');
                    // Clear inputs with animation
                    $('#schemafy-meta-custom-title').val('').trigger('input');
                    $('#schemafy-meta-custom-desc').val('').trigger('input');
                    // Update counters and preview
                    updateTitleCounter();
                    updateDescriptionCounter();
                    updateGooglePreview();
                    // Reload current values from SEO plugin
                    loadCurrentMetaTags(clearedUrl, clearedPostId);
                } else {
                    showNotification(getResponseMessage(response, text('error_clearing_meta', 'Error clearing meta tags')), 'error');
                }
            },
            error: function(jqXHR) {
                showNotification(getAjaxErrorMessage(jqXHR, text('error_clearing_meta', 'Error clearing meta tags')), 'error');
                console.error('Clear error:', jqXHR);
            },
            complete: function() {
                clearRequest = null;
                // Re-enable both buttons
                $clearBtn.prop('disabled', false).attr('aria-busy', 'false').html(originalHtml);
                $submitBtn.prop('disabled', false);
            }
        });
    }

    /**
     * Show notification
     */
    function showNotification(message, type) {
        if (window.SCHEMAFY && window.SCHEMAFY.showNotification) {
            window.SCHEMAFY.showNotification(message, type);
        } else {
            // Fallback to console if notification system not available
        }
    }

    function setTextOrEmpty(selector, value, emptyText) {
        const $target = $(selector);
        $target.empty();

        if (value) {
            $target.text(value);
            return;
        }

        $('<span />')
            .css('color', '#a1a1aa')
            .text(emptyText)
            .appendTo($target);
    }

    function getResponseMessage(response, fallback) {
        if (response && response.data) {
            if (typeof response.data === 'string') {
                return response.data;
            }

            if (response.data.message) {
                return response.data.message;
            }
        }

        return fallback || text('unknown_error', 'Unknown error');
    }

    function getAjaxErrorMessage(jqXHR, fallback) {
        if (jqXHR && jqXHR.responseJSON) {
            return getResponseMessage(jqXHR.responseJSON, fallback);
        }

        if (jqXHR && jqXHR.status === 403) {
            return text('permission_denied_refresh', 'Permission denied. Please refresh the page and try again.');
        }

        if (jqXHR && jqXHR.status === 0) {
            return text('network_error_connection', 'Network error. Please check your connection.');
        }

        if (jqXHR && jqXHR.status === 423) {
            return text('meta_busy_retry', 'Schemafy is already saving meta tags. Please retry in a moment.');
        }

        return fallback || text('unknown_error', 'Unknown error');
    }

    function formatMessage(template, replacements) {
        return String(template || '').replace(/\{([a-z0-9_]+)\}/gi, function(match, key) {
            return Object.prototype.hasOwnProperty.call(replacements, key) ? replacements[key] : match;
        });
    }

    /**
     * Escape HTML
     */
    function escapeHtml(value) {
        const text = String(value == null ? '' : value);
        const map = {
            '&': '&amp;',
            '<': '&lt;',
            '>': '&gt;',
            '"': '&quot;',
            "'": '&#039;'
        };
        return text.replace(/[&<>"']/g, function(m) { return map[m]; });
    }

    // Initialize when Meta Tags tab is shown
    $(document).on('click', '[data-tab="metadata"]', function() {
        setTimeout(function() {
            window.SCHEMAFY.MetaTags.init();
        }, 100);
    });

    // Also try to initialize on document ready if tab is already active
    $(document).ready(function() {
        if ($('#schemafy-tab-metadata').hasClass('active')) {
            window.SCHEMAFY.MetaTags.init();
        }
    });

    /* ─────────────────────────────────────────────
     * BULK CSV IMPORT
     * ───────────────────────────────────────────── */

    let bulkParsedRows = [];

    const BULK_MAX_ROWS  = 500;
    const SITE_ORIGIN    = getSiteOrigin();
    const SITE_HOST      = getSiteHost(SITE_ORIGIN);

    function getSiteOrigin() {
        const configured = schemafy_ajax.site_url || window.location.origin || '';

        try {
            return new URL(configured).origin.toLowerCase();
        } catch (_) {
            return String(configured).replace(/\/$/, '').toLowerCase();
        }
    }

    function getSiteHost(origin) {
        try {
            return new URL(origin).hostname.replace(/^www\./, '').toLowerCase();
        } catch (_) {
            return String(origin).replace(/^https?:\/\//, '').replace(/\/$/, '').replace(/:\d+$/, '').replace(/^www\./, '').toLowerCase();
        }
    }

    // Toggle bulk panel
    $(document).on('click', '#schemafy-mtm-bulk-toggle', function() {
        const $panel = $('#schemafy-mtm-bulk-panel');
        const open = $panel.is(':visible');
        $panel.slideToggle(200);
        $(this).toggleClass('schemafy-btn-active', !open);
    });

    // Download template CSV
    $(document).on('click', '#schemafy-mtm-download-template', function() {
        const siteBase = SITE_ORIGIN || 'https://yoursite.com';
        const csv =
            'url,meta_title,meta_description\n' +
            '"' + siteBase + '/about","About Us | Your Company","We help businesses grow with expert SEO and structured data."\n' +
            '"' + siteBase + '/services","Our Services | Your Company","Explore our digital marketing, SEO and content strategy services."\n' +
            '"' + siteBase + '/contact","Contact Us | Your Company","Get in touch with our team. Fast replies, no commitment needed."';
        const blob = new Blob(['﻿' + csv], { type: 'text/csv;charset=utf-8;' });
        const url  = URL.createObjectURL(blob);
        const a    = document.createElement('a');
        a.href = url; a.download = 'meta-tags-template.csv'; a.click();
        URL.revokeObjectURL(url);
    });

    // File input change
    $(document).on('change', '#schemafy-mtm-csv-file', function(e) {
        const file = e.target.files[0];
        if (file) handleCSVFile(file);
    });

    // Drag & drop
    $(document).on('dragover dragenter', '#schemafy-mtm-dropzone', function(e) {
        e.preventDefault(); e.stopPropagation();
        $(this).addClass('drag-over');
    }).on('dragleave drop', '#schemafy-mtm-dropzone', function(e) {
        e.preventDefault(); e.stopPropagation();
        $(this).removeClass('drag-over');
        if (e.type === 'drop') {
            const file = e.originalEvent.dataTransfer.files[0];
            if (file) handleCSVFile(file);
        }
    });

    // Clear results
    $(document).on('click', '#schemafy-mtm-clear-csv', function() {
        resetBulkState();
    });

    // Import button
    $(document).on('click', '#schemafy-mtm-import-btn', function() {
        const toImport = bulkParsedRows.filter(r => r.status !== 'error');
        if (!toImport.length) return;
        runBulkImport(toImport);
    });

    function resetBulkState() {
        $('#schemafy-mtm-val-results').hide();
        $('#schemafy-mtm-import-result').hide().removeClass('import-result-success import-result-error');
        $('#schemafy-mtm-csv-file').val('');
        $('#schemafy-mtm-import-btn').prop('disabled', true);
        $('#schemafy-mtm-import-btn-label').text('Import');
        bulkParsedRows = [];
    }

    function handleCSVFile(file) {
        // File type guard
        const ext = (file.name || '').split('.').pop().toLowerCase();
        if (ext !== 'csv' && ext !== 'txt') {
            showBulkError('Unsupported file type ".' + ext + '". Please upload a .csv file.');
            return;
        }
        // File size guard (5 MB)
        if (file.size > 5 * 1024 * 1024) {
            showBulkError('File too large (' + (file.size / 1024 / 1024).toFixed(1) + ' MB). Maximum is 5 MB.');
            return;
        }
        // Reset previous results before reading new file
        $('#schemafy-mtm-val-results').hide();
        $('#schemafy-mtm-import-result').hide().removeClass('import-result-success import-result-error');
        bulkParsedRows = [];

        const reader = new FileReader();
        reader.onload = function(e) {
            let text = e.target.result;
            // Strip UTF-8 BOM (Excel exports include it)
            text = text.replace(/^﻿/, '');
            const parsed = parseCSV(text);
            if (parsed.error) {
                showBulkError(parsed.error);
                return;
            }
            if (parsed.rows.length > BULK_MAX_ROWS) {
                showBulkError(
                    'Too many rows: ' + parsed.rows.length + '. Maximum is ' + BULK_MAX_ROWS + ' rows per import. ' +
                    'Please split your CSV into smaller files.'
                );
                return;
            }
            const validated = validateCSVRows(parsed.rows);
            bulkParsedRows = validated;
            renderValidationResults(validated, parsed.meta);
        };
        reader.onerror = function() {
            showBulkError('Could not read the file. Try saving it as UTF-8 CSV and re-uploading.');
        };
        reader.readAsText(file, 'UTF-8');
    }

    /* ── CSV Parser ──────────────────────────────
     * Handles: comma, semicolon, tab delimiters
     * Handles: quoted fields with commas/newlines
     * Handles: doubled-quote escaping ("")
     * Handles: BOM (stripped before this call)
     * Handles: CRLF, LF, CR line endings
     * ─────────────────────────────────────────── */
    function parseCSV(text) {
        const lines = text.split(/\r\n|\n|\r/);
        const nonEmpty = lines.filter(l => l.trim());

        if (!nonEmpty.length)      return { error: 'The file is empty.' };
        if (nonEmpty.length < 2)   return { error: 'File needs at least a header row and one data row.' };

        // Detect delimiter by counting occurrences across the first 4 lines
        const sample = nonEmpty.slice(0, Math.min(4, nonEmpty.length)).join('\n');
        const counts = {
            ',':  (sample.match(/,/g)  || []).length,
            ';':  (sample.match(/;/g)  || []).length,
            '\t': (sample.match(/\t/g) || []).length,
        };
        let delim = ',';
        if (counts[';']  > counts[','] && counts[';']  > counts['\t']) delim = ';';
        if (counts['\t'] > counts[','] && counts['\t'] > counts[';'])  delim = '\t';

        const rawHeaders = parseCSVLine(nonEmpty[0], delim);

        if (rawHeaders.length < 2) {
            const delimLabel = delim === '\t' ? 'tab' : '"' + delim + '"';
            return {
                error: 'Could not detect columns. Only ' + rawHeaders.length + ' column(s) found using delimiter ' + delimLabel + '. ' +
                       'Make sure your CSV uses comma, semicolon, or tab as separator and that the first row is a header.'
            };
        }

        const headers = rawHeaders.map(h => h.trim().toLowerCase().replace(/\s+/g, '_').replace(/[^a-z0-9_]/g, ''));

        // Extended column name aliases (including Spanish)
        const URL_ALIASES   = ['url','page_url','link','page_link','address','href','pagina','pagina_url','enlace'];
        const TITLE_ALIASES = ['meta_title','title','seo_title','page_title','titulo','meta_titulo','seo_titulo','titulo_seo'];
        const DESC_ALIASES  = ['meta_description','description','seo_description','meta_desc','desc',
                               'descripcion','meta_descripcion','seo_descripcion','descripcion_seo'];

        const colUrl   = headers.findIndex(h => URL_ALIASES.includes(h));
        const colTitle = headers.findIndex(h => TITLE_ALIASES.includes(h));
        const colDesc  = headers.findIndex(h => DESC_ALIASES.includes(h));

        // Report missing required columns with helpful context
        const missing = [];
        if (colUrl === -1) missing.push('"url" (accepted: ' + URL_ALIASES.slice(0,4).join(', ') + ')');
        if (colTitle === -1 && colDesc === -1) {
            missing.push('"meta_title" and/or "meta_description" (accepted: title, seo_title, description, meta_desc…)');
        }
        if (missing.length) {
            return {
                error: 'Missing required columns: ' + missing.join(' · ') + '.\n' +
                       'Columns detected in your file: ' + headers.map(h => '"' + h + '"').join(', ') + '.'
            };
        }

        const rows = [];
        const parseWarnings = [];

        for (let i = 1; i < nonEmpty.length; i++) {
            const line = nonEmpty[i].trim();
            if (!line) continue;

            const cells = parseCSVLine(line, delim);

            // Detect suspicious rows (column count mismatch — possible unquoted delimiter in value)
            if (cells.length > headers.length + 2) {
                parseWarnings.push('Row ' + (i + 1) + ': ' + cells.length + ' cells found, ' + headers.length + ' expected. ' +
                                   'Values with ' + (delim === '\t' ? 'tabs' : '"' + delim + '"') + ' should be wrapped in quotes.');
            }

            rows.push({
                url:              colUrl   !== -1 ? (cells[colUrl]   || '').trim() : '',
                meta_title:       colTitle !== -1 ? (cells[colTitle] || '').trim() : '',
                meta_description: colDesc  !== -1 ? (cells[colDesc]  || '').trim() : '',
                _line: i + 1,
            });
        }

        if (!rows.length) return { error: 'No data rows found. The file has a header but no data.' };

        const delimLabel = delim === '\t' ? 'tab' : delim;
        return {
            rows,
            meta: {
                delimiter:    delimLabel,
                data_rows:    rows.length,
                has_title:    colTitle !== -1,
                has_desc:     colDesc  !== -1,
                parse_warns:  parseWarnings,
            },
        };
    }

    function parseCSVLine(line, delim) {
        const result = [];
        let cur = '', inQ = false;
        for (let i = 0; i < line.length; i++) {
            const ch = line[i];
            if (inQ) {
                if (ch === '"') {
                    const next = line[i + 1];
                    if (next === '"') { cur += '"'; i++; }                       // escaped ""
                    else if (next === undefined || next === delim) { inQ = false; } // real closing quote
                    else { cur += '"'; }                                         // lenient: literal inner quote
                } else {
                    cur += ch;
                }
            } else {
                if (ch === '"' && cur === '') { inQ = true; }                    // open quote at field start
                else if (ch === delim) { result.push(cur); cur = ''; }
                else { cur += ch; }
            }
        }
        result.push(cur);
        return result;
    }

    /* Normalize URL: strip trailing slash for dedup (except bare domain) */
    function normalizeUrlForDedup(url) {
        if (!url) return '';
        try {
            const p = new URL(url);
            if (p.pathname.length > 1 && p.pathname.endsWith('/')) {
                p.pathname = p.pathname.slice(0, -1);
            }
            return p.href.toLowerCase();
        } catch (_) {
            return url.toLowerCase();
        }
    }

    /* ── Row Validator ───────────────────────────── */
    function validateCSVRows(rows) {
        const seenUrls = new Map(); // normalized → original row index

        return rows.map(function(row, idx) {
            const errors   = [];
            const warnings = [];

            // ── URL ──────────────────────────────────
            const url = row.url;
            let parsedUrl  = null;
            let normalizedUrl = url;

            if (!url) {
                errors.push('Missing URL');
            } else {
                try {
                    parsedUrl     = new URL(url);
                    normalizedUrl = normalizeUrlForDedup(url);

                    // Protocol mismatch
                    if (SITE_ORIGIN.startsWith('https://') && url.startsWith('http://')) {
                        warnings.push('URL uses HTTP — will be auto-upgraded to HTTPS on import');
                    }

                    // Cross-domain check
                    const urlHost = parsedUrl.hostname.replace(/^www\./, '').toLowerCase();
                    if (SITE_HOST && urlHost !== SITE_HOST) {
                        errors.push('Domain "' + parsedUrl.hostname + '" differs from this site (' + SITE_HOST + ')');
                    }
                } catch (_) {
                    errors.push('Invalid URL — must start with http:// or https://');
                }

                // Dedup check (case-insensitive, ignores trailing slash)
                if (seenUrls.has(normalizedUrl)) {
                    const firstRow = seenUrls.get(normalizedUrl) + 2;
                    errors.push('Duplicate URL (same as row ' + firstRow + ')');
                } else {
                    seenUrls.set(normalizedUrl, idx);
                }
            }

            // ── Title ────────────────────────────────
            const t = row.meta_title;
            let titleStatus = 'empty';
            if (t) {
                if      (t.length > 200) { errors.push('Title too long: ' + t.length + ' chars (max 200)');                titleStatus = 'error'; }
                else if (t.length > 70)  { warnings.push('Title long: ' + t.length + ' chars (Google shows ~60-70)');      titleStatus = 'warn'; }
                else if (t.length > 60)  { warnings.push('Title slightly long: ' + t.length + ' chars (ideal 50-60)');     titleStatus = 'warn'; }
                else if (t.length < 10)  { warnings.push('Title very short: ' + t.length + ' chars (ideal ≥ 10)');         titleStatus = 'warn'; }
                else                     { titleStatus = 'ok'; }
            }

            // ── Description ──────────────────────────
            const d = row.meta_description;
            let descStatus = 'empty';
            if (d) {
                if      (d.length > 500) { errors.push('Description too long: ' + d.length + ' chars (max 500)');          descStatus = 'error'; }
                else if (d.length > 160) { warnings.push('Description long: ' + d.length + ' chars (Google shows ~160)');  descStatus = 'warn'; }
                else if (d.length >= 120) { descStatus = 'ok'; }
                else if (d.length < 50)  { warnings.push('Description short: ' + d.length + ' chars (ideal ≥ 50)');        descStatus = 'warn'; }
                else                     { warnings.push('Description could be longer: ' + d.length + ' chars (ideal 120-160)'); descStatus = 'warn'; }
            }

            // Nothing to save
            if (!t && !d && !errors.length) {
                errors.push('Both title and description are empty — nothing to save');
            }

            const status = errors.length ? 'error' : warnings.length ? 'warning' : 'valid';
            return {
                rowNum: row._line || (idx + 2),
                url,
                normalizedUrl,
                meta_title:       t,
                meta_description: d,
                errors,
                warnings,
                status,
                titleStatus,
                descStatus,
            };
        });
    }

    /* ── Render validation table ─────────────────── */
    function renderValidationResults(rows, meta) {
        const total      = rows.length;
        const valid      = rows.filter(r => r.status === 'valid').length;
        const warned     = rows.filter(r => r.status === 'warning').length;
        const errCount   = rows.filter(r => r.status === 'error').length;
        const importable = valid + warned;

        // File info bar
        let metaBar = '';
        if (meta) {
            metaBar = '<span class="schemafy-mtm-val-sum-item" style="color:#71717a;margin-left:auto;font-size:11px;">' +
                'delimiter: ' + escapeHtml(meta.delimiter) +
                (!meta.has_title ? ' · <span style="color:#f59e0b;">no title col</span>' : '') +
                (!meta.has_desc  ? ' · <span style="color:#f59e0b;">no description col</span>' : '') +
                (meta.parse_warns && meta.parse_warns.length
                    ? ' · <span style="color:#ef4444;" title="' + escapeHtml(meta.parse_warns.join('\n')) + '">⚠ ' + meta.parse_warns.length + ' parse issue(s)</span>'
                    : '') +
                '</span>';
        }

        $('#schemafy-mtm-val-summary').html(
            '<span class="schemafy-mtm-val-sum-item"><span class="dot dot-total"></span>' + total + ' rows</span>' +
            '<span class="schemafy-mtm-val-sum-item"><span class="dot dot-valid"></span>' + valid + ' ready</span>' +
            (warned   ? '<span class="schemafy-mtm-val-sum-item"><span class="dot dot-warn"></span>'  + warned   + ' warnings</span>' : '') +
            (errCount ? '<span class="schemafy-mtm-val-sum-item"><span class="dot dot-error"></span>' + errCount + ' errors (skip)</span>' : '') +
            metaBar
        );

        // Table rows
        let tbody = '';
        rows.forEach(function(r) {
            const rowClass   = r.status === 'error' ? 'row-error' : r.status === 'warning' ? 'row-warn' : 'row-valid';
            const titleChars = r.meta_title       ? r.meta_title.length       : 0;
            const descChars  = r.meta_description ? r.meta_description.length : 0;

            const tBadge = r.meta_title
                ? '<span class="schemafy-mtm-char-badge char-' + r.titleStatus + '">' + titleChars + '/' + META_TITLE_MAX + '</span>'
                : '<span class="schemafy-mtm-char-badge char-empty">—</span>';
            const dBadge = r.meta_description
                ? '<span class="schemafy-mtm-char-badge char-' + r.descStatus + '">' + descChars + '/' + META_DESCRIPTION_MAX + '</span>'
                : '<span class="schemafy-mtm-char-badge char-empty">—</span>';

            const allIssues = r.errors.map(e   => '<span class="err">✗ ' + escapeHtml(e) + '</span>').join('<br>') +
                              r.warnings.map(w => '<span class="wrn">⚠ ' + escapeHtml(w) + '</span>').join('<br>');

            const badge = r.status === 'error'   ? '<span class="schemafy-mtm-status-badge badge-error">✗ Error</span>'   :
                          r.status === 'warning'  ? '<span class="schemafy-mtm-status-badge badge-warn">⚠ Warning</span>' :
                                                    '<span class="schemafy-mtm-status-badge badge-valid">✓ Valid</span>';

            tbody +=
                '<tr class="' + rowClass + '">' +
                '<td style="color:#a1a1aa;font-size:11px;">' + r.rowNum + '</td>' +
                '<td class="schemafy-mtm-url-cell" title="' + escapeHtml(r.url || '') + '">' + escapeHtml((r.url || '').replace(/^https?:\/\//, '')) + '</td>' +
                '<td>' + tBadge + (r.meta_title       ? '<br><span style="font-size:11px;color:#52525b;">' + escapeHtml(r.meta_title.slice(0, 45))       + (r.meta_title.length       > 45 ? '…' : '') + '</span>' : '') + '</td>' +
                '<td>' + dBadge + (r.meta_description ? '<br><span style="font-size:11px;color:#52525b;">' + escapeHtml(r.meta_description.slice(0, 55)) + (r.meta_description.length > 55 ? '…' : '') + '</span>' : '') + '</td>' +
                '<td class="schemafy-mtm-issues">' + (allIssues || '<span style="color:#a1a1aa;">—</span>') + '</td>' +
                '<td>' + badge + '</td>' +
                '</tr>';
        });

        $('#schemafy-mtm-val-tbody').html(tbody);

        // Footer + import button
        if (importable > 0) {
            $('#schemafy-mtm-import-note').text(
                errCount ? errCount + ' row(s) with errors will be skipped.' : 'All rows ready to import.'
            );
            $('#schemafy-mtm-import-btn').prop('disabled', false);
            $('#schemafy-mtm-import-btn-label').text('Import ' + importable + ' row' + (importable !== 1 ? 's' : ''));
        } else {
            $('#schemafy-mtm-import-note').text('No importable rows. Fix errors and re-upload.');
            $('#schemafy-mtm-import-btn').prop('disabled', true);
            $('#schemafy-mtm-import-btn-label').text('Import');
        }

        $('#schemafy-mtm-import-result').hide();
        $('#schemafy-mtm-val-results').show();
    }

    /* Inline error — no alert() */
    function showBulkError(msg) {
        bulkParsedRows = [];
        $('#schemafy-mtm-csv-file').val('');
        $('#schemafy-mtm-val-results').hide();
        $('#schemafy-mtm-import-result')
            .removeClass('import-result-success')
            .addClass('import-result-error')
            .html('<strong>✗ Error:</strong> ' + escapeHtml(msg))
            .show();
    }

    /* ── Run Import ──────────────────────────────── */
    function runBulkImport(rows) {
        const $btn    = $('#schemafy-mtm-import-btn');
        const $result = $('#schemafy-mtm-import-result');
        const total   = rows.length;

        $btn.prop('disabled', true)
            .html('<span class="dashicons dashicons-image-rotate spin" aria-hidden="true"></span> ' +
                  '<span id="schemafy-mtm-import-btn-label">Importing ' + total + ' row' + (total !== 1 ? 's' : '') + '…</span>');

        // Send normalized URLs so PHP receives the same string used for dedup
        const payload = rows.map(r => ({
            url:              r.normalizedUrl || r.url,
            meta_title:       r.meta_title,
            meta_description: r.meta_description,
        }));

        $.ajax({
            url:     schemafy_ajax.ajax_url,
            type:    'POST',
            timeout: 120000, // mirror PHP set_time_limit(120)
            data: {
                action: 'schemafy_bulk_import_meta_tags',
                nonce:  schemafy_ajax.nonce,
                rows:   JSON.stringify(payload),
            },

            success: function(response) {
                $btn.prop('disabled', false)
                    .html('<span id="schemafy-mtm-import-btn-label">Import ' + total + ' row' + (total !== 1 ? 's' : '') + '</span>');

                if (response.success) {
                    const d = response.data;
                    const newCnt  = d.new     || 0;
                    const updCnt  = d.updated || 0;
                    const skipCnt = d.skipped || 0;

                    const parts = [];
                    if (newCnt)  parts.push(newCnt  + ' new');
                    if (updCnt)  parts.push(updCnt  + ' updated');
                    if (skipCnt) parts.push(skipCnt + ' skipped (invalid URL)');

                    $result
                        .removeClass('import-result-error')
                        .addClass('import-result-success')
                        .html(
                            '<strong>✓ Import complete.</strong> ' + parts.join(', ') + '.' +
                            ' <a href="#" id="schemafy-mtm-reload-list" style="margin-left:8px;font-weight:600;">Reload page list ↺</a>' +
                            ' <a href="#" id="schemafy-mtm-import-another" style="margin-left:8px;font-weight:600;color:#6366f1;">Import another file →</a>'
                        )
                        .show();

                    // Reset so user can immediately import another file
                    $('#schemafy-mtm-csv-file').val('');
                    bulkParsedRows = [];

                    $(document).one('click', '#schemafy-mtm-reload-list', function(e) {
                        e.preventDefault();
                        $('#schemafy-mtm-url-list').html(
                            '<div style="padding:24px 16px;text-align:center;">' +
                            '<div class="schemafy-spinner-v2" style="margin:0 auto 10px;"></div>' +
                            '<p style="color:#a1a1aa;font-size:12px;margin:0;">Reloading…</p></div>'
                        );
                        loadPages();
                    });

                    $(document).one('click', '#schemafy-mtm-import-another', function(e) {
                        e.preventDefault();
                        resetBulkState();
                    });

                } else {
                    const errMsg = getResponseMessage(response, text('unknown_error', 'Unknown error'));
                    $result
                        .removeClass('import-result-success')
                        .addClass('import-result-error')
                        .html('<strong>✗ Import failed:</strong> ' + escapeHtml(errMsg))
                        .show();
                }
            },

            error: function(jqXHR, textStatus) {
                $btn.prop('disabled', false)
                    .html('<span id="schemafy-mtm-import-btn-label">Import ' + total + ' row' + (total !== 1 ? 's' : '') + '</span>');

                let msg = 'Network error. Check your connection and try again.';
                if (textStatus === 'timeout') {
                    msg = 'Request timed out after 2 minutes. Try splitting your CSV into batches of 200 rows or less.';
                } else if (jqXHR.status === 413) {
                    msg = 'Payload too large. Reduce the number of rows per batch.';
                } else if (jqXHR.status === 403) {
                    msg = 'Session expired. Please refresh the page and try again.';
                } else if (jqXHR.status >= 500) {
                    msg = 'Server error (' + jqXHR.status + '). Try a smaller batch or check your server logs.';
                } else if (jqXHR.status === 0) {
                    msg = 'Connection lost. Check your network and try again.';
                }

                $result
                    .removeClass('import-result-success')
                    .addClass('import-result-error')
                    .html('<strong>✗ Error:</strong> ' + escapeHtml(msg))
                    .show();
            },
        });
    }


})(jQuery);
