jQuery(document).ready(function ($) {
    // Invoice number live preview
    function updateInvoicePreview() {
        var $preview = $('#freefactu-preview-number');
        if (!$preview.length) return;

        var prefix = $('#freefactu_prefix').val() || '';
        var number = $('#freefactu_next_number').val() || '1';
        var suffix = $('#freefactu_suffix').val() || '';
        var padding = parseInt($('#freefactu_padding').val()) || 0;

        // Replace date placeholders
        var now = new Date();
        var year = now.getFullYear().toString();
        var month = ('0' + (now.getMonth() + 1)).slice(-2);
        var day = ('0' + now.getDate()).slice(-2);

        prefix = prefix.replace(/\[year\]/g, year)
            .replace(/\[month\]/g, month)
            .replace(/\[day\]/g, day);
        suffix = suffix.replace(/\[year\]/g, year)
            .replace(/\[month\]/g, month)
            .replace(/\[day\]/g, day);

        // Apply padding
        var formattedNumber = number;
        if (padding > 0) {
            formattedNumber = number.toString().padStart(padding, '0');
        }

        var result = prefix + formattedNumber + suffix;

        // Animate the update
        $preview.fadeOut(100, function () {
            $(this).text(result || '1').fadeIn(100);
        });
    }

    // Bind to numbering fields
    $(document).on('input', '.freefactu-numbering-field', updateInvoicePreview);

    // Rectificativa invoice number live preview
    function updateRectificativaPreview() {
        var $preview = $('#freefactu-rectificativa-preview-number');
        if (!$preview.length) return;

        var prefix = $('#freefactu_rectificativa_prefix').val() || 'R-';
        var number = $('#freefactu_rectificativa_next_number').val() || '1';
        var suffix = $('#freefactu_rectificativa_suffix').val() || '';
        var padding = parseInt($('#freefactu_rectificativa_padding').val()) || 0;

        // Replace date placeholders
        var now = new Date();
        var year = now.getFullYear().toString();
        var month = ('0' + (now.getMonth() + 1)).slice(-2);
        var day = ('0' + now.getDate()).slice(-2);

        prefix = prefix.replace(/\[year\]/g, year)
            .replace(/\[month\]/g, month)
            .replace(/\[day\]/g, day);
        suffix = suffix.replace(/\[year\]/g, year)
            .replace(/\[month\]/g, month)
            .replace(/\[day\]/g, day);

        // Apply padding
        var formattedNumber = number;
        if (padding > 0) {
            formattedNumber = number.toString().padStart(padding, '0');
        }

        var result = prefix + formattedNumber + suffix;

        // Animate the update
        $preview.fadeOut(100, function () {
            $(this).text(result || 'R-1').fadeIn(100);
        });
    }

    // Bind to rectificativa numbering fields
    $(document).on('input', '.freefactu-rectificativa-numbering-field', updateRectificativaPreview);

    // Certificate upload handler
    $(document).on('change', '.freefactu-cert-input', function () {
        var $input = $(this);
        var file = this.files[0];

        if (!file) return;

        // Validate file extension
        var ext = file.name.split('.').pop().toLowerCase();
        if (ext !== 'p12' && ext !== 'pfx') {
            alert(freefactu_params.i18n.select_file);
            $input.val('');
            return;
        }

        var $container = $('#freefactu-cert-container');
        var $card = $container.find('.freefactu-cert-card');
        var $uploadBtn = $card.find('.freefactu-upload-cert-btn');
        var originalBtnHtml = $uploadBtn.html();

        // Show loading state with spinner
        $card.css('opacity', '0.6');
        $card.find('button, label').css('pointer-events', 'none');
        $uploadBtn.html('<span class="dashicons dashicons-update spin" style="vertical-align: middle;"></span> ' + freefactu_params.i18n.uploading);

        var formData = new FormData();
        formData.append('action', 'freefactu_upload_certificate');
        formData.append('security', freefactu_params.upload_cert_nonce);
        formData.append('certificate', file);

        $.ajax({
            url: ajaxurl,
            type: 'POST',
            data: formData,
            processData: false,
            contentType: false,
            success: function (response) {
                if (response.success && response.data.html) {
                    // Seamlessly update the UI
                    $container.html(response.data.html);
                    // Update has_certificate flag
                    freefactu_params.has_certificate = true;
                } else {
                    alert(freefactu_params.i18n.error + ': ' + (response.data || 'Error desconocido'));
                    $card.css('opacity', '1');
                    $card.find('button, label').css('pointer-events', 'auto');
                    $uploadBtn.html(originalBtnHtml);
                }
            },
            error: function (xhr, textStatus, errorThrown) {
                console.error('Certificate upload error:', {
                    status: xhr.status,
                    statusText: xhr.statusText,
                    responseText: xhr.responseText,
                    textStatus: textStatus,
                    errorThrown: errorThrown
                });
                // Try to extract server error message from JSON response
                var errorMsg = 'Error de conexión';
                try {
                    var resp = JSON.parse(xhr.responseText);
                    if (resp && resp.data) {
                        errorMsg = typeof resp.data === 'string' ? resp.data : (resp.data.message || errorMsg);
                    }
                } catch (e) {
                    // Not JSON, use generic message with status
                    if (xhr.status) {
                        errorMsg += ' (HTTP ' + xhr.status + ')';
                    }
                }
                alert(freefactu_params.i18n.error + ': ' + errorMsg);
                $card.css('opacity', '1');
                $card.find('button, label').css('pointer-events', 'auto');
                $uploadBtn.html(originalBtnHtml);
            }
        });
    });

    // Remove certificate handler
    $(document).on('click', '.freefactu-remove-cert', function (e) {
        e.preventDefault();
        e.stopPropagation();

        if (!confirm(freefactu_params.i18n.confirm_remove)) {
            return false;
        }

        var $button = $(this);
        var $container = $('#freefactu-cert-container');
        var $card = $container.find('.freefactu-cert-card');

        // Show loading state with spinner
        $card.css('opacity', '0.6');
        $card.find('button, label').css('pointer-events', 'none');
        $button.html('<span class="dashicons dashicons-update spin" style="vertical-align: middle;"></span> ' + freefactu_params.i18n.removing);

        $.ajax({
            url: ajaxurl,
            type: 'POST',
            data: {
                action: 'freefactu_remove_certificate',
                security: freefactu_params.remove_cert_nonce
            },
            success: function (response) {
                if (response.success && response.data.html) {
                    // Seamlessly update the UI
                    $container.html(response.data.html);
                    // Update has_certificate flag
                    freefactu_params.has_certificate = false;
                } else {
                    alert(freefactu_params.i18n.error + ': ' + (response.data || 'Error desconocido'));
                    $card.css('opacity', '1');
                    $card.find('button, label').css('pointer-events', 'auto');
                    $button.html('<span class="dashicons dashicons-trash" style="vertical-align: middle; margin-right: 3px;"></span> Eliminar');
                }
            },
            error: function () {
                alert(freefactu_params.i18n.error + ': Error de conexión');
                $card.css('opacity', '1');
                $card.find('button, label').css('pointer-events', 'auto');
                $button.html('<span class="dashicons dashicons-trash" style="vertical-align: middle; margin-right: 3px;"></span> Eliminar');
            }
        });

        return false;
    });

    // Clear QR cache handler
    $(document).on('click', '.freefactu-clear-qr-cache', function (e) {
        e.preventDefault();

        var confirmMessage = freefactu_params.i18n.confirm_clear_qr || '¿Estás seguro de que deseas limpiar la caché de códigos QR? Los códigos se regenerarán automáticamente cuando sea necesario.';
        if (!confirm(confirmMessage)) {
            return false;
        }

        var $button = $(this);
        var $container = $('#freefactu-qr-cache-container');
        var originalBtnHtml = $button.html();

        // Show loading state with spinner
        $button.prop('disabled', true);
        $button.html('<span class="dashicons dashicons-update spin" style="vertical-align: middle;"></span> ' + (freefactu_params.i18n.clearing || 'Limpiando...'));

        $.ajax({
            url: ajaxurl,
            type: 'POST',
            data: {
                action: 'freefactu_clear_qr_cache',
                security: freefactu_params.clear_qr_cache_nonce
            },
            success: function (response) {
                if (response.success) {
                    // Show success message
                    var successMessage = response.data.message || 'Caché limpiada correctamente.';
                    alert(successMessage);

                    // Update the description to show 0 cached items
                    var $description = $container.find('.description');
                    if ($description.length) {
                        $description.text(freefactu_params.i18n.no_qr_cache || 'No hay códigos QR en caché.');
                    }
                } else {
                    alert(freefactu_params.i18n.error + ': ' + (response.data || 'Error desconocido'));
                }

                // Restore button
                $button.prop('disabled', false);
                $button.html(originalBtnHtml);
            },
            error: function () {
                alert(freefactu_params.i18n.error + ': Error de conexión');
                $button.prop('disabled', false);
                $button.html(originalBtnHtml);
            }
        });

        return false;
    });

    // ============================================================================
    // CLEAR LOGS CONFIRMATION HANDLER
    // ============================================================================
    // Migrated from inline onclick in class-freefactu-debug.php

    $(document).on('click', 'input[name="clear_logs"]', function (e) {
        var confirmMessage = freefactu_params.i18n.confirm_clear_logs || '¿Estás seguro?';
        if (!confirm(confirmMessage)) {
            e.preventDefault();
            return false;
        }
        return true;
    });

    // ============================================================================
    // NIF DISPLAY FIELD POSITION HANDLER
    // ============================================================================
    // Migrated from inline wp_add_inline_script in class-freefactu-checkout-fields.php
    // Moves the NIF display field into the WooCommerce admin order address block

    (function initNifDisplayField() {
        var $nifDisplay = $('.freefactu-nif-display p');
        if (!$nifDisplay.length) {
            return; // Not on a relevant page
        }

        var $addressBlock = $nifDisplay.closest('.order_data_column').find('.address');

        // Try to insert after the company name in the address block
        // The address block content is text nodes and BRs.
        // Appending is safe and visible.
        if ($addressBlock.length && $nifDisplay.length) {
            $addressBlock.append($nifDisplay);
            $('.freefactu-nif-display').remove();
        }
    })();

    // ============================================================================
    // UNIFIED VERIFACTU INVOICE ACTION HANDLER
    // ============================================================================
    // This single event handler replaces all previous separate handlers for:
    // - Standalone mode: order list, order view metabox
    // - Integrated mode: order list, order view metabox
    // - Invoice list (Facturas Verifactu)
    //
    // All icons now use the centralized render_verifactu_icon_html() function
    // which adds the .freefactu-invoice-action class and data attributes.
    // ============================================================================

    $(document).on('click', '.freefactu-invoice-action:not(.freefactu-presupuesto-action)', function (e) {
        e.preventDefault();

        var $button = $(this);

        // Prevent duplicate clicks while loading
        if ($button.hasClass('loading')) {
            return;
        }

        // Extract data from attributes set by render_verifactu_icon_html()
        var orderId = $button.data('order-id');
        var status = $button.data('status') || 'normal';
        var context = $button.data('context') || 'unknown';

        console.log('Unified handler: order=' + orderId + ', status=' + status + ', context=' + context);

        // Validate order ID
        if (!orderId) {
            alert(freefactu_params.i18n.error + ': No se pudo determinar el ID del pedido.');
            console.error('Unified handler: Missing order ID');
            return;
        }

        // ============================================================================
        // CERTIFICATE VALIDATION
        // Certificate and declaration checks are now handled within showInvoiceTypeDialog()
        // which displays styled inline warnings instead of JavaScript confirm() dialogs.
        // This provides a better user experience and maintains visual consistency.
        // ============================================================================

        /**
         * Add loading state to the button.
         * - Adds 'loading' class for CSS styling
         * - Stores original icon HTML for restoration on error
         * - Disables pointer events via CSS
         */
        function addLoadingState() {
            // Store original icon wrapper HTML for restoration on error
            var $iconWrapper = $button.find('.freefactu-icon-wrapper');
            if ($iconWrapper.length) {
                $button.data('original-icon-html', $iconWrapper.html());
            }

            // Add loading class - CSS handles spinner display and pointer-events
            $button.addClass('loading');
        }

        /**
         * Remove loading state from the button.
         * - Removes 'loading' class
         * - Optionally restores original icon on error
         * @param {boolean} restoreIcon - Whether to restore original icon (for errors)
         */
        function removeLoadingState(restoreIcon) {
            $button.removeClass('loading');

            // Restore original icon HTML on error
            if (restoreIcon) {
                var originalHtml = $button.data('original-icon-html');
                if (originalHtml) {
                    var $iconWrapper = $button.find('.freefactu-icon-wrapper');
                    if ($iconWrapper.length) {
                        $iconWrapper.html(originalHtml);
                    }
                }
            }
        }

        /**
         * Display error to user and log to console.
         * - Shows error in the metabox instead of using alert
         * - Logs detailed error info to browser console for debugging
         * - Updates icon to alert state after error
         *
         * @param {string} errorType - Type of error ('network' or 'server')
         * @param {string} errorMessage - User-friendly error message
         * @param {object} debugInfo - Additional debug information for console
         * @param {string} metaboxHtml - Optional: pre-rendered metabox HTML from server
         */
        function displayError(errorType, errorMessage, debugInfo, metaboxHtml) {
            // Log detailed error to console for debugging (Requirement 8.6)
            console.error('Freefactu Error [' + errorType + ']:', errorMessage);
            if (debugInfo) {
                console.error('Debug info:', debugInfo);
            }

            // Remove loading state
            removeLoadingState(false);

            // Update button state to alert
            $button.removeClass('exists').addClass('alert');
            $button.data('status', 'alert_aeat');

            // Update the status badge in the icon wrapper
            var $iconWrapper = $button.find('.freefactu-icon-wrapper');
            if ($iconWrapper.length) {
                // Remove any existing badge
                $iconWrapper.find('.freefactu-status-badge').remove();
                // Add alert badge SVG
                $iconWrapper.append('<svg class="freefactu-status-badge freefactu-badge-alert" width="12" height="12" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M1 21h22L12 2 1 21z" fill="#ffb900"/><path d="M13 18h-2v-2h2v2zm0-4h-2v-4h2v4z" fill="#fff"/></svg>');
            }

            // Update button text
            var $buttonText = $button.find('.freefactu-icon-text');
            if ($buttonText.length) {
                $buttonText.text(freefactu_params.i18n.retry_invoice || 'Reintentar Factura');
            }

            // Display error in metabox if in order_view context
            if (context === 'order_view') {
                displayErrorInMetabox(orderId, errorMessage, metaboxHtml);
            } else {
                // For other contexts (order_list, invoice_list), redirect to order page to show error
                var orderUrl = freefactu_params.order_edit_url_base || '/wp-admin/admin.php?page=wc-orders&action=edit&id=';
                window.location.href = orderUrl + orderId;
            }
        }

        /**
         * Display error message in the metabox without page refresh.
         * 
         * @param {int} orderId - The order ID
         * @param {string} errorMessage - The error message to display
         * @param {string} metaboxHtml - Optional: pre-rendered metabox HTML from server
         */
        function displayErrorInMetabox(orderId, errorMessage, metaboxHtml) {
            var $metabox = $('.freefactu-meta-box-content');

            // If we have pre-rendered HTML from server, use it first
            if (metaboxHtml) {
                $metabox.replaceWith(metaboxHtml);
                // Re-query the metabox as the old element is removed from DOM
                $metabox = $('.freefactu-meta-box-content');
            }

            // Otherwise create an error display
            var $existingError = $metabox.find('.freefactu-inline-error');

            var errorHtml = '<div class="freefactu-inline-error" style="background: #fef0f0; border: 1px solid #d63638; border-radius: 4px; padding: 12px; margin-bottom: 12px;">' +
                '<p style="margin: 0 0 8px; color: #8b1c1c; font-weight: 600;">' +
                '<span class="dashicons dashicons-warning" style="color: #d63638; margin-right: 5px;"></span>' +
                (freefactu_params.i18n.error_title || 'Error al crear factura') +
                '</p>' +
                '<p style="margin: 0; color: #8b1c1c; font-size: 12px;">' +
                $('<div/>').text(errorMessage).html() + // Escape HTML
                '</p>' +
                '</div>';

            if ($existingError.length) {
                $existingError.replaceWith(errorHtml);
            } else {
                // Insert error after invoice info or at the top of the metabox
                var $invoiceInfo = $metabox.find('.freefactu-invoice-info');
                if ($invoiceInfo.length) {
                    $invoiceInfo.after(errorHtml);
                } else {
                    $metabox.prepend(errorHtml);
                }
            }

            // Optionally refresh the metabox from server to get accurate state
            refreshMetaboxContent(orderId);
        }

        /**
         * Refresh metabox content from server.
         * 
         * @param {int} orderId - The order ID
         */
        function refreshMetaboxContent(orderId) {
            $.ajax({
                url: ajaxurl,
                type: 'POST',
                data: {
                    action: 'freefactu_refresh_metabox',
                    order_id: orderId,
                    security: freefactu_params.unified_action_nonce
                },
                success: function (response) {
                    if (response.success && response.data.html) {
                        // Server returns complete metabox HTML including the outer div
                        $('.freefactu-meta-box-content').replaceWith(response.data.html);
                    }
                }
            });
        }

        /**
         * Handle network/connection errors from AJAX calls.
         *
         * @param {object} xhr - XMLHttpRequest object
         * @param {string} ajaxStatus - AJAX status string
         * @param {string} error - Error message
         */
        function handleNetworkError(xhr, ajaxStatus, error) {
            var errorMessage = freefactu_params.i18n.connection_error || 'Error de conexión';

            // Add more detail if available
            if (error && error !== 'error') {
                errorMessage += ' (' + error + ')';
            }

            displayError('network', errorMessage, {
                status: ajaxStatus,
                error: error,
                responseText: xhr.responseText,
                readyState: xhr.readyState,
                statusCode: xhr.status
            });
        }

        /**
         * Handle server errors from AJAX response.
         * @param {object} response - Server response object
         */
        function handleServerError(response) {
            // Extract error message from server response
            var errorMessage = 'Error desconocido';
            var metaboxHtml = null;

            if (response && response.data) {
                if (typeof response.data === 'string') {
                    errorMessage = response.data;
                } else if (response.data.message) {
                    errorMessage = response.data.message;
                }
                // Extract metabox HTML if provided by server
                if (response.data.metabox_html) {
                    metaboxHtml = response.data.metabox_html;
                }
            }

            displayError('server', errorMessage, {
                response: response
            }, metaboxHtml);
        }

        // For success status, open existing PDF directly without confirmation
        if (status === 'success') {
            // Add loading state before AJAX call
            addLoadingState();

            $.ajax({
                url: ajaxurl,
                type: 'POST',
                data: {
                    action: 'freefactu_unified_invoice_action',
                    order_id: orderId,
                    context: context,
                    security: freefactu_params.unified_action_nonce
                },
                success: function (response) {
                    // Remove loading state (no need to restore icon on success)
                    removeLoadingState(false);

                    if (response.success && response.data.pdf_url) {
                        // Navigate directly instead of opening new window to avoid popup blocking
                        window.location.href = response.data.pdf_url;
                    } else {
                        // Server returned error response (Requirement 8.2)
                        handleServerError(response);
                    }
                },
                error: function (xhr, ajaxStatus, error) {
                    // Network/connection error (Requirement 8.1)
                    handleNetworkError(xhr, ajaxStatus, error);
                }
            });
            return;
        }

        // Validation: Check onboarding requirements before proceeding with any retry/subsanar action
        // If requirements are missing, show the requirements dialog directly instead of the generic confirmation
        var onboarding = freefactu_params.onboarding || { all_complete: false };
        if (!onboarding.all_complete && (status === 'alert_aeat' || status === 'alert' || status === 'alert_qr' || status === 'alert_client')) {
            showInvoiceTypeDialog(orderId, context, $button, addLoadingState, removeLoadingState, handleServerError, handleNetworkError);
            return;
        }

        // Determine confirmation message based on status
        var confirmMessage;

        // Check if this is a subsanable AEAT error
        if ($button.hasClass('subsanable') && (status === 'alert_aeat' || status === 'alert')) {
            // For list views, redirect to order page instead of showing dialog
            if (context !== 'order_view') {
                console.log('Unified handler: Redirecting to order page for subsanation');
                var orderUrl = freefactu_params.order_edit_url_base || '/wp-admin/admin.php?page=wc-orders&action=edit&id=';
                window.location.href = orderUrl + orderId;
                return;
            }

            // Get error info from data attributes
            var errorCategory = $button.data('error-category') || '';
            var errorMessage = $button.data('error-message') || '';

            // Check if this error requires a fix dialog
            if (requiresFixDialog(errorCategory, errorMessage)) {
                console.log('Unified handler: Showing fix dialog for error category:', errorCategory);
                showErrorFixDialog(orderId, context, errorCategory, errorMessage, true, $button, addLoadingState, removeLoadingState, handleServerError, handleNetworkError);
                return;
            }

            // Standard subsanation (no dialog needed)
            confirmMessage = freefactu_params.i18n.confirm_subsanar || 'SUBSANACIÓN: Se creará un nuevo snapshot con los datos actualizados y se reenviará a la AEAT. ¿Deseas continuar?';

            if (!confirm(confirmMessage)) {
                console.log('Unified handler: User cancelled subsanation');
                return;
            }

            // Save order first then retry - this ensures any form changes (like NIF edits) are persisted
            // before creating the new snapshot for subsanation
            proceedWithSaveAndRetry(orderId, context, status, $button, addLoadingState, removeLoadingState, handleServerError, handleNetworkError);
            return;
        }

        if (status === 'alert_aeat' || status === 'alert_qr' || status === 'alert_client') {
            // For list views (order_list, invoice_list), redirect to order page to show error details
            if (context !== 'order_view') {
                console.log('Unified handler: Redirecting to order page for error details');
                var orderUrl = freefactu_params.order_edit_url_base || '/wp-admin/admin.php?page=wc-orders&action=edit&id=';
                window.location.href = orderUrl + orderId;
                return;
            }

            // Get error info from data attributes
            var errorCategory = $button.data('error-category') || '';
            var errorMessage = $button.data('error-message') || '';

            // Check if this error requires a fix dialog (e.g., client chaining errors)
            if (requiresFixDialog(errorCategory, errorMessage)) {
                console.log('Unified handler: Showing fix dialog for error category:', errorCategory);
                showErrorFixDialog(orderId, context, errorCategory, errorMessage, false, $button, addLoadingState, removeLoadingState, handleServerError, handleNetworkError);
                return;
            }

            // For order_view context, show retry confirmation
            confirmMessage = freefactu_params.i18n.confirm_retry || 'ATENCIÓN: Se intentará regenerar la factura Verifactu. ¿Deseas continuar?';

            // Show confirmation dialog for retries
            if (!confirm(confirmMessage)) {
                console.log('Unified handler: User cancelled');
                return;
            }

            // Save order first then retry (to capture any form changes)
            proceedWithSaveAndRetry(orderId, context, status, $button, addLoadingState, removeLoadingState, handleServerError, handleNetworkError);
            return;
        }

        // Normal status - show invoice type selection dialog
        showInvoiceTypeDialog(orderId, context, $button, addLoadingState, removeLoadingState, handleServerError, handleNetworkError);
    });

    // ============================================================================
    // LEGACY HANDLERS (kept for backward compatibility with old icon markup)
    // These will be removed in a future version once all icons use the new format
    // ============================================================================

    // Legacy: Standalone mode order list action - existing invoice (just open PDF)
    //$(document).on('click', '.wc-action-button-freefactu_invoice.exists:not(.freefactu-invoice-action)', function (e) {
    //    // Let the default behavior proceed (open PDF link)
    //    return true;
    //});

    // Legacy: Integrated mode - existing invoice (just open PDF)
    //$(document).on('click', '.verifactu_invoice.exists:not(.freefactu-invoice-action)', function (e) {
    //    // Let the default behavior proceed (open PDF link)
    //    return true;
    //});

    // ============================================================================
    // INTEGRATED MODE: ENHANCE WPO_WCPDF META BOX BUTTONS
    // ============================================================================
    // In integrated mode, our Verifactu button is rendered by WPO_WCPDF's meta box
    // which doesn't support custom data attributes. We need to add them via JS.
    // ============================================================================

    function enhanceWpoWcpdfVerifactuButtons() {
        // Find Verifactu buttons in WPO_WCPDF meta box that don't have our class yet
        var $buttons = $('.wpo_wcpdf-actions a.verifactu_invoice:not(.freefactu-invoice-action)');

        if ($buttons.length === 0) {
            return; // No buttons to enhance
        }

        console.log('Found ' + $buttons.length + ' WPO_WCPDF Verifactu button(s) to enhance');

        $buttons.each(function () {
            var $button = $(this);

            // Extract order ID from the page
            var orderId = null;

            // Try to get order ID from WooCommerce order edit page
            // Method 1: From URL parameter
            var urlParams = new URLSearchParams(window.location.search);
            orderId = urlParams.get('id') || urlParams.get('post');

            console.log('Method 1 (URL params): orderId=' + orderId);

            // Method 2: From hidden input on order edit page
            if (!orderId) {
                orderId = $('input[name="post_ID"]').val() || $('input#post_ID').val();
                console.log('Method 2 (hidden input): orderId=' + orderId);
            }

            // Method 3: From WooCommerce HPOS order edit page
            if (!orderId) {
                var match = window.location.pathname.match(/\/orders\/(\d+)/);
                if (match) {
                    orderId = match[1];
                    console.log('Method 3 (pathname): orderId=' + orderId);
                }
            }

            // Method 4: From WooCommerce HPOS - check for order ID in the page URL (admin.php?page=wc-orders&action=edit&id=123)
            if (!orderId) {
                var pageParam = urlParams.get('page');
                if (pageParam === 'wc-orders') {
                    orderId = urlParams.get('id');
                    console.log('Method 4 (wc-orders page): orderId=' + orderId);
                }
            }

            // Only enhance the button if we successfully found an order ID
            if (orderId) {
                // Add our class for the unified handler
                $button.addClass('freefactu-invoice-action');

                $button.attr('data-order-id', orderId);
                $button.attr('data-context', 'order_view');

                // Determine status from button classes
                var status = 'normal';
                if ($button.hasClass('alert')) {
                    status = 'alert_aeat'; // Default alert status
                } else if ($button.hasClass('exists')) {
                    status = 'success';
                }
                $button.attr('data-status', status);

                // Prevent default link behavior (WPO_WCPDF sets href="#")
                $button.attr('href', '#');
                $button.removeAttr('target');

                console.log('✓ Enhanced WPO_WCPDF Verifactu button: order=' + orderId + ', status=' + status);
            } else {
                console.error('✗ Could not determine order ID for WPO_WCPDF Verifactu button enhancement');
                console.error('URL:', window.location.href);
                console.error('Pathname:', window.location.pathname);
                console.error('Search:', window.location.search);
            }
        });
    }

    // Run on page load
    enhanceWpoWcpdfVerifactuButtons();

    // Also run after any AJAX calls that might reload the meta box
    $(document).ajaxComplete(function () {
        setTimeout(enhanceWpoWcpdfVerifactuButtons, 100);
    });

    // Debug: Log when document is ready
    console.log('Freefactu admin script loaded');

    // NOTE: The deprecated .freefactu-retry-invoice handler has been removed.
    // All invoice actions now use the unified handler via .freefactu-invoice-action class.
    // The History page (Facturas Verifactu) now uses render_verifactu_icon_html() which
    // generates icons with the .freefactu-invoice-action class.

    // ============================================================================
    // DECLARACION RESPONSABLE HANDLERS (Modal Wizard)
    // ============================================================================

    // Open declaration modal
    $(document).on('click', '#freefactu-new-declaration-btn, #freefactu-new-declaration-btn-empty', function (e) {
        e.preventDefault();
        $('#freefactu-declaration-modal').fadeIn(200);
        // Reset to step 1
        showWizardStep(1);
    });

    // Close declaration modal - close button (always close, regardless of child clicked)
    $(document).on('click', '.freefactu-modal-close', function (e) {
        e.preventDefault();
        $(this).closest('.freefactu-modal').fadeOut(200);
    });

    // Close declaration modal - overlay click (only when clicking directly on overlay)
    $(document).on('click', '.freefactu-modal-overlay', function (e) {
        if (e.target === this) {
            $(this).closest('.freefactu-modal').fadeOut(200);
        }
    });

    // Wizard step navigation - Next
    $(document).on('click', '.freefactu-wizard-next', function (e) {
        e.preventDefault();
        var nextStep = parseInt($(this).data('next'));
        var currentStep = nextStep - 1;

        // Validate current step
        if (currentStep === 1) {
            // Operator data comes from hidden fields (from settings)
            var operatorName = $('input[name="operator_name"]').val().trim();
            var operatorNif = $('input[name="operator_nif"]').val().trim();
            var softwareName = $('#declaration_software_name').val().trim();
            var producerName = $('#declaration_producer_name').val().trim();
            var producerNif = $('#declaration_producer_nif').val().trim();

            if (!operatorName || !operatorNif) {
                alert('Los datos del operador no están configurados. Por favor, complete los datos de la empresa en la pestaña Configuración.');
                return;
            }

            if (!producerName || !producerNif) {
                alert('Por favor, complete los datos del productor del SIF (Nombre y NIF).');
                return;
            }

            if (!softwareName) {
                alert('Por favor, introduzca un nombre para el sistema.');
                $('#declaration_software_name').focus();
                return;
            }

            if (softwareName.toLowerCase().indexOf('freefactu') !== -1) {
                alert('El nombre del sistema no puede contener "Freefactu". Por favor, use un nombre personalizado para su sistema (ej: "MiEmpresa SIF").');
                $('#declaration_software_name').focus();
                return;
            }

            // Validate version format (X.Y.Z)
            var softwareVersion = $('#declaration_software_version').val().trim();
            if (!softwareVersion) {
                alert('Por favor, introduzca una versión para el sistema (ej: 1.0.0).');
                $('#declaration_software_version').focus();
                return;
            }

            var versionPattern = /^\d+\.\d+\.\d+$/;
            if (!versionPattern.test(softwareVersion)) {
                alert('El formato de versión no es válido. Use el formato X.Y.Z (ej: 1.0.0, 1.1.0, 2.0.0).');
                $('#declaration_software_version').focus();
                return;
            }

            // Generate declaration content via AJAX when moving to step 2
            var $btn = $(this);
            var originalHtml = $btn.html();
            $btn.prop('disabled', true).html('<span class="dashicons dashicons-update spin"></span> Generando...');

            $.ajax({
                url: ajaxurl,
                type: 'POST',
                data: {
                    action: 'freefactu_generate_declaration_content',
                    declaration_nonce: $('input[name="declaration_nonce"]').val(),
                    operator_name: operatorName,
                    operator_nif: operatorNif,
                    software_name: softwareName,
                    software_version: softwareVersion,
                    software_id_code: $('#declaration_software_id_code').val() || 'FF',
                    installation_number: $('#declaration_installation_number').val(),
                    producer_name: producerName,
                    producer_nif: producerNif,
                    producer_address: $('#declaration_producer_address').val() || '',
                    producer_postal_code: $('#declaration_producer_postal_code').val() || '',
                    producer_city: $('#declaration_producer_city').val() || '',
                    producer_phone: $('#declaration_producer_phone').val() || '',
                    producer_email: $('#declaration_producer_email').val() || '',
                    producer_website: $('#declaration_producer_website').val() || ''
                },
                success: function (response) {
                    $btn.prop('disabled', false).html(originalHtml);
                    if (response.success) {
                        $('#declaration_content').val(response.data.content);
                        showWizardStep(nextStep);
                    } else {
                        alert('Error: ' + (response.data || 'Error al generar contenido'));
                    }
                },
                error: function () {
                    $btn.prop('disabled', false).html(originalHtml);
                    alert('Error de conexión. Por favor, inténtelo de nuevo.');
                }
            });
            return;
        }

        if (currentStep === 2) {
            // Validate declaration content
            var content = $('#declaration_content').val().trim();
            if (!content) {
                alert('El contenido de la declaración no puede estar vacío.');
                return;
            }
        }

        showWizardStep(nextStep);
    });

    // Wizard step navigation - Previous
    $(document).on('click', '.freefactu-wizard-prev', function (e) {
        e.preventDefault();
        var prevStep = parseInt($(this).data('prev'));
        showWizardStep(prevStep);
    });

    // Show wizard step
    function showWizardStep(step) {
        // Hide all step contents
        $('.freefactu-wizard-content').hide();
        // Show target step content
        $('.freefactu-wizard-content[data-step="' + step + '"]').fadeIn(200);

        // Update step indicators
        $('.freefactu-wizard-step').each(function () {
            var $step = $(this);
            var stepNum = parseInt($step.data('step'));

            $step.removeClass('active completed');
            $step.find('.step-number').removeAttr('style');
            $step.find('.step-label').removeAttr('style');
            $step.find('.step-connector').removeAttr('style');

            if (stepNum === step) {
                $step.addClass('active');
            } else if (stepNum < step) {
                $step.addClass('completed');
            }
        });

        // Step 2: Reset scroll state and disable continue button when entering
        if (step === 2) {
            var $textarea = $('#declaration_content');
            var $continueBtn = $('#freefactu-step2-continue');

            // Helper function to check if scrolled to bottom
            function checkScrollPosition() {
                if (!$continueBtn.prop('disabled')) return; // Already enabled

                var textarea = $textarea[0];
                if (!textarea) return;

                var scrollTop = textarea.scrollTop;
                var scrollHeight = textarea.scrollHeight;
                var clientHeight = textarea.clientHeight;

                // Consider "near bottom" as scrolled within 50px of the end
                // Or if content doesn't need scrolling at all
                var needsScroll = scrollHeight > clientHeight;
                var isNearBottom = scrollTop >= (scrollHeight - clientHeight - 50);

                if (!needsScroll || isNearBottom) {
                    $continueBtn.prop('disabled', false).removeAttr('title');
                    $textarea.off('scroll.step2'); // Remove handler once enabled
                }
            }

            // Reset scroll state - disable button until scrolled
            var tooltipText = 'Debes haber revisado la declaración para continuar';
            if (freefactu_params && freefactu_params.i18n && freefactu_params.i18n.scroll_to_continue) {
                tooltipText = freefactu_params.i18n.scroll_to_continue;
            }
            $continueBtn.prop('disabled', true).attr('title', tooltipText);

            // Wait for content to render, then set up scroll detection
            setTimeout(function () {
                if (!$textarea.length) return;

                // Bind scroll event directly to the textarea (scroll events don't bubble)
                $textarea.off('scroll.step2').on('scroll.step2', checkScrollPosition);

                // Check immediately in case content doesn't need scrolling
                // or user already scrolled before we bound the event
                checkScrollPosition();
            }, 150);
        }
    }

    // Save declaration form (Step 3)
    $(document).on('submit', '#freefactu-declaration-form', function (e) {
        e.preventDefault();

        // Validate confirmation checkbox
        if (!$('#declaration_confirm').is(':checked')) {
            alert('Debe aceptar la declaración de responsabilidad para continuar.');
            return;
        }

        // Validate software name is not empty or contains "freefactu"
        var softwareName = $('#declaration_software_name').val().trim();
        if (!softwareName) {
            alert('Por favor, introduzca un nombre para el sistema.');
            $('#declaration_software_name').focus();
            return;
        }
        if (softwareName.toLowerCase().indexOf('freefactu') !== -1) {
            alert('El nombre del sistema no puede contener "Freefactu". Por favor, use un nombre personalizado para su sistema (ej: "MiEmpresa SIF").');
            $('#declaration_software_name').focus();
            return;
        }

        var $form = $(this);
        var $submitBtn = $('#freefactu-submit-declaration');
        var $step3Actions = $('#freefactu-step3-actions');
        var $progressContainer = $('#freefactu-declaration-progress');
        var $progressList = $('#freefactu-progress-list');
        var $successContainer = $('#freefactu-declaration-success');
        var $errorContainer = $('#freefactu-declaration-error');
        var $errorMessage = $('#freefactu-declaration-error-message');
        var $confirmationBox = $('.freefactu-confirmation-box');
        var $sifInfoBox = $('#freefactu-sif-info');
        var $readyNotice = $('#freefactu-ready-to-generate-notice');

        // Hide step 3 action buttons (Anterior + Generar), SIF info, ready notice, and show progress
        $step3Actions.hide();
        $confirmationBox.hide();
        $sifInfoBox.hide();
        $readyNotice.hide();
        $errorContainer.hide();
        $progressContainer.show();
        $progressList.empty();

        // Progress steps
        var steps = [
            { id: 'validate', text: 'Validando datos del operador...', icon: '<span class="dashicons dashicons-search"></span>' },
            { id: 'content', text: 'Preparando contenido de la declaración...', icon: '<span class="dashicons dashicons-edit"></span>' },
            { id: 'pdf', text: 'Generando PDF de la declaración...', icon: '<span class="dashicons dashicons-media-document"></span>' },
            { id: 'zip_plugin', text: 'Comprimiendo código del plugin...', icon: '<span class="dashicons dashicons-archive"></span>' },
            { id: 'zip_uploads', text: 'Añadiendo facturas PDF al archivo...', icon: '<span class="dashicons dashicons-portfolio"></span>' },
            { id: 'zip_db', text: 'Exportando tablas de base de datos...', icon: '<span class="dashicons dashicons-database"></span>' },
            { id: 'finalize', text: 'Finalizando archivo SIF (ZIP)...', icon: '<span class="dashicons dashicons-star-filled"></span>' },
            { id: 'save', text: 'Guardando declaración en base de datos...', icon: '<span class="dashicons dashicons-download"></span>' }
        ];

        // Add progress items (all start with pending status)
        steps.forEach(function (step) {
            $progressList.append(
                '<li id="progress-' + step.id + '" class="freefactu-progress-item">' +
                '<span class="step-icon freefactu-progress-icon">' + step.icon + '</span>' +
                '<span class="step-text">' + step.text + '</span>' +
                '<span class="step-status freefactu-progress-status"></span>' +
                '</li>'
            );
        });

        // Track completed steps - only advance one step at a time with spinner
        var currentStepIndex = 0;
        var ajaxCompleted = false;
        var ajaxSuccess = false;

        // Show spinner on first step
        $progressList.find('li').eq(0).find('.step-status').html('<span class="dashicons dashicons-update spin" style="color: #2271b1;"></span>');

        // Animate through steps - mark previous as done, show spinner on current
        var stepInterval = setInterval(function () {
            if (ajaxCompleted) {
                clearInterval(stepInterval);
                return;
            }

            // Only advance if we're not at the last step yet
            // Keep the last step with a spinner until AJAX completes
            if (currentStepIndex < steps.length - 1) {
                // Mark current step as done
                $progressList.find('li').eq(currentStepIndex).find('.step-status').html('<span class="dashicons dashicons-yes" style="color: #46b450;"></span>');

                // Move to next step
                currentStepIndex++;

                // Show spinner on new current step
                $progressList.find('li').eq(currentStepIndex).find('.step-status').html('<span class="dashicons dashicons-update spin freefactu-progress-spinner"></span>');
            }
            // If we're at the last step, keep showing the spinner until AJAX completes
        }, 600);

        $.ajax({
            url: ajaxurl,
            type: 'POST',
            data: $form.serialize() + '&action=freefactu_save_declaration',
            success: function (response) {
                ajaxCompleted = true;
                ajaxSuccess = response.success;
                clearInterval(stepInterval);

                if (response.success) {
                    // Mark all remaining steps as complete (including the last one)
                    $progressList.find('li').each(function () {
                        $(this).find('.step-status').html('<span class="dashicons dashicons-yes freefactu-progress-check"></span>');
                    });

                    setTimeout(function () {
                        // Show success message (hide progress, keep actions hidden)
                        $progressContainer.hide();
                        $successContainer.show();
                    }, 500);
                } else {
                    // Show error container with close button
                    $progressContainer.hide();
                    $errorMessage.text(response.data || 'Error desconocido');
                    $errorContainer.show();
                    // Actions remain hidden - user must click Close button
                }
            },
            error: function () {
                ajaxCompleted = true;
                clearInterval(stepInterval);
                // Show error container with close button
                $progressContainer.hide();
                $errorMessage.text('Error de conexión. Por favor, inténtelo de nuevo.');
                $errorContainer.show();
                // Actions remain hidden - user must click Close button
            }
        });
    });

    // Declaration success OK button - reload the page
    $(document).on('click', '#freefactu-declaration-ok', function (e) {
        e.preventDefault();
        // Navigate to the SIF tab
        window.location.href = window.location.pathname + '?page=freefactu&tab=sif';
    });

    // Declaration error Close button - close the modal
    $(document).on('click', '#freefactu-declaration-close', function (e) {
        e.preventDefault();
        // Close the modal
        $('#freefactu-declaration-modal').fadeOut(200);
    });

    // Close modal on background click
    $(document).on('click', '#freefactu-declaration-view-modal', function (e) {
        if (e.target === this) {
            $(this).fadeOut(200);
        }
    });

    // Close modal on Escape key
    $(document).on('keydown', function (e) {
        if (e.key === 'Escape' && $('#freefactu-info-modal').is(':visible')) {
            $('#freefactu-info-modal').fadeOut(150).remove();
        }
        if (e.key === 'Escape' && $('#freefactu-declaration-view-modal').is(':visible')) {
            $('#freefactu-declaration-view-modal').fadeOut(200);
        }
        if (e.key === 'Escape' && $('#freefactu-invoice-type-dialog').is(':visible')) {
            $('#freefactu-invoice-type-dialog').fadeOut(200).remove();
        }
        if (e.key === 'Escape' && $('#freefactu-rectificativa-dialog').is(':visible')) {
            $('#freefactu-rectificativa-dialog').fadeOut(200).remove();
        }
    });

    // ============================================================================
    // INVOICE TYPE SELECTION DIALOG WITH ONBOARDING
    // ============================================================================

    /**
     * Show invoice type selection dialog with onboarding checklist
     * Displays comprehensive prerequisites in a beautiful modal
     */
    function showInvoiceTypeDialog(orderId, context, $button, addLoadingState, removeLoadingState, handleServerError, handleNetworkError) {
        var onboarding = freefactu_params.onboarding || { all_complete: false, steps: [] };
        var allComplete = onboarding.all_complete;

        // Build onboarding steps HTML
        var stepsHtml = '';
        var steps = onboarding.steps || [];

        for (var i = 0; i < steps.length; i++) {
            var step = steps[i];
            var isComplete = step.complete;
            var stepNumber = i + 1;

            // Step icon/status
            var statusIcon = isComplete
                ? '<div style="width: 32px; height: 32px; border-radius: 50%; background: linear-gradient(135deg, #46b450 0%, #2e7d32 100%); display: flex; align-items: center; justify-content: center; flex-shrink: 0;"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M20 6L9 17l-5-5" stroke="#fff" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/></svg></div>'
                : '<div style="width: 32px; height: 32px; border-radius: 50%; background: linear-gradient(135deg, #dcdcde 0%, #c3c4c7 100%); display: flex; align-items: center; justify-content: center; flex-shrink: 0; font-weight: 600; color: #50575e; font-size: 14px;">' + stepNumber + '</div>';

            // Build detail text based on step type
            var detailHtml = '';
            if (!isComplete) {
                switch (step.id) {
                    case 'system':
                        // Check if requirements are met but just need acknowledgment
                        if (step.data.needs_acknowledgment) {
                            detailHtml = '<span style="color: #996800; font-size: 12px;"><span class="dashicons dashicons-warning" style="font-size: 14px; width: 14px; height: 14px; vertical-align: text-bottom;"></span> Requisitos cumplidos, falta confirmar</span>';
                        } else if (!step.data.requirements_met) {
                            var issues = [];
                            if (!step.data.php_version_ok) issues.push('PHP ' + step.data.php_version + ' (requiere 7.4+)');
                            if (!step.data.openssl_ok) issues.push('OpenSSL no disponible');
                            if (!step.data.dom_ok) issues.push('Extensión DOM no disponible');
                            detailHtml = '<span style="color: #d63638; font-size: 12px;"><span class="dashicons dashicons-warning" style="font-size: 14px; width: 14px; height: 14px; vertical-align: text-bottom;"></span> ' + issues.join(', ') + '</span>';
                        } else {
                            detailHtml = '<span style="color: #996800; font-size: 12px;">Pendiente de verificar</span>';
                        }
                        break;
                    case 'series':
                        var missing = [];
                        if (!step.data.has_normal) missing.push('Serie para facturas normales');
                        if (!step.data.has_rectificativa) missing.push('Serie para rectificativas');
                        detailHtml = '<span style="color: #996800; font-size: 12px;">Falta: ' + missing.join(', ') + '</span>';
                        break;
                    case 'company':
                        var missing = [];
                        if (!step.data.has_name) missing.push('Razón Social');
                        if (!step.data.has_nif) missing.push('NIF/CIF');
                        if (!step.data.has_certificate) missing.push('Certificado');
                        else if (step.data.is_expired) missing.push('Certificado caducado');
                        detailHtml = '<span style="color: #996800; font-size: 12px;">Falta: ' + missing.join(', ') + '</span>';
                        break;
                    case 'declaration':
                        if (step.data.message) {
                            detailHtml = '<span style="color: #d63638; font-size: 12px;">' + step.data.message + '</span>';
                        } else {
                            detailHtml = '<span style="color: #996800; font-size: 12px;">Debe crear al menos una declaración</span>';
                        }
                        break;
                }
            } else {
                detailHtml = '<span style="color: #46b450; font-size: 12px;"><span class="dashicons dashicons-yes" style="font-size: 14px; width: 14px; height: 14px; vertical-align: text-bottom;"></span> Completado</span>';
            }

            // Action button (only for incomplete steps with URL or special cases)
            var actionHtml = '';
            if (!isComplete && step.id === 'system') {
                // System step always shows "Ver requisitos" button
                actionHtml = '<button type="button" class="button button-small freefactu-view-system-requirements" data-fingerprint="' + (step.data.fingerprint || '') + '" data-requirements-met="' + (step.data.requirements_met ? '1' : '0') + '" style="margin-left: auto; flex-shrink: 0; font-size: 11px;">Ver requisitos</button>';
            } else if (!isComplete && step.url && step.action) {
                actionHtml = '<a href="' + step.url + '" class="button button-small" style="margin-left: auto; flex-shrink: 0; font-size: 11px;">' + step.action + '</a>';
            }

            // Step row styling
            var rowBg = isComplete ? '#f0fdf0' : '#fffbf0';
            var rowBorder = isComplete ? '#c3e6cb' : '#ffeeba';

            stepsHtml += '<div style="display: flex; align-items: center; gap: 12px; padding: 12px 16px; background: ' + rowBg + '; border: 1px solid ' + rowBorder + '; border-radius: 8px; margin-bottom: 8px;">' +
                statusIcon +
                '<div style="flex: 1; min-width: 0;">' +
                '<div style="font-weight: 600; color: #1d2327; font-size: 13px; margin-bottom: 2px;">' + step.title + '</div>' +
                detailHtml +
                '</div>' +
                actionHtml +
                '</div>';
        }

        // Build invoice buttons section (only if all complete)
        var buttonsHtml = '';
        if (allComplete) {
            buttonsHtml = '<div>' +
                '<div style="display: flex; flex-direction: column; gap: 10px;">' +
                '<button type="button" id="freefactu-new-invoice-btn" class="button button-primary button-large" style="width: 100%; padding: 14px; font-size: 14px; display: flex; align-items: center; justify-content: center; gap: 8px;">' +
                '<span class="dashicons dashicons-media-document" style="line-height: 1;"></span>' +
                (freefactu_params.i18n.new_invoice || 'Nueva factura') +
                '</button>' +
                '<button type="button" id="freefactu-rectificativa-btn" class="button button-large" style="width: 100%; padding: 14px; font-size: 14px; background: linear-gradient(135deg, #f5af19 0%, #f12711 100%); border: none; color: #fff; display: flex; align-items: center; justify-content: center; gap: 8px; cursor: pointer;">' +
                '<span class="dashicons dashicons-undo" style="line-height: 1;"></span>' +
                (freefactu_params.i18n.rectificativa || 'Factura rectificativa') +
                '</button>' +
                '</div>' +
                '</div>';
        } else {
            buttonsHtml = '<div style="margin-top: 20px; padding: 16px; background: linear-gradient(135deg, #fef0f0 0%, #fce8e6 100%); border: 1px solid #f5c6cb; border-radius: 8px; text-align: center;">' +
                '<span class="dashicons dashicons-no" style="font-size: 32px; width: 32px; height: 32px; line-height: 32px; display: block; margin: 0 auto 8px; color: #dc3545;"></span>' +
                '<p style="margin: 0; color: #721c24; font-size: 13px; font-weight: 500;">Completa todos los pasos anteriores para poder crear facturas VeriFactu.</p>' +
                '</div>';
        }

        // Calculate completion progress
        var completedCount = 0;
        for (var j = 0; j < steps.length; j++) {
            if (steps[j].complete) completedCount++;
        }
        var progressPercent = Math.round((completedCount / steps.length) * 100);

        // Progress bar (only shown when not all complete)
        var progressColor = progressPercent === 100 ? '#46b450' : (progressPercent >= 50 ? '#ffb900' : '#dc3545');
        var progressHtml = '<div style="margin-bottom: 20px;">' +
            '<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;">' +
            '<span style="font-size: 12px; color: #646970;">Progreso de configuración</span>' +
            '<span style="font-size: 12px; font-weight: 600; color: ' + progressColor + ';">' + completedCount + '/' + steps.length + ' completados</span>' +
            '</div>' +
            '<div style="height: 8px; background: #e0e0e0; border-radius: 4px; overflow: hidden;">' +
            '<div style="height: 100%; width: ' + progressPercent + '%; background: linear-gradient(90deg, ' + progressColor + ' 0%, ' + (progressPercent === 100 ? '#2e7d32' : progressColor) + ' 100%); border-radius: 4px; transition: width 0.3s ease;"></div>' +
            '</div>' +
            '</div>';

        // Create dialog HTML - simplified when all complete
        var dialogHtml;
        if (allComplete) {
            // Simplified dialog - just header and buttons
            dialogHtml = '<div id="freefactu-invoice-type-dialog" style="position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.6); z-index: 100000; display: flex; align-items: center; justify-content: center; padding: 20px;">' +
                '<div class="freefactu-dialog-content" style="background: #fff; border-radius: 12px; box-shadow: 0 20px 60px rgba(0,0,0,0.3); max-width: 400px; width: 100%; overflow: hidden;">' +
                // Header
                '<div style="padding: 24px 24px 20px;">' +
                '<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 20px;">' +
                '<div style="width: 42px; height: 42px; border-radius: 6px; background: linear-gradient(135deg, #e4e4e4 0%, #f6f6f6 100%); display: flex; align-items: center; justify-content: center;">' +
                '<span class="dashicons dashicons-yes-alt" style="font-size: 24px; color: #46b450;"></span>' +
                '</div>' +
                '<div>' +
                '<h2 style="margin: 0; font-size: 18px; color: #1d2327;">' + (freefactu_params.i18n.invoice_type_title || 'Nueva factura VeriFactu') + '</h2>' +
                '<p style="margin: 2px 0 0; font-size: 13px; color: #46b450;">Sistema listo para facturar</p>' +
                '</div>' +
                '</div>' +
                buttonsHtml +
                '</div>' +
                // Footer
                '<div style="padding: 16px 24px; border-top: 1px solid #e0e0e0; background: #f9f9f9;">' +
                '<button type="button" id="freefactu-cancel-dialog" class="button" style="width: 100%; padding: 10px;">' +
                (freefactu_params.i18n.cancel || 'Cerrar') +
                '</button>' +
                '</div>' +
                '</div>' +
                '</div>';
        } else {
            // Full onboarding dialog with steps
            dialogHtml = '<div id="freefactu-invoice-type-dialog" style="position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.6); z-index: 100000; display: flex; align-items: center; justify-content: center; padding: 20px;">' +
                '<div class="freefactu-dialog-content" style="background: #fff; border-radius: 12px; box-shadow: 0 20px 60px rgba(0,0,0,0.3); max-width: 520px; width: 100%; max-height: 90vh; overflow: hidden; display: flex; flex-direction: column;">' +
                // Header
                '<div style="padding: 24px 24px 0; flex-shrink: 0;">' +
                '<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 16px;">' +
                '<div style="width: 48px; height: 48px; border-radius: 12px; background: linear-gradient(135deg, #2271b1 0%, #135e96 100%); display: flex; align-items: center; justify-content: center;">' +
                '<span class="dashicons dashicons-list-view" style="font-size: 24px; width: 24px; height: 24px; color: #fff;"></span>' +
                '</div>' +
                '<div>' +
                '<h2 style="margin: 0; font-size: 20px; color: #1d2327;">' + (freefactu_params.i18n.invoice_type_title || 'Nueva factura VeriFactu') + '</h2>' +
                '<p style="margin: 2px 0 0; font-size: 13px; color: #646970;">Requisitos para enviar facturas a AEAT</p>' +
                '</div>' +
                '</div>' +
                progressHtml +
                '</div>' +
                // Scrollable content
                '<div style="padding: 0 24px 24px; overflow-y: auto; flex: 1;">' +
                stepsHtml +
                buttonsHtml +
                '</div>' +
                // Footer
                '<div style="padding: 16px 24px; border-top: 1px solid #e0e0e0; background: #f9f9f9; flex-shrink: 0;">' +
                '<button type="button" id="freefactu-cancel-dialog" class="button" style="width: 100%; padding: 10px;">' +
                (freefactu_params.i18n.cancel || 'Cerrar') +
                '</button>' +
                '</div>' +
                '</div>' +
                '</div>';
        }

        // Remove any existing dialog
        $('#freefactu-invoice-type-dialog').remove();

        // Add to body
        $('body').append(dialogHtml);

        // Handle new invoice button
        $('#freefactu-new-invoice-btn').on('click', function () {
            $('#freefactu-invoice-type-dialog').fadeOut(200, function () {
                $(this).remove();
            });

            // Show confirmation for new invoice
            var confirmMessage = 'ATENCIÓN: ¿Estás seguro de enviar a Verifactu? La factura se enviará al sistema de Verifactu y no podrá ser modificada.';
            if (!confirm(confirmMessage)) {
                return;
            }

            // Proceed with invoice creation
            proceedWithInvoiceCreation(orderId, context, $button, addLoadingState, removeLoadingState, handleServerError, handleNetworkError);
        });

        // Handle rectificativa button
        $('#freefactu-rectificativa-btn').on('click', function () {
            $('#freefactu-invoice-type-dialog').fadeOut(200, function () {
                $(this).remove();
            });

            // Show rectificativa dialog
            showRectificativaDialog(orderId, context, $button, addLoadingState, removeLoadingState);
        });

        // Handle cancel button
        $('#freefactu-cancel-dialog').on('click', function () {
            $('#freefactu-invoice-type-dialog').fadeOut(200, function () {
                $(this).remove();
            });
        });

        // Handle "Ver requisitos" button for system requirements step
        $(document).on('click', '.freefactu-view-system-requirements', function (e) {
            e.preventDefault();
            e.stopPropagation();

            var $btn = $(this);
            var fingerprint = $btn.data('fingerprint');
            var requirementsMet = $btn.data('requirements-met') === 1 || $btn.data('requirements-met') === '1';

            showSystemRequirementsModal(fingerprint, requirementsMet);
        });

        // Close on background click
        $('#freefactu-invoice-type-dialog').on('click', function (e) {
            if (e.target === this) {
                $(this).fadeOut(200, function () {
                    $(this).remove();
                });
            }
        });
    }

    /**
     * Show system requirements modal with detailed checklist.
     * Displays all system requirements with green checks or red X marks.
     * When all requirements are met, shows an "Ok" button to acknowledge.
     *
     * @param {string} fingerprint - Current system requirements fingerprint
     * @param {boolean} requirementsMet - Whether all requirements are currently met
     */
    function showSystemRequirementsModal(fingerprint, requirementsMet) {
        var onboarding = freefactu_params.onboarding || { steps: [] };
        var systemStep = null;

        // Find the system step
        for (var i = 0; i < onboarding.steps.length; i++) {
            if (onboarding.steps[i].id === 'system') {
                systemStep = onboarding.steps[i];
                break;
            }
        }

        if (!systemStep) {
            console.error('System step not found in onboarding data');
            return;
        }

        var data = systemStep.data;

        // Build requirements list HTML
        var requirementsHtml = '';

        // PHP Version
        var phpIcon = data.php_version_ok
            ? '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="11" fill="#46b450"/><path d="M9 12l2 2 4-4" stroke="#fff" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>'
            : '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="11" fill="#d63638"/><path d="M15 9l-6 6M9 9l6 6" stroke="#fff" stroke-width="2" stroke-linecap="round"/></svg>';
        var phpColor = data.php_version_ok ? '#46b450' : '#d63638';
        var phpText = data.php_version_ok
            ? 'PHP ' + data.php_version + ' (≥7.4 requerido)'
            : 'PHP ' + data.php_version + ' (se requiere 7.4 o superior)';

        requirementsHtml += '<div style="display: flex; align-items: center; gap: 12px; padding: 12px; background: ' + (data.php_version_ok ? '#f0fdf0' : '#fef0f0') + '; border-radius: 8px; margin-bottom: 8px;">' +
            phpIcon +
            '<div style="flex: 1;">' +
            '<div style="font-weight: 500; color: #1d2327;">Versión de PHP</div>' +
            '<div style="font-size: 12px; color: ' + phpColor + ';">' + phpText + '</div>' +
            '</div>' +
            '</div>';

        // OpenSSL
        var opensslIcon = data.openssl_ok
            ? '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="11" fill="#46b450"/><path d="M9 12l2 2 4-4" stroke="#fff" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>'
            : '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="11" fill="#d63638"/><path d="M15 9l-6 6M9 9l6 6" stroke="#fff" stroke-width="2" stroke-linecap="round"/></svg>';
        var opensslColor = data.openssl_ok ? '#46b450' : '#d63638';
        var opensslText = data.openssl_ok
            ? 'Extensión disponible'
            : 'No disponible - contacta con tu proveedor de hosting';

        requirementsHtml += '<div style="display: flex; align-items: center; gap: 12px; padding: 12px; background: ' + (data.openssl_ok ? '#f0fdf0' : '#fef0f0') + '; border-radius: 8px; margin-bottom: 8px;">' +
            opensslIcon +
            '<div style="flex: 1;">' +
            '<div style="font-weight: 500; color: #1d2327;">Extensión OpenSSL</div>' +
            '<div style="font-size: 12px; color: ' + opensslColor + ';">' + opensslText + '</div>' +
            '</div>' +
            '</div>';

        // DOM Extension
        var domIcon = data.dom_ok
            ? '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="11" fill="#46b450"/><path d="M9 12l2 2 4-4" stroke="#fff" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>'
            : '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="11" fill="#d63638"/><path d="M15 9l-6 6M9 9l6 6" stroke="#fff" stroke-width="2" stroke-linecap="round"/></svg>';
        var domColor = data.dom_ok ? '#46b450' : '#d63638';
        var domText = data.dom_ok
            ? 'Extensión disponible'
            : 'No disponible - contacta con tu proveedor de hosting';

        requirementsHtml += '<div style="display: flex; align-items: center; gap: 12px; padding: 12px; background: ' + (data.dom_ok ? '#f0fdf0' : '#fef0f0') + '; border-radius: 8px; margin-bottom: 8px;">' +
            domIcon +
            '<div style="flex: 1;">' +
            '<div style="font-weight: 500; color: #1d2327;">Extensión DOM</div>' +
            '<div style="font-size: 12px; color: ' + domColor + ';">' + domText + '</div>' +
            '</div>' +
            '</div>';

        // GD/Imagick (optional, just for info)
        var gdIcon = data.gd_ok
            ? '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="11" fill="#46b450"/><path d="M9 12l2 2 4-4" stroke="#fff" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>'
            : '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="11" fill="#ffb900"/><path d="M12 8v4M12 16h.01" stroke="#fff" stroke-width="2" stroke-linecap="round"/></svg>';
        var gdColor = data.gd_ok ? '#46b450' : '#996800';
        var gdText = data.gd_ok
            ? 'Extensión disponible (GD o Imagick)'
            : 'Recomendado para generación de imágenes';

        requirementsHtml += '<div style="display: flex; align-items: center; gap: 12px; padding: 12px; background: ' + (data.gd_ok ? '#f0fdf0' : '#fffbeb') + '; border-radius: 8px; margin-bottom: 8px;">' +
            gdIcon +
            '<div style="flex: 1;">' +
            '<div style="font-weight: 500; color: #1d2327;">Extensión GD/Imagick</div>' +
            '<div style="font-size: 12px; color: ' + gdColor + ';">' + gdText + ' <span style="color: #646970;">(opcional)</span></div>' +
            '</div>' +
            '</div>';

        // Footer button(s)
        var buttonsHtml = '';
        if (requirementsMet) {
            buttonsHtml = '<div style="display: flex; gap: 10px;">' +
                '<button type="button" id="freefactu-system-req-ok" class="button button-primary" style="flex: 1; padding: 12px; font-size: 14px;" data-fingerprint="' + fingerprint + '">' +
                '<span class="dashicons dashicons-yes" style="line-height: 1.2;"></span> Ok' +
                '</button>' +
                '</div>';
        } else {
            buttonsHtml = '<div style="background: #fef0f0; border: 1px solid #f5c6cb; border-radius: 8px; padding: 16px; text-align: center;">' +
                '<p style="margin: 0 0 10px; color: #721c24; font-weight: 500;"><span class="dashicons dashicons-dismiss" style="font-size: 16px; color: #dc3232; vertical-align: text-bottom;"></span> No se cumplen todos los requisitos</p>' +
                '<p style="margin: 0; color: #721c24; font-size: 12px;">Contacta con tu proveedor de hosting para resolver los problemas indicados.</p>' +
                '</div>' +
                '<button type="button" id="freefactu-system-req-close" class="button" style="width: 100%; margin-top: 10px; padding: 10px;">Cerrar</button>';
        }

        // Build modal HTML
        var modalHtml = '<div id="freefactu-system-requirements-modal" style="position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.7); z-index: 100001; display: flex; align-items: center; justify-content: center; padding: 20px;">' +
            '<div style="background: #fff; border-radius: 12px; box-shadow: 0 20px 60px rgba(0,0,0,0.4); max-width: 480px; width: 100%; max-height: 90vh; overflow: hidden; display: flex; flex-direction: column;">' +
            // Header
            '<div style="padding: 20px 24px; border-bottom: 1px solid #e0e0e0; flex-shrink: 0;">' +
            '<div style="display: flex; align-items: center; gap: 12px;">' +
            '<div style="width: 44px; height: 44px; border-radius: 10px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); display: flex; align-items: center; justify-content: center;">' +
            '<span class="dashicons dashicons-desktop" style="font-size: 22px; color: #fff;"></span>' +
            '</div>' +
            '<div>' +
            '<h3 style="margin: 0; font-size: 18px; color: #1d2327;">Requisitos del Sistema</h3>' +
            '<p style="margin: 2px 0 0; font-size: 12px; color: #646970;">Verifica que tu servidor cumple con los requisitos</p>' +
            '</div>' +
            '</div>' +
            '</div>' +
            // Content
            '<div style="padding: 20px 24px; overflow-y: auto; flex: 1;">' +
            requirementsHtml +
            '</div>' +
            // Footer
            '<div style="padding: 16px 24px; border-top: 1px solid #e0e0e0; background: #f9f9f9; flex-shrink: 0;">' +
            buttonsHtml +
            '</div>' +
            '</div>' +
            '</div>';

        // Remove any existing modal
        $('#freefactu-system-requirements-modal').remove();

        // Add to body
        $('body').append(modalHtml);

        // Handle Ok button click (acknowledge requirements)
        $('#freefactu-system-req-ok').on('click', function () {
            var $btn = $(this);
            var fp = $btn.data('fingerprint');

            $btn.prop('disabled', true).html('<span class="dashicons dashicons-update spin" style="line-height: 1.2;"></span> Confirmando...');

            $.ajax({
                url: ajaxurl,
                type: 'POST',
                data: {
                    action: 'freefactu_ack_system_requirements',
                    security: freefactu_params.ack_system_requirements_nonce,
                    fingerprint: fp
                },
                success: function (response) {
                    if (response.success) {
                        // Close modal and refresh the page to update onboarding status
                        $('#freefactu-system-requirements-modal').fadeOut(200, function () {
                            $(this).remove();
                        });

                        // Close the invoice type dialog as well and refresh
                        $('#freefactu-invoice-type-dialog').fadeOut(200, function () {
                            $(this).remove();
                            // Reload page to get updated onboarding status
                            window.location.reload();
                        });
                    } else {
                        alert('Error: ' + (response.data || 'Error desconocido'));
                        $btn.prop('disabled', false).html('<span class="dashicons dashicons-yes" style="line-height: 1.2;"></span> Ok');
                    }
                },
                error: function () {
                    alert('Error de conexión. Por favor, inténtalo de nuevo.');
                    $btn.prop('disabled', false).html('<span class="dashicons dashicons-yes" style="line-height: 1.2;"></span> Ok');
                }
            });
        });

        // Handle close button click
        $('#freefactu-system-req-close').on('click', function () {
            $('#freefactu-system-requirements-modal').fadeOut(200, function () {
                $(this).remove();
            });
        });

        // Close on background click
        $('#freefactu-system-requirements-modal').on('click', function (e) {
            if (e.target === this) {
                $(this).fadeOut(200, function () {
                    $(this).remove();
                });
            }
        });

        // Close on Escape key
        $(document).on('keydown.systemReqModal', function (e) {
            if (e.key === 'Escape' && $('#freefactu-system-requirements-modal').is(':visible')) {
                $('#freefactu-system-requirements-modal').fadeOut(200, function () {
                    $(this).remove();
                });
                $(document).off('keydown.systemReqModal');
            }
        });
    }

    /**
     * Proceed with regular invoice creation.
     * For order_view context, saves the order first to capture any form changes
     * before sending to AEAT.
     */
    function proceedWithInvoiceCreation(orderId, context, $button, addLoadingState, removeLoadingState, handleServerError, handleNetworkError) {
        addLoadingState();

        // Determine which action to use based on context
        // For order_view, we always save the order first to capture any form changes
        var ajaxAction = 'freefactu_unified_invoice_action';
        var ajaxData = {
            action: ajaxAction,
            order_id: orderId,
            context: context,
            security: freefactu_params.unified_action_nonce
        };

        // For order_view context, save the order first to ensure all modifications are persisted
        if (context === 'order_view') {
            ajaxAction = 'freefactu_save_and_create_invoice';

            // Serialize the order form data to capture any changes made by the user
            // This includes billing fields (NIF, address, etc.) that may have been edited
            var formData = {};
            var $form = $('#order_data, #woocommerce-order-data, form#post, .woocommerce-order-data');

            if ($form.length) {
                // Get all input fields including billing fields
                $form.find('input, select, textarea').each(function () {
                    var $field = $(this);
                    var name = $field.attr('name');

                    if (name) {
                        // Handle checkboxes specially
                        if ($field.attr('type') === 'checkbox') {
                            formData[name] = $field.is(':checked') ? $field.val() : '';
                        } else {
                            formData[name] = $field.val();
                        }
                    }
                });
            }

            ajaxData = {
                action: ajaxAction,
                order_id: orderId,
                context: context,
                security: freefactu_params.unified_action_nonce,
                form_data: formData
            };
        }

        $.ajax({
            url: ajaxurl,
            type: 'POST',
            data: ajaxData,
            success: function (response) {
                if (response.success) {
                    removeLoadingState(false);
                    $button.removeClass('alert').addClass('exists');
                    $button.data('status', 'success');

                    if (response.data.pdf_url) {
                        window.location.href = response.data.pdf_url;
                    }
                } else {
                    handleServerError(response);
                }
            },
            error: function (xhr, ajaxStatus, error) {
                handleNetworkError(xhr, ajaxStatus, error);
            }
        });
    }

    /**
     * Save order and retry a failed invoice in one seamless operation.
     * This is used for order_view context when retrying failed invoices.
     * Saves order first to capture any form changes, then retries the invoice.
     * 
     * @param {int} orderId - The order ID
     * @param {string} context - The context (always order_view for this function)
     * @param {string} status - The current invoice status (alert_aeat, alert_client, etc.)
     * @param {jQuery} $button - The button element
     * @param {function} addLoadingState - Function to add loading state
     * @param {function} removeLoadingState - Function to remove loading state
     * @param {function} handleServerError - Function to handle server errors
     * @param {function} handleNetworkError - Function to handle network errors
     */
    function proceedWithSaveAndRetry(orderId, context, status, $button, addLoadingState, removeLoadingState, handleServerError, handleNetworkError) {
        // Validation: Check onboarding requirements before retrying
        // If requirements are missing (e.g. certificate expired, settings changed), show the requirements dialog
        var onboarding = freefactu_params.onboarding || { all_complete: false };
        if (!onboarding.all_complete) {
            showInvoiceTypeDialog(orderId, context, $button, addLoadingState, removeLoadingState, handleServerError, handleNetworkError);
            return;
        }
        // Hide existing errors immediately in order_view to indicate retry attempt
        if (context === 'order_view') {
            $('.freefactu-meta-box-content').find('.freefactu-inline-error, .freefactu-error-details').slideUp(200);
        }

        addLoadingState();

        // Serialize the order form data to capture any changes made by the user
        // This includes billing fields (NIF, address, etc.) that may have been edited
        var formData = {};
        var $form = $('#order_data, #woocommerce-order-data, form#post, .woocommerce-order-data');

        if ($form.length) {
            // Get all input fields including billing fields
            $form.find('input, select, textarea').each(function () {
                var $field = $(this);
                var name = $field.attr('name');

                if (name) {
                    // Handle checkboxes specially
                    if ($field.attr('type') === 'checkbox') {
                        formData[name] = $field.is(':checked') ? $field.val() : '';
                    } else {
                        formData[name] = $field.val();
                    }
                }
            });
        }

        // Build the AJAX data object
        var ajaxData = {
            action: 'freefactu_save_and_retry_invoice',
            order_id: orderId,
            status: status,
            context: context,
            security: freefactu_params.unified_action_nonce,
            form_data: formData
        };

        // Check if there's a huella_anterior field for hash_chain error subsanation
        var $huellaField = $('#freefactu_huella_anterior');
        var $idAnteriorField = $('#freefactu_id_anterior');
        var $fechaAnteriorField = $('#freefactu_fecha_anterior');

        if ($huellaField.length && $huellaField.val().trim()) {
            ajaxData.huella_anterior = $huellaField.val().trim();
        }

        if ($idAnteriorField.length && $idAnteriorField.val().trim()) {
            ajaxData.id_anterior = $idAnteriorField.val().trim();
        }

        if ($fechaAnteriorField.length && $fechaAnteriorField.val().trim()) {
            ajaxData.fecha_anterior = $fechaAnteriorField.val().trim();
        }

        $.ajax({
            url: ajaxurl,
            type: 'POST',
            data: ajaxData,
            success: function (response) {
                if (response.success) {
                    removeLoadingState(false);
                    $button.removeClass('alert subsanable').addClass('exists');
                    $button.data('status', 'success');

                    // Update button text and icon
                    var $buttonText = $button.find('.freefactu-icon-text');
                    if ($buttonText.length) {
                        $buttonText.text(freefactu_params.i18n.view_invoice || 'Ver Factura');
                    }

                    // Update status badge to success
                    var $iconWrapper = $button.find('.freefactu-icon-wrapper');
                    if ($iconWrapper.length) {
                        $iconWrapper.find('.freefactu-status-badge').remove();
                        $iconWrapper.append('<svg class="freefactu-status-badge freefactu-badge-success" width="12" height="12" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="11" fill="#46b450"/><path d="M9 12l2 2 4-4" stroke="#fff" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>');
                    }

                    if (response.data.pdf_url) {
                        window.location.href = response.data.pdf_url;
                    }
                } else {
                    handleServerError(response);
                }
            },
            error: function (xhr, ajaxStatus, error) {
                handleNetworkError(xhr, ajaxStatus, error);
            }
        });
    }

    /**
     * Show info modal for rectificativa options
     */
    function showRectificativaInfoModal(title, content) {
        var modalHtml = '<div id="freefactu-info-modal" style="position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.7); z-index: 100001; display: flex; align-items: center; justify-content: center; padding: 20px;">' +
            '<div style="background: #fff; padding: 25px 30px; border-radius: 12px; box-shadow: 0 15px 50px rgba(0,0,0,0.4); max-width: 500px; width: 100%; max-height: 80vh; overflow-y: auto;">' +
            '<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">' +
            '<h3 style="margin: 0; font-size: 18px; color: #1d2327;">' + title + '</h3>' +
            '<button type="button" id="freefactu-close-info-modal" style="background: none; border: none; font-size: 24px; cursor: pointer; color: #666; padding: 0; line-height: 1;">&times;</button>' +
            '</div>' +
            '<div style="color: #50575e; line-height: 1.6; font-size: 14px;">' + content + '</div>' +
            '</div>' +
            '</div>';

        $('#freefactu-info-modal').remove();
        $('body').append(modalHtml);

        $('#freefactu-close-info-modal, #freefactu-info-modal').on('click', function (e) {
            if (e.target === this || e.target.id === 'freefactu-close-info-modal') {
                $('#freefactu-info-modal').fadeOut(150, function () {
                    $(this).remove();
                });
            }
        });
    }

    /**
     * Check if error category requires a fix dialog based on error category.
     * @param {string} errorCategory - The error category (e.g., 'hash_chain', 'client')
     * @param {string} errorMessage - The error message (for detecting chaining errors in client errors)
     * @returns {boolean}
     */
    function requiresFixDialog(errorCategory, errorMessage) {
        // Check if category is in the dialog-required list
        var dialogCategories = freefactu_params.fix_dialog_categories || [];
        if (dialogCategories.indexOf(errorCategory) !== -1) {
            return true;
        }

        // Check if client error is about chaining
        if (errorCategory === 'client' && errorMessage) {
            var chainingPatterns = ['previousHash', 'previousInvoiceId', 'Previous hash', 'Previous invoice ID', 'huella anterior', 'factura anterior', 'encadenamiento'];
            var msgLower = errorMessage.toLowerCase();
            for (var i = 0; i < chainingPatterns.length; i++) {
                if (msgLower.indexOf(chainingPatterns[i].toLowerCase()) !== -1) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Show error fix dialog with dynamic fields based on error category.
     * Styled similar to showRectificativaDialog.
     */
    function showErrorFixDialog(orderId, context, errorCategory, errorMessage, isSubsanable, $button, addLoadingState, removeLoadingState, handleServerError, handleNetworkError) {
        // Validation: Check onboarding requirements first
        var onboarding = freefactu_params.onboarding || { all_complete: false };
        if (!onboarding.all_complete) {
            showInvoiceTypeDialog(orderId, context, $button, addLoadingState, removeLoadingState, handleServerError, handleNetworkError);
            return;
        }

        var i18n = freefactu_params.i18n || {};
        var fixFields = freefactu_params.fix_fields || {};

        // Determine which fields to show
        var fields = fixFields['hash_chain'] || [];

        // Dialog title based on category
        var dialogTitle = i18n.fix_dialog_hash_chain_title || 'Subsanar error de encadenamiento';
        if (errorCategory === 'client') {
            dialogTitle = i18n.fix_dialog_client_title || 'Corregir error de validación';
        }

        // Button text
        var submitText = isSubsanable
            ? (i18n.fix_submit_subsanar || 'Subsanar')
            : (i18n.fix_submit_retry || 'Reintentar');

        // Build field HTML
        var fieldsHtml = '';
        for (var i = 0; i < fields.length; i++) {
            var field = fields[i];
            var inputAttrs = 'type="' + (field.type || 'text') + '" ' +
                'id="freefactu-fix-' + field.name + '" ' +
                'name="' + field.name + '" ' +
                'placeholder="' + (field.placeholder || '') + '" ' +
                'style="width: 100%; padding: 10px; border: 1px solid #dcdcde; border-radius: 4px; font-size: 14px;' +
                (field.name === 'huella_anterior' ? ' font-family: monospace; font-size: 11px;' : '') + '"';

            if (field.maxlength) {
                inputAttrs += ' maxlength="' + field.maxlength + '"';
            }
            if (field.pattern) {
                inputAttrs += ' pattern="' + field.pattern + '"';
            }

            fieldsHtml += '<div style="margin-bottom: 15px;">' +
                '<label style="display: block; margin-bottom: 6px; font-weight: 600; color: #1d2327; font-size: 13px;">' +
                (field.label || field.name) +
                '</label>' +
                '<input ' + inputAttrs + '>' +
                (field.help ? '<p style="margin: 4px 0 0; color: #646970; font-size: 12px;">' + field.help + '</p>' : '') +
                '</div>';
        }

        // Build dialog HTML
        var dialogHtml = '<div id="freefactu-error-fix-dialog" style="position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.6); z-index: 100000; display: flex; align-items: center; justify-content: center; overflow-y: auto;">' +
            '<div class="freefactu-dialog-content" style="background: #fff; padding: 30px; border-radius: 8px; box-shadow: 0 10px 40px rgba(0,0,0,0.3); max-width: 500px; width: 95%; margin: 20px;">' +
            '<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 20px;">' +
            '<span class="dashicons dashicons-warning" style="font-size: 28px; margin-right: 8px; color: #dba617;"></span>' +
            '<h2 style="margin: 0; font-size: 20px; color: #1d2327;">' + dialogTitle + '</h2>' +
            '</div>' +
            '<p style="color: #646970; margin-bottom: 20px; font-size: 14px; line-height: 1.5;">' +
            (i18n.fix_dialog_description || 'Introduce los datos necesarios para corregir el error.') +
            '</p>' +
            (errorMessage ? '<div style="background: #fef0f0; border: 1px solid #d63638; border-radius: 4px; padding: 12px; margin-bottom: 20px;">' +
                '<p style="margin: 0; color: #8b1c1c; font-size: 13px;"><strong>Error:</strong> ' + errorMessage + '</p>' +
                '</div>' : '') +
            '<div class="freefactu-fix-fields">' + fieldsHtml + '</div>' +
            '<p style="color: #646970; font-size: 12px; margin-bottom: 20px; font-style: italic;">' +
            'Nota: Estos campos son opcionales si el sistema puede recuperar los datos automáticamente.' +
            '</p>' +
            '<div style="display: flex; gap: 10px;">' +
            '<button type="button" id="freefactu-fix-submit" class="button button-primary" style="flex: 1; padding: 12px; font-size: 14px; background: linear-gradient(135deg, #2271b1 0%, #135e96 100%); border: none;">' +
            submitText + '</button>' +
            '<button type="button" id="freefactu-fix-cancel" class="button" style="padding: 12px;">' +
            (i18n.cancel || 'Cancelar') + '</button>' +
            '</div></div></div>';

        $('#freefactu-error-fix-dialog').remove();
        $('body').append(dialogHtml);

        // Handle submit
        $('#freefactu-fix-submit').on('click', function () {
            var fixData = {};
            for (var j = 0; j < fields.length; j++) {
                var fieldName = fields[j].name;
                var value = $('#freefactu-fix-' + fieldName).val().trim();
                if (value) {
                    fixData[fieldName] = value;
                }
            }
            $('#freefactu-error-fix-dialog').fadeOut(200, function () { $(this).remove(); });
            proceedWithSaveAndRetryWithFixData(orderId, context, isSubsanable ? 'alert_aeat' : 'alert_client', fixData, $button, addLoadingState, removeLoadingState, handleServerError, handleNetworkError);
        });

        // Handle cancel and background click
        $('#freefactu-fix-cancel, #freefactu-error-fix-dialog').on('click', function (e) {
            if (e.target === this || e.target.id === 'freefactu-fix-cancel') {
                $('#freefactu-error-fix-dialog').fadeOut(200, function () { $(this).remove(); });
            }
        });
    }

    /**
     * Save order and retry with fix data from dialog.
     */
    function proceedWithSaveAndRetryWithFixData(orderId, context, status, fixData, $button, addLoadingState, removeLoadingState, handleServerError, handleNetworkError) {
        // Hide existing errors immediately in order_view to indicate retry attempt
        if (context === 'order_view') {
            $('.freefactu-meta-box-content').find('.freefactu-inline-error, .freefactu-error-details').slideUp(200);
        }

        addLoadingState();

        var formData = {};
        var $form = $('#order_data, #woocommerce-order-data, form#post, .woocommerce-order-data');
        if ($form.length) {
            $form.find('input, select, textarea').each(function () {
                var $field = $(this);
                var name = $field.attr('name');
                if (name) {
                    formData[name] = $field.attr('type') === 'checkbox'
                        ? ($field.is(':checked') ? $field.val() : '')
                        : $field.val();
                }
            });
        }

        var ajaxData = {
            action: 'freefactu_save_and_retry_invoice',
            order_id: orderId,
            status: status,
            context: context,
            security: freefactu_params.unified_action_nonce,
            form_data: formData
        };

        // Add fix data
        if (fixData.huella_anterior) ajaxData.huella_anterior = fixData.huella_anterior;
        if (fixData.id_anterior) ajaxData.id_anterior = fixData.id_anterior;
        if (fixData.fecha_anterior) ajaxData.fecha_anterior = fixData.fecha_anterior;

        $.ajax({
            url: ajaxurl,
            type: 'POST',
            data: ajaxData,
            success: function (response) {
                if (response.success) {
                    removeLoadingState(false);
                    $button.removeClass('alert subsanable').addClass('exists');
                    $button.data('status', 'success');
                    var $buttonText = $button.find('.freefactu-icon-text');
                    if ($buttonText.length) $buttonText.text(freefactu_params.i18n.view_invoice || 'Ver Factura');
                    var $iconWrapper = $button.find('.freefactu-icon-wrapper');
                    if ($iconWrapper.length) {
                        $iconWrapper.find('.freefactu-status-badge').remove();
                        $iconWrapper.append('<svg class="freefactu-status-badge freefactu-badge-success" width="12" height="12" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="11" fill="#46b450"/><path d="M9 12l2 2 4-4" stroke="#fff" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>');
                    }
                    if (response.data.pdf_url) window.location.href = response.data.pdf_url;
                } else {
                    handleServerError(response);
                }
            },
            error: function (xhr, ajaxStatus, error) {
                handleNetworkError(xhr, ajaxStatus, error);
            }
        });
    }

    /**
     * Show rectificativa form dialog
     */
    function showRectificativaDialog(orderId, context, $button, addLoadingState, removeLoadingState) {
        var i18n = freefactu_params.i18n;

        // Info content for each rectificativa type
        var infoR1 = '<p><strong>R1 — Rectificativa por error fundado en derecho</strong></p>' +
            '<p>Se usa cuando la factura original es <strong>inválida legalmente</strong>.</p>' +
            '<p>Hay un error jurídico: por ejemplo, tipo de IVA mal aplicado, sujeto pasivo equivocado, régimen fiscal incorrecto, etc.</p>' +
            '<p><span class="dashicons dashicons-arrow-right-alt"></span> <em>Ej.: pusiste IVA 10% y debía ser 21%.</em></p>' +
            '<p style="background: #f0f7ff; padding: 10px; border-radius: 6px; margin-top: 10px;"><strong>Es la causa más habitual.</strong></p>';

        var infoR2 = '<p><strong>R2 — Rectificativa por artículo 80.3 LIVA</strong></p>' +
            '<p>Artículo 80.3 LIVA: <strong>créditos incobrables</strong>.</p>' +
            '<p>Se usa cuando la empresa quiere modificar la base imponible por impago del cliente después del plazo legal.</p>' +
            '<p><span class="dashicons dashicons-arrow-right-alt"></span> <em>Ej.: un cliente no paga una factura después de 6 meses / 1 año y cumples todos los requisitos para modificar la BI.</em></p>';

        var infoR3 = '<p><strong>R3 — Rectificativa por artículo 80.4 LIVA</strong></p>' +
            '<p>Artículo 80.4 LIVA: <strong>concurso de acreedores</strong>.</p>' +
            '<p>Se usa cuando el cliente entra en concurso y la empresa rectifica la base imponible por este motivo.</p>' +
            '<p><span class="dashicons dashicons-arrow-right-alt"></span> <em>Ej.: el cliente está en concurso y se puede reducir la BI.</em></p>';

        var infoR4 = '<p><strong>R4 — Resto de rectificativas</strong></p>' +
            '<p>Para cualquier rectificativa que <strong>no sea R1, R2 o R3</strong>.</p>' +
            '<p><strong>Ejemplos:</strong></p>' +
            '<ul style="margin: 10px 0; padding-left: 20px;">' +
            '<li>Cambiar un dato no fiscal (dirección, nombre mal escrito…)</li>' +
            '<li>Devolver mercancía</li>' +
            '<li>Modificar unidades</li>' +
            '<li>Cambiar precio pactado</li>' +
            '<li>Error material no jurídico (cálculo mal hecho, etc.)</li>' +
            '</ul>' +
            '<p style="background: #fff8e5; padding: 10px; border-radius: 6px;"><span class="dashicons dashicons-arrow-right-alt"></span> <strong>Si no encaja en R1–R3, va a R4.</strong></p>';

        var infoR5 = '<p><strong>R5 — Rectificativa simplificada</strong></p>' +
            '<p>Rectificación de <strong>facturas simplificadas (tickets)</strong>.</p>' +
            '<p><strong>Solo para:</strong></p>' +
            '<ul style="margin: 10px 0; padding-left: 20px;">' +
            '<li>Facturas simplificadas emitidas sin datos del cliente</li>' +
            '<li>Tickets de TPV</li>' +
            '</ul>' +
            '<p><span class="dashicons dashicons-arrow-right-alt"></span> <em>Ej.: corregir un ticket en un restaurante.</em></p>';

        var infoMetodoS = '<p><strong>S — Sustitución (importe total correcto)</strong></p>' +
            '<p>La factura rectificativa <strong>sustituye por completo</strong> a la original.</p>' +
            '<p>En la rectificativa se pone:</p>' +
            '<ul style="margin: 10px 0; padding-left: 20px;">' +
            '<li>La base imponible correcta</li>' +
            '<li>El IVA correcto</li>' +
            '<li>El total correcto</li>' +
            '</ul>' +
            '<p>No se expresa la diferencia, sino el <strong>importe final definitivo</strong>.</p>' +
            '<p style="background: #e8f5e9; padding: 10px; border-radius: 6px; margin-top: 10px;"><span class="dashicons dashicons-arrow-right-alt"></span> <strong>Úsalo cuando quieres "recrear" la factura correcta.</strong></p>';

        var infoMetodoI = '<p><strong>I — Diferencias (solo la diferencia)</strong></p>' +
            '<p>Se declara solo la <strong>variación</strong> respecto a la factura original.</p>' +
            '<p>Los valores pueden ser <strong>negativos o positivos</strong>.</p>' +
            '<p style="background: #f5f5f5; padding: 12px; border-radius: 6px; margin: 15px 0;"><strong>Ejemplo:</strong><br>' +
            'Factura original: 100 €<br>' +
            'Debía ser: 80 €<br>' +
            'Rectificativa por diferencias (I): <strong>–20 €</strong></p>' +
            '<p style="background: #fff3e0; padding: 10px; border-radius: 6px;"><span class="dashicons dashicons-arrow-right-alt"></span> <strong>Úsalo cuando solo ajustas cantidades.</strong></p>';

        // Radio button styles
        var radioStyles = 'style="position: relative; display: flex; align-items: center; padding: 6px 8px; margin-bottom: 8px; background: #f9f9f9; border: 2px solid #dcdcde; border-radius: 8px; cursor: pointer; transition: all 0.2s ease;"';
        var radioInputStyles = 'style="margin: 0; margin-right: 12px; width: 18px; height: 18px; accent-color: #2271b1;"';
        var radioLabelStyles = 'style="flex: 1; font-size: 14px; color: #1d2327; cursor: pointer;"';
        var infoButtonStyles = 'style="width: 18px; height: 18px; border-radius: 50%; background: #2271b1; color: #fff; border: none; font-size: 12px; font-weight: bold; cursor: pointer; display: flex; align-items: center; justify-content: center; margin-left: 10px; flex-shrink: 0; transition: background 0.2s;"';

        var dialogHtml = '<div id="freefactu-rectificativa-dialog" style="position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.6); z-index: 100000; display: flex; align-items: center; justify-content: center; overflow-y: auto;">' +
            '<div class="freefactu-dialog-content" style="background: #fff; padding: 30px; border-radius: 8px; box-shadow: 0 10px 40px rgba(0,0,0,0.3); max-width: 650px; width: 95%; margin: 20px; max-height: 90vh; overflow-y: auto;">' +
            '<h2 style="margin: 0 0 20px; font-size: 20px; color: #1d2327;">' + (i18n.rectificativa_title || 'Crear factura rectificativa') + '</h2>' +

            // Invoice search section
            '<div style="margin-bottom: 20px;">' +
            '<label style="display: block; margin-bottom: 8px; font-weight: 600;">' + (i18n.select_original_invoice || 'Seleccionar factura a rectificar') + '</label>' +
            '<input type="text" id="freefactu-invoice-search" placeholder="' + (i18n.search_invoices || 'Buscar por número o pedido...') + '" style="width: 100%; padding: 10px; border: 1px solid #dcdcde; border-radius: 4px;">' +
            '<div id="freefactu-invoice-list" style="margin-top: 10px; max-height: 200px; overflow-y: auto; border: 1px solid #dcdcde; border-radius: 4px; display: none;"></div>' +
            '<div id="freefactu-selected-invoice" style="margin-top: 10px; padding: 12px; background: #f0f7ff; border: 1px solid #2271b1; border-radius: 4px; display: none;"></div>' +
            '<input type="hidden" id="freefactu-original-invoice-id" value="">' +
            '</div>' +

            // Tipo de rectificativa - Radio buttons
            '<div style="margin-bottom: 20px;">' +
            '<label style="display: block; margin-bottom: 12px; font-weight: 600; font-size: 15px;">' + (i18n.tipo_rectificativa || 'Tipo de rectificativa') + '</label>' +
            '<div class="freefactu-radio-group">' +

            '<label class="freefactu-radio-option" ' + radioStyles + ' data-value="R1">' +
            '<input type="radio" name="tipo_rectificativa" value="R1" checked ' + radioInputStyles + '>' +
            '<span ' + radioLabelStyles + '><strong>R1</strong> — Error fundado en derecho</span>' +
            '<button type="button" class="freefactu-info-btn" data-info="R1" ' + infoButtonStyles + '>i</button>' +
            '</label>' +

            '<label class="freefactu-radio-option" ' + radioStyles + ' data-value="R2">' +
            '<input type="radio" name="tipo_rectificativa" value="R2" ' + radioInputStyles + '>' +
            '<span ' + radioLabelStyles + '><strong>R2</strong> — Art. 80.3 LIVA (créditos incobrables)</span>' +
            '<button type="button" class="freefactu-info-btn" data-info="R2" ' + infoButtonStyles + '>i</button>' +
            '</label>' +

            '<label class="freefactu-radio-option" ' + radioStyles + ' data-value="R3">' +
            '<input type="radio" name="tipo_rectificativa" value="R3" ' + radioInputStyles + '>' +
            '<span ' + radioLabelStyles + '><strong>R3</strong> — Art. 80.4 LIVA (concurso)</span>' +
            '<button type="button" class="freefactu-info-btn" data-info="R3" ' + infoButtonStyles + '>i</button>' +
            '</label>' +

            '<label class="freefactu-radio-option" ' + radioStyles + ' data-value="R4">' +
            '<input type="radio" name="tipo_rectificativa" value="R4" ' + radioInputStyles + '>' +
            '<span ' + radioLabelStyles + '><strong>R4</strong> — Resto de rectificativas</span>' +
            '<button type="button" class="freefactu-info-btn" data-info="R4" ' + infoButtonStyles + '>i</button>' +
            '</label>' +

            '<label class="freefactu-radio-option" ' + radioStyles + ' data-value="R5">' +
            '<input type="radio" name="tipo_rectificativa" value="R5" ' + radioInputStyles + '>' +
            '<span ' + radioLabelStyles + '><strong>R5</strong> — Rectificativa simplificada (tickets)</span>' +
            '<button type="button" class="freefactu-info-btn" data-info="R5" ' + infoButtonStyles + '>i</button>' +
            '</label>' +

            '</div>' +
            '</div>' +

            // Método de rectificación - Radio buttons
            '<div style="margin-bottom: 20px;">' +
            '<label style="display: block; margin-bottom: 12px; font-weight: 600; font-size: 15px;">' + (i18n.metodo_rectificativa || 'Método de rectificación') + '</label>' +
            '<div class="freefactu-radio-group">' +

            '<label class="freefactu-radio-option" ' + radioStyles + ' data-value="S">' +
            '<input type="radio" name="metodo_rectificativa" value="S" checked ' + radioInputStyles + '>' +
            '<span ' + radioLabelStyles + '><strong>S</strong> — Por sustitución (importe total correcto)</span>' +
            '<button type="button" class="freefactu-info-btn" data-info="S" ' + infoButtonStyles + '>i</button>' +
            '</label>' +

            '<label class="freefactu-radio-option" ' + radioStyles + ' data-value="I">' +
            '<input type="radio" name="metodo_rectificativa" value="I" ' + radioInputStyles + '>' +
            '<span ' + radioLabelStyles + '><strong>I</strong> — Por diferencias (solo la diferencia)</span>' +
            '<button type="button" class="freefactu-info-btn" data-info="I" ' + infoButtonStyles + '>i</button>' +
            '</label>' +

            '</div>' +
            '</div>' +

            // Motivo
            '<div style="margin-bottom: 25px;">' +
            '<label style="display: block; margin-bottom: 8px; font-weight: 600;">' + (i18n.motivo || 'Motivo de la rectificación (opcional)') + '</label>' +
            '<textarea id="freefactu-motivo" rows="3" style="width: 100%; padding: 10px; border: 1px solid #dcdcde; border-radius: 4px; resize: vertical;"></textarea>' +
            '</div>' +

            // Buttons
            '<div style="display: flex; gap: 10px;">' +
            '<button type="button" id="freefactu-send-rectificativa" class="button button-primary" style="flex: 1; padding: 12px; font-size: 14px; background: linear-gradient(135deg, #f5af19 0%, #f12711 100%); border: none;" disabled>' +
            (i18n.send_rectificativa || 'Crear Rectificativa') +
            '</button>' +
            '<button type="button" id="freefactu-cancel-rectificativa" class="button" style="padding: 12px;">' +
            (i18n.cancel || 'Cancelar') +
            '</button>' +
            '</div>' +
            '</div>' +
            '</div>';

        $('body').append(dialogHtml);

        // Store info content for easy access
        var infoContent = {
            'R1': { title: 'R1 — Error fundado en derecho', content: infoR1 },
            'R2': { title: 'R2 — Art. 80.3 LIVA', content: infoR2 },
            'R3': { title: 'R3 — Art. 80.4 LIVA', content: infoR3 },
            'R4': { title: 'R4 — Resto de rectificativas', content: infoR4 },
            'R5': { title: 'R5 — Rectificativa simplificada', content: infoR5 },
            'S': { title: 'Método S — Sustitución', content: infoMetodoS },
            'I': { title: 'Método I — Diferencias', content: infoMetodoI }
        };

        // Handle info button clicks
        $(document).off('click.freefactu-info').on('click.freefactu-info', '.freefactu-info-btn', function (e) {
            e.preventDefault();
            e.stopPropagation();
            var infoKey = $(this).data('info');
            if (infoContent[infoKey]) {
                showRectificativaInfoModal(infoContent[infoKey].title, infoContent[infoKey].content);
            }
        });

        // Info button hover effects
        $('.freefactu-info-btn').on('mouseenter', function () {
            $(this).css('background', '#135e96');
        }).on('mouseleave', function () {
            $(this).css('background', '#2271b1');
        });

        // Radio option hover and selection styling
        function updateRadioStyles() {
            $('.freefactu-radio-option').each(function () {
                var $option = $(this);
                var $input = $option.find('input[type="radio"]');
                if ($input.is(':checked')) {
                    $option.css({
                        'border-color': '#2271b1',
                        'background': '#f0f7ff'
                    });
                } else {
                    $option.css({
                        'border-color': '#dcdcde',
                        'background': '#f9f9f9'
                    });
                }
            });
        }

        // Initial style update
        updateRadioStyles();

        // Update styles on radio change
        $('input[name="tipo_rectificativa"], input[name="metodo_rectificativa"]').on('change', function () {
            updateRadioStyles();
        });

        // Hover effects for radio options
        $('.freefactu-radio-option').on('mouseenter', function () {
            var $input = $(this).find('input[type="radio"]');
            if (!$input.is(':checked')) {
                $(this).css({
                    'border-color': '#a7aaad',
                    'background': '#f0f0f1'
                });
            }
        }).on('mouseleave', function () {
            updateRadioStyles();
        });

        var searchTimeout;

        // Search invoices on input
        $('#freefactu-invoice-search').on('input', function () {
            var searchTerm = $(this).val();
            clearTimeout(searchTimeout);

            if (searchTerm.length >= 0) {
                searchTimeout = setTimeout(function () {
                    searchInvoices(searchTerm);
                }, 300);
            }
        });

        // Show invoice list on focus
        $('#freefactu-invoice-search').on('focus', function () {
            if ($('#freefactu-invoice-list').children().length === 0) {
                searchInvoices('');
            }
            $('#freefactu-invoice-list').slideDown(200);
        });

        // Send rectificativa
        $('#freefactu-send-rectificativa').on('click', function () {
            var invoiceId = $('#freefactu-original-invoice-id').val();
            if (!invoiceId) {
                alert('Por favor, selecciona una factura a rectificar.');
                return;
            }

            if (!confirm(i18n.confirm_rectificativa || 'ATENCIÓN: Se creará una factura rectificativa. ¿Deseas continuar?')) {
                return;
            }

            var $btn = $(this);
            $btn.prop('disabled', true).text('Procesando...');

            // Get values from radio buttons instead of selects
            var tipoRectificativa = $('input[name="tipo_rectificativa"]:checked').val();
            var metodoRectificativa = $('input[name="metodo_rectificativa"]:checked').val();

            $.ajax({
                url: ajaxurl,
                type: 'POST',
                data: {
                    action: 'freefactu_create_rectificativa',
                    order_id: orderId,
                    invoice_id: invoiceId,
                    tipo_rectificativa: tipoRectificativa,
                    metodo_rectificativa: metodoRectificativa,
                    motivo: $('#freefactu-motivo').val(),
                    security: freefactu_params.rectificativa_nonce
                },
                success: function (response) {
                    if (response.success) {
                        $('#freefactu-rectificativa-dialog').remove();
                        // Open PDF like normal invoices instead of showing alert
                        if (response.data.pdf_url) {
                            window.location.href = response.data.pdf_url;
                        } else {
                            // Fallback: reload page if no PDF URL available
                            location.reload();
                        }
                    } else {
                        alert('Error: ' + response.data);
                        $btn.prop('disabled', false).text(i18n.send_rectificativa || 'Crear Rectificativa');
                    }
                },
                error: function () {
                    alert('Error de conexión');
                    $btn.prop('disabled', false).text(i18n.send_rectificativa || 'Crear Rectificativa');
                }
            });
        });

        // Cancel
        $('#freefactu-cancel-rectificativa').on('click', function () {
            $('#freefactu-rectificativa-dialog').fadeOut(200, function () {
                $(this).remove();
            });
        });

        // Close on background click
        $('#freefactu-rectificativa-dialog').on('click', function (e) {
            if (e.target === this) {
                $(this).fadeOut(200, function () {
                    $(this).remove();
                });
            }
        });
    }

    /**
     * Search invoices for rectificativa selection
     */
    function searchInvoices(searchTerm) {
        var $list = $('#freefactu-invoice-list');
        $list.html('<div style="padding: 15px; text-align: center; color: #666;">' + (freefactu_params.i18n.loading_invoices || 'Cargando...') + '</div>').show();

        $.ajax({
            url: ajaxurl,
            type: 'POST',
            data: {
                action: 'freefactu_search_invoices',
                search: searchTerm,
                security: freefactu_params.unified_action_nonce
            },
            success: function (response) {
                if (response.success && response.data.invoices.length > 0) {
                    var html = '';
                    $.each(response.data.invoices, function (i, inv) {
                        // Create rectificativa badge if applicable
                        var rectificativaBadge = '';
                        if (inv.is_rectificativa) {
                            rectificativaBadge = '<span style="display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; background: linear-gradient(135deg, #f5af19 0%, #f12711 100%); color: #fff; font-size: 11px; font-weight: bold; border-radius: 3px; margin-left: 6px; vertical-align: middle;">R</span>';
                        }

                        html += '<div class="freefactu-invoice-item" data-id="' + inv.id + '" data-number="' + inv.invoice_number + '" data-customer="' + inv.customer + '" data-total="' + inv.total + '" data-date="' + inv.date + '" data-is-rectificativa="' + (inv.is_rectificativa ? '1' : '0') + '" style="padding: 12px; border-bottom: 1px solid #eee; cursor: pointer; transition: background 0.2s;">' +
                            '<div style="font-weight: 600; display: flex; align-items: center;">' + inv.invoice_number + rectificativaBadge + '</div>' +
                            '<div style="font-size: 12px; color: #666;">' + inv.customer + ' · ' + inv.date + ' · ' + inv.total + '</div>' +
                            '</div>';
                    });
                    $list.html(html);

                    // Handle invoice selection
                    $('.freefactu-invoice-item').on('click', function () {
                        var $item = $(this);
                        var id = $item.data('id');
                        var number = $item.data('number');
                        var customer = $item.data('customer');
                        var total = $item.data('total');
                        var date = $item.data('date');
                        var isRectificativa = $item.data('is-rectificativa') === 1 || $item.data('is-rectificativa') === '1';

                        // Create rectificativa badge for selected invoice display
                        var selectedBadge = '';
                        if (isRectificativa) {
                            selectedBadge = '<span style="display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; background: linear-gradient(135deg, #f5af19 0%, #f12711 100%); color: #fff; font-size: 11px; font-weight: bold; border-radius: 3px; margin-left: 6px; vertical-align: middle;">R</span>';
                        }

                        $('#freefactu-original-invoice-id').val(id);
                        $('#freefactu-selected-invoice').html(
                            '<div style="display: flex; align-items: center;"><strong>' + number + '</strong>' + selectedBadge + '</div>' +
                            '<span style="font-size: 12px; color: #666;">' + customer + ' · ' + date + ' · ' + total + '</span>' +
                            '<button type="button" class="freefactu-clear-selection" style="float: right; background: none; border: none; color: #d63638; cursor: pointer;">✕</button>'
                        ).show();
                        $list.slideUp(200);
                        $('#freefactu-invoice-search').val(number);
                        $('#freefactu-send-rectificativa').prop('disabled', false);

                        // Handle clear selection
                        $('.freefactu-clear-selection').on('click', function (e) {
                            e.stopPropagation();
                            $('#freefactu-original-invoice-id').val('');
                            $('#freefactu-selected-invoice').hide();
                            $('#freefactu-invoice-search').val('');
                            $('#freefactu-send-rectificativa').prop('disabled', true);
                        });
                    }).on('mouseenter', function () {
                        $(this).css('background', '#f0f7ff');
                    }).on('mouseleave', function () {
                        $(this).css('background', '');
                    });
                } else {
                    $list.html('<div style="padding: 15px; text-align: center; color: #666;">' + (freefactu_params.i18n.no_invoices_found || 'No se encontraron facturas') + '</div>');
                }
            },
            error: function () {
                $list.html('<div style="padding: 15px; text-align: center; color: #d63638;">Error de conexión</div>');
            }
        });
    }

    // ============================================================================
    // INVOICE SERIES MANAGEMENT HANDLERS
    // ============================================================================

    // Open series creation dialog
    $(document).on('click', '.freefactu-new-series-btn', function (e) {
        e.preventDefault();
        var type = $(this).data('type');
        var typeLabel = type === 'normal' ? 'Facturas Normales' : 'Facturas Rectificativas';

        $('#freefactu-series-type').val(type);
        $('#freefactu-dialog-title').text('Nueva Serie - ' + typeLabel);

        // Set default prefix based on type
        if (type === 'rectificativa') {
            $('#freefactu-series-prefix').attr('placeholder', 'Ej: R-[year]-');
            $('#freefactu-dialog-preview').css('background', 'linear-gradient(135deg, #f5af19 0%, #f12711 100%)');
        } else {
            $('#freefactu-series-prefix').attr('placeholder', 'Ej: FAC-[year]-');
            $('#freefactu-dialog-preview').css('background', 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)');
        }

        // Clear form
        $('#freefactu-series-name').val('');
        $('#freefactu-series-prefix').val('');
        $('#freefactu-series-suffix').val('');
        $('#freefactu-series-padding').val(6);

        updateSeriesDialogPreview();
        $('#freefactu-series-dialog').css('display', 'flex').hide().fadeIn(200);
    });

    // Close series dialog
    $(document).on('click', '.freefactu-close-dialog', function (e) {
        e.preventDefault();
        $('#freefactu-series-dialog').fadeOut(200);
    });

    $(document).on('click', '#freefactu-series-dialog', function (e) {
        if (e.target === this) $(this).fadeOut(200);
    });

    // Series dialog live preview
    function updateSeriesDialogPreview() {
        var prefix = $('#freefactu-series-prefix').val() || '';
        var suffix = $('#freefactu-series-suffix').val() || '';
        var padding = parseInt($('#freefactu-series-padding').val()) || 0;

        var now = new Date();
        prefix = prefix.replace(/\[year\]/g, now.getFullYear())
            .replace(/\[month\]/g, ('0' + (now.getMonth() + 1)).slice(-2))
            .replace(/\[day\]/g, ('0' + now.getDate()).slice(-2));
        suffix = suffix.replace(/\[year\]/g, now.getFullYear())
            .replace(/\[month\]/g, ('0' + (now.getMonth() + 1)).slice(-2))
            .replace(/\[day\]/g, ('0' + now.getDate()).slice(-2));

        var num = padding > 0 ? '1'.padStart(padding, '0') : '1';
        $('#freefactu-dialog-preview-number').text(prefix + num + suffix || '1');
    }
    $(document).on('input', '.freefactu-series-input', updateSeriesDialogPreview);

    // Series form submission
    $(document).on('submit', '#freefactu-series-form', function (e) {
        e.preventDefault();
        var $form = $(this);
        var $submitBtn = $form.find('button[type="submit"]');
        var originalBtnHtml = $submitBtn.html();

        var name = $('#freefactu-series-name').val().trim();
        if (!name) { alert('Por favor, introduce un nombre.'); return; }

        $submitBtn.prop('disabled', true).html('<span class="dashicons dashicons-update spin"></span> Creando...');

        $.ajax({
            url: ajaxurl,
            type: 'POST',
            data: {
                action: 'freefactu_create_series',
                security: freefactu_params.series_nonce,
                name: name,
                type: $('#freefactu-series-type').val(),
                prefix: $('#freefactu-series-prefix').val(),
                suffix: $('#freefactu-series-suffix').val(),
                padding: $('#freefactu-series-padding').val()
            },
            success: function (response) {
                if (response.success) window.location.reload();
                else { alert('Error: ' + (response.data || 'Error')); $submitBtn.prop('disabled', false).html(originalBtnHtml); }
            },
            error: function () { alert('Error de conexión.'); $submitBtn.prop('disabled', false).html(originalBtnHtml); }
        });
    });

    // Series radio selection
    $(document).on('change', '.freefactu-series-radio', function () {
        var seriesId = $(this).val();
        var type = $(this).data('type');
        $('.freefactu-series-radio[data-type="' + type + '"]').prop('disabled', true);

        $.ajax({
            url: ajaxurl,
            type: 'POST',
            data: { action: 'freefactu_set_active_series', security: freefactu_params.series_nonce, series_id: seriesId },
            success: function (response) { window.location.reload(); },
            error: function () { alert('Error de conexión.'); window.location.reload(); }
        });
    });

    // Delete series
    $(document).on('click', '.freefactu-delete-series-btn', function (e) {
        e.preventDefault();
        e.stopPropagation();

        if (!confirm('¿Eliminar esta serie?')) return;

        var $btn = $(this).prop('disabled', true);
        $.ajax({
            url: ajaxurl,
            type: 'POST',
            data: { action: 'freefactu_delete_series', security: freefactu_params.series_nonce, series_id: $btn.data('series-id') },
            success: function (response) { if (response.success) window.location.reload(); else { alert('Error: ' + response.data); $btn.prop('disabled', false); } },
            error: function () { alert('Error de conexión.'); $btn.prop('disabled', false); }
        });
    });

    // ============================================================================
    // DEBUG MODAL (AJAX-Loaded Invoice Debug Info)
    // ============================================================================

    /**
     * Get or create the debug modal overlay element.
     * Creates the modal structure if it doesn't exist.
     */
    function getDebugModalOverlay() {
        var $overlay = $('#freefactu-debug-modal-overlay');
        if ($overlay.length === 0) {
            var modalHtml = '<div id="freefactu-debug-modal-overlay" class="freefactu-debug-modal-overlay">' +
                '<div class="freefactu-debug-modal" role="dialog" aria-labelledby="freefactu-debug-modal-title" aria-modal="true">' +
                '<div id="freefactu-debug-modal-content"></div>' +
                '</div>' +
                '</div>';
            $('body').append(modalHtml);
            $overlay = $('#freefactu-debug-modal-overlay');
        }
        return $overlay;
    }

    /**
     * Show loading state in debug modal
     */
    function showDebugModalLoading() {
        var loadingHtml = '<div class="freefactu-debug-modal-header">' +
            '<h2>' + (freefactu_params.i18n.debug_loading_title || 'Cargando información...') + '</h2>' +
            '<button type="button" class="freefactu-debug-modal-close" aria-label="' + (freefactu_params.i18n.close || 'Cerrar') + '">' +
            '<span class="dashicons dashicons-no-alt"></span>' +
            '</button>' +
            '</div>' +
            '<div class="freefactu-debug-modal-loading">' +
            '<span class="spinner is-active"></span>' +
            '<p>' + (freefactu_params.i18n.debug_loading_text || 'Cargando información de depuración...') + '</p>' +
            '</div>';
        $('#freefactu-debug-modal-content').html(loadingHtml);
    }

    /**
     * Show error state in debug modal
     */
    function showDebugModalError(message) {
        var errorHtml = '<div class="freefactu-debug-modal-header">' +
            '<h2>' + (freefactu_params.i18n.error || 'Error') + '</h2>' +
            '<button type="button" class="freefactu-debug-modal-close" aria-label="' + (freefactu_params.i18n.close || 'Cerrar') + '">' +
            '<span class="dashicons dashicons-no-alt"></span>' +
            '</button>' +
            '</div>' +
            '<div class="freefactu-debug-modal-error">' +
            '<span class="dashicons dashicons-warning"></span>' +
            '<p>' + $('<div/>').text(message).html() + '</p>' +
            '</div>';
        $('#freefactu-debug-modal-content').html(errorHtml);
    }

    /**
     * Open the debug modal and load content via AJAX
     */
    function openDebugModal(orderId) {
        var $overlay = getDebugModalOverlay();

        // Show modal with loading state
        showDebugModalLoading();
        $overlay.addClass('is-visible');
        $('body').css('overflow', 'hidden'); // Prevent body scrolling

        // Load debug content via AJAX
        $.ajax({
            url: ajaxurl,
            type: 'POST',
            data: {
                action: 'freefactu_get_debug_content',
                order_id: orderId,
                security: freefactu_params.debug_modal_nonce
            },
            success: function (response) {
                if (response.success && response.data.html) {
                    $('#freefactu-debug-modal-content').html(response.data.html);
                    // Initialize interactive elements after content loads
                    initDebugModalInteractions();
                } else {
                    showDebugModalError(response.data || (freefactu_params.i18n.error || 'Error desconocido'));
                }
            },
            error: function () {
                showDebugModalError(freefactu_params.i18n.connection_error || 'Error de conexión');
            }
        });
    }

    /**
     * Close the debug modal
     */
    function closeDebugModal() {
        var $overlay = $('#freefactu-debug-modal-overlay');
        $overlay.removeClass('is-visible');
        $('body').css('overflow', ''); // Restore body scrolling

        // Clear content after animation
        setTimeout(function () {
            $('#freefactu-debug-modal-content').empty();
        }, 200);
    }

    /**
     * Initialize interactive elements inside the debug modal
     * (copy buttons, toggle buttons, XML viewers)
     */
    function initDebugModalInteractions() {
        var $modal = $('#freefactu-debug-modal-content');

        // Copy hash button
        $modal.find('.copy-hash-btn').off('click').on('click', function () {
            var $btn = $(this);
            var hash = $btn.attr('data-hash');
            navigator.clipboard.writeText(hash).then(function () {
                var $icon = $btn.find('.dashicons');
                $icon.removeClass('dashicons-clipboard').addClass('dashicons-yes');
                setTimeout(function () {
                    $icon.removeClass('dashicons-yes').addClass('dashicons-clipboard');
                }, 1500);
            });
        });

        // Toggle hash visibility button
        $modal.find('.toggle-hash-btn').off('click').on('click', function () {
            var $btn = $(this);
            var $container = $btn.closest('.freefactu-hash-display').parent();
            var $fullHash = $container.find('.hash-full');
            var $icon = $btn.find('.dashicons');

            if ($fullHash.is(':hidden')) {
                $fullHash.slideDown(150);
                $icon.removeClass('dashicons-visibility').addClass('dashicons-hidden');
            } else {
                $fullHash.slideUp(150);
                $icon.removeClass('dashicons-hidden').addClass('dashicons-visibility');
            }
        });

        // Toggle XML visibility
        $modal.find('.toggle-xml-btn').off('click').on('click', function () {
            var $btn = $(this);
            var $container = $btn.parent().find('.xml-container');
            var $icon = $btn.find('.dashicons');

            if ($container.is(':hidden')) {
                $container.slideDown(200);
                $icon.removeClass('dashicons-visibility').addClass('dashicons-hidden');
            } else {
                $container.slideUp(200);
                $icon.removeClass('dashicons-hidden').addClass('dashicons-visibility');
            }
        });

        // Copy XML button
        $modal.find('.copy-xml-btn').off('click').on('click', function () {
            var $btn = $(this);
            var xml = $btn.attr('data-xml');
            navigator.clipboard.writeText(xml).then(function () {
                var $icon = $btn.find('.dashicons');
                $icon.removeClass('dashicons-clipboard').addClass('dashicons-yes');
                setTimeout(function () {
                    $icon.removeClass('dashicons-yes').addClass('dashicons-clipboard');
                }, 1500);
            });
        });
    }

    // Click handler for debug modal button
    $(document).on('click', '.freefactu-open-debug-modal', function (e) {
        e.preventDefault();
        var orderId = $(this).data('order-id');
        if (orderId) {
            openDebugModal(orderId);
        }
    });

    // Close modal on close button click
    $(document).on('click', '.freefactu-debug-modal-close', function (e) {
        e.preventDefault();
        closeDebugModal();
    });

    // Close modal on overlay background click
    $(document).on('click', '#freefactu-debug-modal-overlay', function (e) {
        if (e.target === this) {
            closeDebugModal();
        }
    });

    // Add Escape key handler for debug modal (extend existing handler)
    $(document).on('keydown', function (e) {
        if (e.key === 'Escape' && $('#freefactu-debug-modal-overlay').hasClass('is-visible')) {
            closeDebugModal();
        }
        // Also handle Escape for export modal
        if (e.key === 'Escape' && $('#freefactu-export-modal-overlay').hasClass('is-visible')) {
            closeExportModal();
        }
    });

    // ============================================================================
    // EXPORT MODAL HANDLERS
    // ============================================================================

    /**
     * Open the export modal.
     */
    function openExportModal() {
        var $overlay = $('#freefactu-export-modal-overlay');
        if ($overlay.length) {
            $overlay.addClass('is-visible');
            // Prevent body scroll
            $('body').css('overflow', 'hidden');
        }
    }

    /**
     * Close the export modal.
     */
    function closeExportModal() {
        var $overlay = $('#freefactu-export-modal-overlay');
        if ($overlay.length) {
            $overlay.removeClass('is-visible');
            // Restore body scroll
            $('body').css('overflow', '');
        }
    }

    // Open export modal via button click
    $(document).on('click', '#freefactu-open-export-modal', function (e) {
        e.preventDefault();
        openExportModal();
    });

    // Close export modal on close button click
    $(document).on('click', '.freefactu-export-modal-close', function (e) {
        e.preventDefault();
        closeExportModal();
    });

    // Close export modal on overlay background click
    $(document).on('click', '#freefactu-export-modal-overlay', function (e) {
        if (e.target === this) {
            closeExportModal();
        }
    });

    // ============================================================================
    // GOOGLE ANALYTICS STYLE DATE RANGE PICKER - SCROLLABLE MONTHS
    // ============================================================================

    /**
     * Date Range Picker Component
     * A Google Analytics inspired date range selector with scrollable months
     */
    var DateRangePicker = {
        // State
        startDate: null,
        endDate: null,
        hoverDate: null,
        selecting: 'start', // 'start' or 'end'

        // Month rendering state
        firstRenderedMonth: null, // {year, month}
        lastRenderedMonth: null,  // {year, month}
        monthsToRender: 13, // How many months to initially render
        isScrolling: false,

        // Spanish month names
        monthNames: [
            'Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
            'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'
        ],

        weekDays: ['Lu', 'Ma', 'Mi', 'Ju', 'Vi', 'Sa', 'Do'],

        /**
         * Initialize the date range picker
         */
        init: function () {
            var self = this;

            // Check if elements exist
            if ($('#freefactu-daterange').length === 0) {
                return;
            }

            // Parse existing dates from hidden inputs
            var existingStart = $('#filter_date_from').val();
            var existingEnd = $('#filter_date_to').val();

            if (existingStart) {
                self.startDate = new Date(existingStart);
            }
            if (existingEnd) {
                self.endDate = new Date(existingEnd);
            }

            // If both dates exist, we're in "start" selecting mode (ready for new selection)
            if (self.startDate && self.endDate) {
                self.selecting = 'start';
            }

            // Bind events
            self.bindEvents();
        },

        /**
         * Bind all event handlers
         */
        bindEvents: function () {
            var self = this;

            // Toggle panel - stop propagation to prevent immediate close
            $(document).on('click', '#freefactu-daterange-trigger', function (e) {
                e.preventDefault();
                e.stopPropagation();
                self.togglePanel();
            });

            // Stop propagation for all clicks inside the panel
            $(document).on('click', '#freefactu-daterange-panel', function (e) {
                e.stopPropagation();
            });

            // Day selection
            $(document).on('click', '.freefactu-daterange__day:not(.is-empty):not(.is-disabled)', function (e) {
                e.preventDefault();
                e.stopPropagation();
                var date = new Date($(this).data('date'));
                self.selectDate(date);
            });

            // Day hover for preview
            $(document).on('mouseenter', '.freefactu-daterange__day:not(.is-empty):not(.is-disabled)', function () {
                if (self.selecting === 'end' && self.startDate && !self.endDate) {
                    var hoverDate = new Date($(this).data('date'));
                    self.hoverDate = hoverDate;
                    self.updateHoverPreview();
                }
            });

            $(document).on('mouseleave', '.freefactu-daterange__months-container', function () {
                if (self.hoverDate) {
                    self.hoverDate = null;
                    self.clearHoverPreview();
                }
            });


            // Preset buttons
            $(document).on('click', '.freefactu-daterange__preset', function (e) {
                e.preventDefault();
                e.stopPropagation();
                var preset = $(this).data('preset');
                self.applyPreset(preset);
            });

            // Cancel button
            $(document).on('click', '#freefactu-daterange-cancel', function (e) {
                e.preventDefault();
                e.stopPropagation();
                self.closePanel();
            });

            // Apply button
            $(document).on('click', '#freefactu-daterange-apply', function (e) {
                e.preventDefault();
                e.stopPropagation();
                self.applySelection();
            });

            // Close on click outside
            $(document).on('click', function (e) {
                if (!$(e.target).closest('#freefactu-daterange').length &&
                    $('#freefactu-daterange-panel').hasClass('is-visible')) {
                    self.closePanel();
                }
            });

            // Close on Escape
            $(document).on('keydown', function (e) {
                if (e.key === 'Escape' && $('#freefactu-daterange-panel').hasClass('is-visible')) {
                    self.closePanel();
                }
            });

            // Status filter auto-submit
            $(document).on('change', '#filter_status', function () {
                $('#freefactu-filter-form').submit();
            });
        },

        /**
         * Toggle panel visibility
         */
        togglePanel: function () {
            var $panel = $('#freefactu-daterange-panel');
            var $trigger = $('#freefactu-daterange-trigger');

            if ($panel.hasClass('is-visible')) {
                this.closePanel();
            } else {
                $panel.addClass('is-visible');
                $trigger.attr('aria-expanded', 'true');
                this.renderMonths();
            }
        },

        /**
         * Close panel
         */
        closePanel: function () {
            $('#freefactu-daterange-panel').removeClass('is-visible');
            $('#freefactu-daterange-trigger').attr('aria-expanded', 'false');
            this.hoverDate = null;
        },

        /**
         * Render multiple months for scrolling
         */
        renderMonths: function () {
            var self = this;
            var $container = $('#freefactu-months-container');
            var $scroll = $('#freefactu-calendar-scroll');
            $container.empty();

            // Determine center month (current date or start date if selected)
            var centerDate = this.startDate ? new Date(this.startDate) : new Date();
            var centerYear = centerDate.getFullYear();
            var centerMonth = centerDate.getMonth();

            // Render months: 6 before, current, 6 after
            var monthsBefore = 6;
            var monthsAfter = 6;

            var html = '';

            for (var offset = -monthsBefore; offset <= monthsAfter; offset++) {
                var date = new Date(centerYear, centerMonth + offset, 1);
                html += this.renderSingleMonth(date.getFullYear(), date.getMonth());
            }

            $container.html(html);

            // Track rendered range
            var firstDate = new Date(centerYear, centerMonth - monthsBefore, 1);
            var lastDate = new Date(centerYear, centerMonth + monthsAfter, 1);
            this.firstRenderedMonth = { year: firstDate.getFullYear(), month: firstDate.getMonth() };
            this.lastRenderedMonth = { year: lastDate.getFullYear(), month: lastDate.getMonth() };

            // Bind scroll event directly (scroll events don't bubble)
            $scroll.off('scroll.daterangepicker').on('scroll.daterangepicker', function () {
                self.handleScroll();
            });

            // Scroll to current month
            this.scrollToCurrentMonth();
            this.updateSelectionDisplay();
        },

        /**
         * Render a single month block
         */
        renderSingleMonth: function (year, month) {
            var self = this;
            var firstDay = new Date(year, month, 1);
            var lastDay = new Date(year, month + 1, 0);
            var startDayOfWeek = firstDay.getDay();
            // Adjust for Monday start (0=Monday, 6=Sunday)
            startDayOfWeek = startDayOfWeek === 0 ? 6 : startDayOfWeek - 1;

            var today = new Date();
            today.setHours(0, 0, 0, 0);

            var html = '<div class="freefactu-daterange__month" data-year="' + year + '" data-month="' + month + '">';
            html += '<div class="freefactu-daterange__month-title">' + this.monthNames[month] + ' ' + year + '</div>';

            // Weekdays header
            html += '<div class="freefactu-daterange__calendar-weekdays">';
            for (var i = 0; i < 7; i++) {
                html += '<span>' + this.weekDays[i] + '</span>';
            }
            html += '</div>';

            // Days grid
            html += '<div class="freefactu-daterange__calendar-days">';

            // Empty cells before first day
            for (var i = 0; i < startDayOfWeek; i++) {
                html += '<button type="button" class="freefactu-daterange__day is-empty">&nbsp;</button>';
            }

            // Days of the month
            for (var day = 1; day <= lastDay.getDate(); day++) {
                var date = new Date(year, month, day);
                var dateStr = this.formatDate(date);
                var classes = ['freefactu-daterange__day'];

                // Today
                if (date.getTime() === today.getTime()) {
                    classes.push('is-today');
                }

                // Selected range
                if (this.startDate && this.endDate) {
                    var start = new Date(this.startDate);
                    var end = new Date(this.endDate);
                    start.setHours(0, 0, 0, 0);
                    end.setHours(0, 0, 0, 0);

                    if (date.getTime() === start.getTime()) {
                        classes.push('is-range-start', 'is-selected');
                    } else if (date.getTime() === end.getTime()) {
                        classes.push('is-range-end', 'is-selected');
                    } else if (date > start && date < end) {
                        classes.push('is-in-range');
                    }
                } else if (this.startDate) {
                    var start = new Date(this.startDate);
                    start.setHours(0, 0, 0, 0);
                    if (date.getTime() === start.getTime()) {
                        classes.push('is-selected', 'is-range-start', 'is-range-end');
                    }
                }

                html += '<button type="button" class="' + classes.join(' ') + '" data-date="' + dateStr + '">' + day + '</button>';
            }

            html += '</div></div>';

            return html;
        },

        /**
         * Scroll to the current month (no animation)
         */
        scrollToCurrentMonth: function () {
            var $scroll = $('#freefactu-calendar-scroll');
            var $container = $('#freefactu-months-container');
            if (!$scroll.length || !$container.length) return;

            // Find current month element
            var now = new Date();
            var $currentMonth = $('.freefactu-daterange__month[data-year="' + now.getFullYear() + '"][data-month="' + now.getMonth() + '"]');

            if ($currentMonth.length) {
                // Get the position of the month title relative to the container
                var monthTitle = $currentMonth.find('.freefactu-daterange__month-title')[0];
                if (monthTitle) {
                    var scrollPosition = monthTitle.offsetTop - $container[0].offsetTop;
                    $scroll.scrollTop(scrollPosition);
                }
            }
        },

        /**
         * Handle scroll for infinite loading
         */
        handleScroll: function () {
            if (this.isScrolling) return;

            var $scroll = $('#freefactu-calendar-scroll');
            var $container = $('#freefactu-months-container');
            var scrollTop = $scroll.scrollTop();
            var scrollHeight = $container.outerHeight();
            var containerHeight = $scroll.outerHeight();

            // Load more months at top (trigger earlier - 200px from edge)
            if (scrollTop < 200) {
                this.prependMonths();
            }

            // Load more months at bottom (trigger earlier - 200px from edge)
            if (scrollTop + containerHeight > scrollHeight - 200) {
                this.appendMonths();
            }
        },

        /**
         * Prepend months to the top
         */
        prependMonths: function () {
            var self = this;
            if (this.isScrolling) return;
            this.isScrolling = true;

            var $container = $('#freefactu-months-container');
            var $scroll = $('#freefactu-calendar-scroll');
            var oldScrollHeight = $container.outerHeight();

            // Add 6 months before
            var html = '';
            for (var i = 6; i >= 1; i--) {
                var date = new Date(this.firstRenderedMonth.year, this.firstRenderedMonth.month - i, 1);
                html += this.renderSingleMonth(date.getFullYear(), date.getMonth());
            }

            $container.prepend(html);

            // Update first rendered month
            var newFirst = new Date(this.firstRenderedMonth.year, this.firstRenderedMonth.month - 6, 1);
            this.firstRenderedMonth = { year: newFirst.getFullYear(), month: newFirst.getMonth() };

            // Maintain scroll position
            var newScrollHeight = $container.outerHeight();
            $scroll.scrollTop($scroll.scrollTop() + (newScrollHeight - oldScrollHeight));

            setTimeout(function () {
                self.isScrolling = false;
            }, 50);
        },

        /**
         * Append months to the bottom
         */
        appendMonths: function () {
            var self = this;
            if (this.isScrolling) return;
            this.isScrolling = true;

            var $container = $('#freefactu-months-container');

            // Add 6 months after
            var html = '';
            for (var i = 1; i <= 6; i++) {
                var date = new Date(this.lastRenderedMonth.year, this.lastRenderedMonth.month + i, 1);
                html += this.renderSingleMonth(date.getFullYear(), date.getMonth());
            }

            $container.append(html);

            // Update last rendered month
            var newLast = new Date(this.lastRenderedMonth.year, this.lastRenderedMonth.month + 6, 1);
            this.lastRenderedMonth = { year: newLast.getFullYear(), month: newLast.getMonth() };

            setTimeout(function () {
                self.isScrolling = false;
            }, 50);
        },

        /**
         * Update hover preview (dashed selection)
         */
        updateHoverPreview: function () {
            var self = this;
            if (!this.startDate || !this.hoverDate) return;

            var start = new Date(this.startDate);
            start.setHours(0, 0, 0, 0);
            var hover = new Date(this.hoverDate);
            hover.setHours(0, 0, 0, 0);

            // Determine range direction
            var rangeStart = start < hover ? start : hover;
            var rangeEnd = start < hover ? hover : start;

            $('.freefactu-daterange__day').each(function () {
                var $day = $(this);
                if ($day.hasClass('is-empty')) return;

                var dayDate = new Date($day.data('date'));
                dayDate.setHours(0, 0, 0, 0);

                // Remove previous preview classes
                $day.removeClass('is-in-preview is-preview-end is-in-preview-mode');

                // Add preview classes
                if (dayDate > rangeStart && dayDate < rangeEnd) {
                    $day.addClass('is-in-preview');
                } else if (dayDate.getTime() === rangeEnd.getTime() && rangeStart.getTime() !== rangeEnd.getTime()) {
                    $day.addClass('is-preview-end');
                }

                // Mark start as being in preview mode for styling
                if (dayDate.getTime() === start.getTime() && start < hover) {
                    $day.addClass('is-in-preview-mode');
                }
            });
        },

        /**
         * Clear hover preview
         */
        clearHoverPreview: function () {
            $('.freefactu-daterange__day').removeClass('is-in-preview is-preview-end is-in-preview-mode');
        },

        /**
         * Format date to YYYY-MM-DD
         */
        formatDate: function (date) {
            var year = date.getFullYear();
            var month = ('0' + (date.getMonth() + 1)).slice(-2);
            var day = ('0' + date.getDate()).slice(-2);
            return year + '-' + month + '-' + day;
        },

        /**
         * Format date for display (Spanish format)
         */
        formatDateDisplay: function (date) {
            var day = date.getDate();
            var month = this.monthNames[date.getMonth()].substring(0, 3);
            var year = date.getFullYear();
            return day + ' ' + month + ' ' + year;
        },

        /**
         * Select a date
         */
        selectDate: function (date) {
            if (this.selecting === 'start' || !this.startDate) {
                // Starting a new selection
                this.startDate = date;
                this.endDate = null;
                this.selecting = 'end';
                this.hoverDate = null;
            } else {
                // Completing the selection
                if (date < this.startDate) {
                    // Clicked before start date - swap them
                    this.endDate = this.startDate;
                    this.startDate = date;
                } else {
                    this.endDate = date;
                }
                this.selecting = 'start';
                this.hoverDate = null;
                this.clearHoverPreview();
            }

            this.refreshDayStyles();
            this.updateSelectionDisplay();
            this.highlightActivePreset();
        },

        /**
         * Refresh day styles after selection change
         */
        refreshDayStyles: function () {
            var self = this;
            var today = new Date();
            today.setHours(0, 0, 0, 0);

            $('.freefactu-daterange__day:not(.is-empty)').each(function () {
                var $day = $(this);
                var date = new Date($day.data('date'));
                date.setHours(0, 0, 0, 0);

                // Reset classes
                $day.removeClass('is-selected is-range-start is-range-end is-in-range');

                // Selected range
                if (self.startDate && self.endDate) {
                    var start = new Date(self.startDate);
                    var end = new Date(self.endDate);
                    start.setHours(0, 0, 0, 0);
                    end.setHours(0, 0, 0, 0);

                    if (date.getTime() === start.getTime()) {
                        $day.addClass('is-range-start is-selected');
                    } else if (date.getTime() === end.getTime()) {
                        $day.addClass('is-range-end is-selected');
                    } else if (date > start && date < end) {
                        $day.addClass('is-in-range');
                    }
                } else if (self.startDate) {
                    var start = new Date(self.startDate);
                    start.setHours(0, 0, 0, 0);
                    if (date.getTime() === start.getTime()) {
                        $day.addClass('is-selected is-range-start is-range-end');
                    }
                }
            });
        },

        /**
         * Update selection display inputs
         */
        updateSelectionDisplay: function () {
            var $startDisplay = $('#freefactu-date-start-display');
            var $endDisplay = $('#freefactu-date-end-display');

            if (this.startDate) {
                $startDisplay.val(this.formatDateDisplay(this.startDate));
            } else {
                $startDisplay.val('');
            }

            if (this.endDate) {
                $endDisplay.val(this.formatDateDisplay(this.endDate));
            } else {
                $endDisplay.val('');
            }
        },

        /**
         * Apply a preset date range
         */
        applyPreset: function (preset) {
            var today = new Date();
            var year = today.getFullYear();
            var month = today.getMonth();

            switch (preset) {
                case 'this-month':
                    this.startDate = new Date(year, month, 1);
                    this.endDate = new Date(year, month + 1, 0);
                    break;

                case 'last-month':
                    this.startDate = new Date(year, month - 1, 1);
                    this.endDate = new Date(year, month, 0);
                    break;

                case 'q1':
                    this.startDate = new Date(year, 0, 1);
                    this.endDate = new Date(year, 2, 31);
                    break;

                case 'q2':
                    this.startDate = new Date(year, 3, 1);
                    this.endDate = new Date(year, 5, 30);
                    break;

                case 'q3':
                    this.startDate = new Date(year, 6, 1);
                    this.endDate = new Date(year, 8, 30);
                    break;

                case 'q4':
                    this.startDate = new Date(year, 9, 1);
                    this.endDate = new Date(year, 11, 31);
                    break;

                case 'this-year':
                    this.startDate = new Date(year, 0, 1);
                    this.endDate = new Date(year, 11, 31);
                    break;

                case 'last-year':
                    this.startDate = new Date(year - 1, 0, 1);
                    this.endDate = new Date(year - 1, 11, 31);
                    break;

                case 'clear':
                    this.startDate = null;
                    this.endDate = null;
                    this.selecting = 'start';
                    this.applySelection();
                    return;
            }

            this.selecting = 'start';

            // Re-render months centered on start date
            this.renderMonths();
            this.highlightActivePreset();
        },

        /**
         * Highlight active preset based on current selection
         */
        highlightActivePreset: function () {
            $('.freefactu-daterange__preset').removeClass('is-active');

            if (!this.startDate || !this.endDate) {
                return;
            }

            var today = new Date();
            var year = today.getFullYear();
            var month = today.getMonth();

            // Check each preset
            var presets = {
                'this-month': [new Date(year, month, 1), new Date(year, month + 1, 0)],
                'last-month': [new Date(year, month - 1, 1), new Date(year, month, 0)],
                'q1': [new Date(year, 0, 1), new Date(year, 2, 31)],
                'q2': [new Date(year, 3, 1), new Date(year, 5, 30)],
                'q3': [new Date(year, 6, 1), new Date(year, 8, 30)],
                'q4': [new Date(year, 9, 1), new Date(year, 11, 31)],
                'this-year': [new Date(year, 0, 1), new Date(year, 11, 31)],
                'last-year': [new Date(year - 1, 0, 1), new Date(year - 1, 11, 31)]
            };

            for (var key in presets) {
                var range = presets[key];
                if (this.datesEqual(this.startDate, range[0]) && this.datesEqual(this.endDate, range[1])) {
                    $('.freefactu-daterange__preset[data-preset="' + key + '"]').addClass('is-active');
                    break;
                }
            }
        },

        /**
         * Check if two dates are equal (ignoring time)
         */
        datesEqual: function (d1, d2) {
            return d1.getFullYear() === d2.getFullYear() &&
                d1.getMonth() === d2.getMonth() &&
                d1.getDate() === d2.getDate();
        },

        /**
         * Apply the current selection and submit form
         */
        applySelection: function () {
            var $dateFrom = $('#filter_date_from');
            var $dateTo = $('#filter_date_to');

            if (this.startDate) {
                $dateFrom.val(this.formatDate(this.startDate));
            } else {
                $dateFrom.val('');
            }

            if (this.endDate) {
                $dateTo.val(this.formatDate(this.endDate));
            } else {
                $dateTo.val('');
            }

            this.closePanel();

            // Submit the form
            $('#freefactu-filter-form').submit();
        }
    };

    // Initialize date range picker
    DateRangePicker.init();

});

