/**
 * Admin JavaScript for PDF Template Manager
 * Version: 1.6.0 - Canonical Selectors Refactor
 */

(function($) {
    'use strict';
    
    // DEBUG MODE - Only enabled when PSF_DEV_MODE is set
    const PSF_DEBUG = window.swpdfDevMode && window.swpdfDevMode.enabled;
    function swpdfLog(...args) {
        if (PSF_DEBUG) console.log('[PSF Debug]', ...args);
    }
    
    // =====================================================
    // CANONICAL CONSTANTS (DO NOT CHANGE)
    // =====================================================
    
    // Core column values - ENUM (locked)
    const PSF_CORE_COLUMNS = ['name', 'email', 'phone', 'stock'];
    
    // Display labels for core columns
    const PSF_CORE_COLUMN_LABELS = {
        'name': '📛 Name',
        'email': '📧 Email',
        'phone': '📱 Phone',
        'stock': '🚗 Stock #'
    };
    
    // Legacy mapping (for backward compatibility with stored data)
    const PSF_LEGACY_COLUMN_MAP = {
        'customer_name': 'name',
        'customer_email': 'email',
        'customer_phone': 'phone',
        'stock_number': 'stock'
    };
    
    // =====================================================
    // SINGLE SOURCE OF TRUTH - STATE OBJECT
    // =====================================================
    
    window.PSF_MAPPING_STATE = {
        initialHash: '',
        isDirty: false,
        coreMappings: {},
        metaMappings: {},
        labels: {},
        duplicateColumns: [],
        duplicateFields: []
    };
    
    // Alias for internal use
    const STATE = window.PSF_MAPPING_STATE;
    
    // Legacy aliases (for backward compatibility during transition)
    const CORE_COLUMNS = PSF_CORE_COLUMNS;
    const CORE_COLUMN_LABELS = PSF_CORE_COLUMN_LABELS;
    
    /**
     * Capture current form state for dirty tracking
     * Returns hash string for comparison
     */
    function captureFormState() {
        const state = {};
        $('#psf-field-mapping-table tbody tr.psf-mapping-row').each(function() {
            const fieldId = $(this).attr('data-field-id');
            state[fieldId] = {
                label: $(this).find('.psf-field-label-input').val(),
                mapping: $(this).find('.psf-map-core-select').val(),
                metaKey: $(this).find('.psf-map-meta-input').val(),
                required: $(this).find('[data-required]').attr('data-required') === '1'
            };
        });
        // Fallback to legacy selectors if new ones not found
        if (Object.keys(state).length === 0) {
            $('#edit-fields-tbody tr').each(function() {
                const fieldName = $(this).data('field-name');
                state[fieldName] = {
                    label: $(this).find('.field-label-edit-input').val(),
                    mapping: normalizeColumnValue($(this).find('.field-mapping-select').val()),
                    metaKey: $(this).find('.field-meta-key-input').val(),
                    required: $(this).find('.field-required-checkbox').is(':checked')
                };
            });
        }
        // Include signature and date position values in state hash
        state['__sig__'] = {
            x: $('#sig-pos-x').val() || '',
            y: $('#sig-pos-y').val() || '',
            w: $('#sig-width').val() || '',
            h: $('#sig-height').val() || ''
        };
        state['__date__'] = {
            enabled: $('#edit-date-enabled').is(':checked'),
            x: $('#edit-date-pos-x').val() || '',
            y: $('#edit-date-pos-y').val() || '',
            fontSize: $('#edit-date-size').val() || ''
        };
        return JSON.stringify(state);
    }
    
    /**
     * Normalize legacy column values to canonical format
     */
    function normalizeColumnValue(value) {
        if (!value) return '';
        return PSF_LEGACY_COLUMN_MAP[value] || value;
    }
    
    /**
     * Convert canonical column value to legacy format for storage
     */
    function toLegacyColumnValue(value) {
        const reverseMap = {
            'name': 'customer_name',
            'email': 'customer_email',
            'phone': 'customer_phone',
            'stock': 'stock_number'
        };
        return reverseMap[value] || value;
    }
    
    /**
     * Check if form has unsaved changes
     * Compares current state hash against initialHash
     */
    function checkDirtyState() {
        if (!STATE.initialHash) return false;
        const currentHash = captureFormState();
        return currentHash !== STATE.initialHash;
    }
    
    /**
     * Update dirty state UI
     * Updates STATE.isDirty and UI elements
     */
    function updateDirtyState() {
        STATE.isDirty = checkDirtyState();
        
        // Use canonical selector with fallback
        const $saveBtn = $('#psf-save-mappings').length ? $('#psf-save-mappings') : $('#save-edited-labels');
        const $dirtyBadge = $('#psf-unsaved-indicator').length ? $('#psf-unsaved-indicator') : $('.psf-dirty-badge');
        
        // Run validation - check BOTH core columns and meta keys
        const coreValid = validateDuplicateCoreColumns();
        const metaValid = validateMetaKeys();
        const hasValidationErrors = !coreValid || !metaValid;
        
        if (STATE.isDirty) {
            // Enable save only if dirty AND no validation errors
            $saveBtn.prop('disabled', hasValidationErrors);
            if ($dirtyBadge.length === 0) {
                $saveBtn.before('<span id="psf-unsaved-indicator" class="psf-dirty-badge">⚠️ Unsaved changes</span>');
            } else {
                $dirtyBadge.show();
            }
        } else {
            $saveBtn.prop('disabled', true);
            $dirtyBadge.hide();
        }
    }
    
    /**
     * Validate for duplicate core column mappings (canonical function)
     * Updates STATE.duplicateColumns and STATE.duplicateFields
     * Returns true if valid, false if duplicates found
     */
    function validateDuplicateCoreColumns() {
        const mappingCounts = {};
        const duplicateColumns = [];
        const duplicateFields = [];
        
        // Count how many fields are mapped to each core column
        // Support both canonical and legacy selectors
        const $rows = $('#psf-field-mapping-table tbody tr.psf-mapping-row').length 
            ? $('#psf-field-mapping-table tbody tr.psf-mapping-row')
            : $('#edit-fields-tbody tr');
        
        $rows.each(function() {
            const $select = $(this).find('.psf-map-core-select').length 
                ? $(this).find('.psf-map-core-select') 
                : $(this).find('.field-mapping-select');
            const rawMapping = $select.val();
            const mapping = normalizeColumnValue(rawMapping);
            const fieldId = $(this).attr('data-field-id') || $(this).data('field-name');
            
            if (mapping && PSF_CORE_COLUMNS.includes(mapping)) {
                if (!mappingCounts[mapping]) {
                    mappingCounts[mapping] = [];
                }
                mappingCounts[mapping].push(fieldId);
            }
        });
        
        // Find duplicates
        Object.keys(mappingCounts).forEach(function(col) {
            if (mappingCounts[col].length > 1) {
                duplicateColumns.push(col);
                duplicateFields.push(...mappingCounts[col]);
            }
        });
        
        // Update STATE
        STATE.duplicateColumns = [...new Set(duplicateColumns)];
        STATE.duplicateFields = [...new Set(duplicateFields)];
        
        // Remove existing warnings
        $('.psf-duplicate-warning, .psf-row-warning .psf-duplicate-warning').remove();
        
        if (STATE.duplicateColumns.length > 0) {
            // Mark affected rows
            $rows.each(function() {
                const $row = $(this);
                const $select = $row.find('.psf-map-core-select, .field-mapping-select');
                const rawMapping = $select.val();
                const mapping = normalizeColumnValue(rawMapping);
                
                if (STATE.duplicateColumns.includes(mapping)) {
                    $row.addClass('psf-row-duplicate');
                    const $warning = $row.find('.psf-row-warning, .psf-mapping-wrapper');
                    if ($warning.find('.psf-duplicate-warning').length === 0) {
                        $warning.append('<span class="psf-duplicate-warning">⚠️ Duplicate: another field uses this column</span>');
                    }
                } else {
                    $row.removeClass('psf-row-duplicate');
                }
            });
            
            // Disable save button
            $('#psf-save-mappings, #save-edited-labels').prop('disabled', true);
            
            // Show banner notice
            if ($('.psf-duplicate-notice').length === 0) {
                const columnNames = STATE.duplicateColumns.map(c => PSF_CORE_COLUMN_LABELS[c] || c).join(', ');
                const notice = '<div class="psf-duplicate-notice notice notice-error inline" style="margin: 0 0 15px 0; padding: 10px 15px;">' +
                    '<p style="margin: 0;">❌ <strong>Duplicate column mapping detected:</strong> ' + escapeHtml(columnNames) + 
                    '. Each core column can only have one field mapped to it.</p></div>';
                $('#psf-mapping-banner, .psf-field-stats').first().after(notice);
            }
            
            return false;
        }
        
        // Clear duplicate state
        $rows.removeClass('psf-row-duplicate');
        $('.psf-duplicate-notice').remove();
        return true;
    }
    
    // Legacy alias
    function validateDuplicateMappings() {
        const coreValid = validateDuplicateCoreColumns();
        const metaValid = validateMetaKeys();
        return coreValid && metaValid;
    }
    
    /**
     * Validate meta key format and uniqueness (canonical function)
     */
    function validateMetaKeys() {
        const usedKeys = {};
        let hasErrors = false;
        
        const $rows = $('#psf-field-mapping-table tbody tr.psf-mapping-row').length 
            ? $('#psf-field-mapping-table tbody tr.psf-mapping-row')
            : $('#edit-fields-tbody tr');
        
        $rows.each(function() {
            const $select = $(this).find('.psf-map-core-select, .field-mapping-select');
            const $metaInput = $(this).find('.psf-map-meta-input, .field-meta-key-input');
            const $error = $(this).find('.psf-meta-key-error');
            const mapping = $select.val();
            
            if (mapping === 'meta') {
                const key = $metaInput.val();
                const validation = validateMetaKey(key);
                
                if (!validation.valid) {
                    hasErrors = true;
                    $error.text(validation.error).show();
                    $metaInput.css('border-color', '#d63638');
                } else if (usedKeys[key]) {
                    hasErrors = true;
                    $error.text('Duplicate meta key').show();
                    $metaInput.css('border-color', '#d63638');
                } else {
                    usedKeys[key] = true;
                    $error.hide();
                    $metaInput.css('border-color', '');
                }
            } else {
                $error.hide();
                $metaInput.css('border-color', '');
            }
        });
        
        return !hasErrors;
    }
    
    /**
     * Validate field types against mappings (canonical function)
     */
    function validateFieldTypes() {
        const $rows = $('#psf-field-mapping-table tbody tr.psf-mapping-row').length 
            ? $('#psf-field-mapping-table tbody tr.psf-mapping-row')
            : $('#edit-fields-tbody tr');
        
        $rows.each(function() {
            const $row = $(this);
            const fieldType = $row.attr('data-field-type') || $row.find('td:eq(4)').text();
            const $select = $row.find('.psf-map-core-select, .field-mapping-select');
            const rawMapping = $select.val();
            const mapping = normalizeColumnValue(rawMapping);
            const $wrapper = $row.find('.psf-row-warning, .psf-mapping-wrapper');
            
            // Remove existing type warning
            $wrapper.find('.psf-type-warning').remove();
            
            // Add warning for problematic type/mapping combos
            const warning = getTypeMismatchWarning(fieldType, mapping);
            if (warning) {
                $wrapper.append(warning);
            }
        });
        
        return true; // Type warnings don't block save
    }
    
    /**
     * Get "Saved As" preview text for a field based on mapping
     */
    function getSavedAsPreview(mapping, metaKey, fieldName) {
        // Support both canonical and legacy column values
        const labels = {
            'name': '📛 Column: Name',
            'email': '📧 Column: Email',
            'phone': '📱 Column: Phone',
            'stock': '🚗 Column: Stock #',
            // Legacy mappings
            'customer_name': '📛 Column: Name',
            'customer_email': '📧 Column: Email',
            'customer_phone': '📱 Column: Phone',
            'stock_number': '🚗 Column: Stock #'
        };
        
        if (mapping === 'meta' && metaKey) {
            return '🏷️ Meta: <code>' + escapeHtml(metaKey) + '</code>';
        } else if (mapping && labels[mapping]) {
            return labels[mapping];
        } else {
            return '<span class="psf-unmapped">📦 Agreement Data</span>';
        }
    }
    
    /**
     * Escape HTML entities for safe display
     */
    function escapeHtml(text) {
        const map = { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#039;' };
        return String(text).replace(/[&<>"']/g, m => map[m]);
    }
    
    /**
     * Count mapped/unmapped fields
     */
    function countMappingStats(fields, getMappingFn) {
        let mapped = 0;
        let unmapped = 0;
        let customMeta = 0;
        
        fields.forEach(function(field) {
            const mapping = getMappingFn(field.name);
            if (mapping && mapping !== '') {
                mapped++;
                if (mapping === 'meta') customMeta++;
            } else {
                unmapped++;
            }
        });
        
        return { mapped, unmapped, customMeta, total: fields.length };
    }
    
    /**
     * Build field stats notice HTML
     */
    function buildStatsNotice(stats) {
        let noticeClass = 'notice-info';
        let icon = 'ℹ️';
        
        if (stats.unmapped > 0) {
            noticeClass = 'notice-warning';
            icon = '⚠️';
        } else if (stats.mapped === stats.total) {
            noticeClass = 'notice-success';
            icon = '✅';
        }
        
        let html = '<div class="psf-field-stats notice ' + noticeClass + ' inline" style="margin: 0 0 15px 0; padding: 10px 15px;">';
        html += '<p style="margin: 0; display: flex; align-items: center; gap: 15px; flex-wrap: wrap;">';
        html += '<strong>' + icon + ' Field Mapping Status:</strong>';
        html += '<span class="psf-stat psf-stat-total">' + stats.total + ' fields total</span>';
        html += '<span class="psf-stat psf-stat-mapped" style="color: #00a32a;">✓ ' + stats.mapped + ' mapped</span>';
        if (stats.unmapped > 0) {
            html += '<span class="psf-stat psf-stat-unmapped" style="color: #d63638;">⊘ ' + stats.unmapped + ' unmapped</span>';
        }
        if (stats.customMeta > 0) {
            html += '<span class="psf-stat psf-stat-meta" style="color: #2271b1;">🏷️ ' + stats.customMeta + ' custom meta</span>';
        }
        html += '</p></div>';
        
        return html;
    }
    
    /**
     * Build column preview box HTML
     */
    function buildColumnPreview() {
        let html = '<div id="psf-column-preview" class="psf-column-preview" style="margin: 0 0 15px 0; padding: 12px 15px; background: #f0f6fc; border: 1px solid #c3d9ed; border-radius: 4px;">';
        html += '<p style="margin: 0 0 8px 0; font-weight: 600; font-size: 12px; color: #1d4ed8;">📊 Column Preview — Live view of where data will be saved:</p>';
        html += '<div class="psf-column-grid" style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; font-size: 12px;">';
        
        PSF_CORE_COLUMNS.forEach(function(col) {
            const label = PSF_CORE_COLUMN_LABELS[col];
            html += '<div class="psf-column-item" data-column="' + col + '">';
            html += '<strong>' + label + ':</strong><br>';
            html += '<span class="psf-column-value">(not mapped)</span>';
            html += '</div>';
        });
        
        html += '</div></div>';
        return html;
    }
    
    /**
     * Update column preview based on current mappings
     */
    function updateColumnPreview() {
        const mappings = {};
        
        // Support both canonical and legacy selectors
        const $rows = $('#psf-field-mapping-table tbody tr.psf-mapping-row').length 
            ? $('#psf-field-mapping-table tbody tr.psf-mapping-row')
            : $('#edit-fields-tbody tr');
        
        // Find which field is mapped to each column
        $rows.each(function() {
            const fieldName = $(this).attr('data-field-id') || $(this).data('field-name');
            const $labelInput = $(this).find('.psf-field-label-input, .field-label-edit-input');
            const label = $labelInput.val() || fieldName;
            const $select = $(this).find('.psf-map-core-select, .field-mapping-select');
            const rawMapping = $select.val();
            const mapping = normalizeColumnValue(rawMapping);
            
            if (mapping && PSF_CORE_COLUMNS.includes(mapping)) {
                if (!mappings[mapping]) {
                    mappings[mapping] = [];
                }
                mappings[mapping].push(label);
            }
        });
        
        // Update each column display
        PSF_CORE_COLUMNS.forEach(function(col) {
            const $item = $('.psf-column-item[data-column="' + col + '"] .psf-column-value');
            if (mappings[col] && mappings[col].length > 0) {
                if (mappings[col].length > 1) {
                    // Duplicate - show warning
                    $item.html('<span style="color: #d63638;">⚠️ ' + escapeHtml(mappings[col].join(', ')) + '</span>');
                } else {
                    $item.html('<span style="color: #00a32a;">✓ ' + escapeHtml(mappings[col][0]) + '</span>');
                }
            } else {
                $item.html('<span style="color: #787c82;">(not mapped)</span>');
            }
        });
    }
    
    /**
     * Build bulk actions toolbar with presets
     */
    function buildBulkToolbar() {
        let html = '<div class="psf-bulk-toolbar" style="display: flex; gap: 15px; align-items: center; margin-bottom: 15px; padding: 10px 15px; background: #f0f0f1; border-radius: 4px; flex-wrap: wrap;">';
        
        // Bulk actions dropdown
        html += '<div class="psf-bulk-actions">';
        html += '<select id="psf-bulk-action" class="regular-text" style="width: auto;">';
        html += '<option value="">— Bulk Actions —</option>';
        html += '<option value="require_all">✓ Mark all required</option>';
        html += '<option value="optional_all">○ Mark all optional</option>';
        html += '<option value="clear_mappings">🗑️ Clear all mappings</option>';
        html += '</select>';
        html += '<button type="button" id="psf-apply-bulk" class="button">Apply</button>';
        html += '</div>';
        
        // Presets - canonical button ID
        html += '<div class="psf-presets">';
        html += '<button type="button" id="psf-preset-basic-contact" class="button" title="Auto-detect and map name/email/phone/stock fields">📇 Basic Contact Preset</button>';
        html += '</div>';
        
        // Auto-label button
        html += '<button type="button" id="psf-auto-label" class="button" title="Generate friendly labels from field names">✨ Auto-Label</button>';
        
        // Search/filter
        html += '<div class="psf-field-search" style="margin-left: auto;">';
        html += '<input type="text" id="psf-field-filter" class="regular-text" placeholder="🔍 Filter fields..." style="width: 200px;">';
        html += '</div>';
        
        html += '</div>';
        return html;
    }
    
    /**
     * Apply Basic Contact preset using heuristics
     * Canonical trigger: #psf-preset-basic-contact
     */
    function applyBasicContactPreset() {
        // Heuristics map to LEGACY values (for storage compatibility)
        const heuristics = {
            'customer_name': ['name', 'full_name', 'fullname', 'customer_name', 'client_name', 'your_name', 'full name', 'customer name'],
            'customer_email': ['email', 'e_mail', 'e-mail', 'customer_email', 'your_email', 'primary_email', 'email_address'],
            'customer_phone': ['phone', 'telephone', 'mobile', 'cell', 'customer_phone', 'phone_number', 'preferred_phone', 'contact_phone'],
            'stock_number': ['stock', 'stock_no', 'stock_number', 'stocknumber', 'vin', 'vehicle_id', 'vehicle_number', 'stock number', 'stock #']
        };
        
        // Support both canonical and legacy selectors
        const $rows = $('#psf-field-mapping-table tbody tr.psf-mapping-row').length 
            ? $('#psf-field-mapping-table tbody tr.psf-mapping-row')
            : $('#edit-fields-tbody tr');
        
        // Check if any fields already have mappings
        let hasExistingMappings = false;
        $rows.each(function() {
            const $select = $(this).find('.psf-map-core-select, .field-mapping-select');
            const mapping = $select.val();
            if (mapping && mapping !== '') {
                hasExistingMappings = true;
                return false; // break
            }
        });
        
        if (hasExistingMappings) {
            if (!confirm('Some fields already have mappings. Apply preset anyway? This will overwrite existing column mappings.')) {
                return;
            }
        }
        
        // Apply heuristics
        let appliedCount = 0;
        
        Object.keys(heuristics).forEach(function(targetMapping) {
            const patterns = heuristics[targetMapping];
            const normalizedTarget = normalizeColumnValue(targetMapping);
            let bestMatch = null;
            let bestScore = 0;
            
            $rows.each(function() {
                const $row = $(this);
                const fieldName = ($row.attr('data-field-id') || $row.data('field-name') || '').toLowerCase();
                const $labelInput = $row.find('.psf-field-label-input, .field-label-edit-input');
                const label = ($labelInput.val() || '').toLowerCase();
                const $select = $row.find('.psf-map-core-select, .field-mapping-select');
                const currentMapping = normalizeColumnValue($select.val());
                
                // Skip if already mapped to a core column
                if (currentMapping && PSF_CORE_COLUMNS.includes(currentMapping)) {
                    return;
                }
                
                // Calculate match score
                let score = 0;
                patterns.forEach(function(pattern) {
                    pattern = pattern.toLowerCase();
                    if (fieldName === pattern || label === pattern) {
                        score = Math.max(score, 100); // Exact match
                    } else if (fieldName.includes(pattern) || label.includes(pattern)) {
                        score = Math.max(score, 50 + pattern.length); // Partial match
                    }
                });
                
                if (score > bestScore) {
                    bestScore = score;
                    bestMatch = $row;
                }
            });
            
            // Apply the best match (use legacy value for storage compatibility)
            if (bestMatch && bestScore > 0) {
                bestMatch.find('.psf-map-core-select, .field-mapping-select').val(targetMapping).trigger('change');
                appliedCount++;
            }
        });
        
        // Show toast feedback
        if (appliedCount > 0) {
            showSaveFeedback('success', appliedCount + ' fields auto-mapped using Basic Contact preset');
        } else {
            showSaveFeedback('info', 'No matching fields found for preset.');
        }
        
        updateDirtyState();
        updateColumnPreview();
        updateStatsNotice();
    }
    
    /**
     * Auto-label fields from field names
     */
    function autoLabelFields() {
        let updatedCount = 0;
        
        // Support both canonical and legacy selectors
        const $rows = $('#psf-field-mapping-table tbody tr.psf-mapping-row').length 
            ? $('#psf-field-mapping-table tbody tr.psf-mapping-row')
            : $('#edit-fields-tbody tr');
        
        $rows.each(function() {
            const $row = $(this);
            const fieldName = $row.attr('data-field-id') || $row.data('field-name') || '';
            const $labelInput = $row.find('.psf-field-label-input, .field-label-edit-input');
            const currentLabel = $labelInput.val().trim();
            
            // Generate friendly label
            const friendlyLabel = generateFriendlyLabel(fieldName);
            
            // Only update if label is empty or matches the raw field name
            const rawName = fieldName.replace(/_/g, ' ').toLowerCase();
            const currentLower = currentLabel.toLowerCase();
            
            if (currentLabel === '' || currentLower === rawName || currentLower === fieldName.toLowerCase()) {
                $labelInput.val(friendlyLabel);
                updatedCount++;
            }
        });
        
        if (updatedCount > 0) {
            showSaveFeedback('success', 'Auto-labeled ' + updatedCount + ' field(s).');
            updateDirtyState();
        } else {
            showSaveFeedback('info', 'All fields already have custom labels.');
        }
    }
    
    /**
     * Generate friendly label from field name
     */
    function generateFriendlyLabel(fieldName) {
        return fieldName
            .replace(/_/g, ' ')           // Replace underscores with spaces
            .replace(/([a-z])([A-Z])/g, '$1 $2') // Split camelCase
            .replace(/\s+/g, ' ')         // Collapse multiple spaces
            .trim()
            .replace(/\b\w/g, l => l.toUpperCase()); // Title case
    }
    
    /**
     * Get row badges/warnings HTML
     */
    function getRowBadges(mapping, isRequired, type) {
        let badges = '';
        
        // Mapped but not required warning
        if (mapping && mapping !== '' && !isRequired) {
            badges += '<span class="psf-badge psf-badge-warning" title="Field is mapped to a column but not marked required - users may skip it">⚠️ Optional</span>';
        }
        
        return badges;
    }
    
    // Beforeunload handler for unsaved changes (uses STATE.isDirty)
    function setupBeforeUnload() {
        $(window).off('beforeunload.psf').on('beforeunload.psf', function(e) {
            if (STATE.isDirty && $('#edit-labels-modal').is(':visible')) {
                const message = 'You have unsaved changes. Are you sure you want to leave?';
                e.returnValue = message;
                return message;
            }
        });
    }
    
    // Set PDF.js worker
    if (typeof pdfjsLib !== 'undefined') {
        pdfjsLib.GlobalWorkerOptions.workerSrc = swpdfAdmin.pdfjsWorker;
    }
    
    let previewPdf = null;
    let previewPage = 1;
    let detectedFields = [];
    let previewScale = 1.2;
    let activePreviewField = null;
    let previewRenderTask = null;
    let highlightTimer = null;
    
    // Zoom level for upload preview (1.0 = 100%)
    let uploadZoomLevel = 1.0;
    let selectedManualField = null; // Currently selected manual field for position editing
    let uploadPreviewPage = 1; // Current page being shown in upload preview
    
    // IMPORTANT: Track currently active agreement_type to prevent cross-template contamination
    let currentAgreementType = null;
    
    // Upload form with auto field detection
    $('#upload-template-form').on('submit', function(e) {
        e.preventDefault();
        
        const formData = new FormData(this);
        formData.append('action', 'swpdf_upload_pdf_template');
        formData.append('nonce', swpdfAdmin.nonce);
        
        const $btn = $(this).find('button[type="submit"]');
        const originalText = $btn.text();
        const agreementType = $('#agreement_type').val();
        
        $btn.prop('disabled', true).text('Uploading...');
        $('#upload-progress').slideDown();
        $('#progress-bar').css('width', '30%');
        
        $.ajax({
            url: swpdfAdmin.ajaxUrl,
            type: 'POST',
            data: formData,
            processData: false,
            contentType: false,
            success: function(response) {
                if (response.success) {
                    $('#progress-bar').css('width', '60%');
                    
                    // Store template info for later save (template not registered yet)
                    window.pendingTemplateUpload = {
                        template_name: response.data.template_name,
                        agreement_type: response.data.agreement_type,
                        filename: response.data.filename
                    };
                    
                    // Now detect fields from the uploaded PDF
                    // Use sanitized agreement_type from server response, not raw user input
                    detectFields(response.data.filename, response.data.agreement_type);
                } else {
                    $('#upload-message')
                        .removeClass('notice-success')
                        .addClass('notice notice-error')
                        .html('<p>' + (response.data.message || 'Upload failed') + '</p>')
                        .slideDown();
                    $('#upload-progress').slideUp();
                    $btn.prop('disabled', false).text(originalText);
                }
            },
            error: function() {
                $('#upload-message')
                    .removeClass('notice-success')
                    .addClass('notice notice-error')
                    .html('<p>Upload failed. Please try again.</p>')
                    .slideDown();
                $('#upload-progress').slideUp();
                $btn.prop('disabled', false).text(originalText);
            }
        });
    });
    
    // Detect fields from uploaded PDF
    async function detectFields(filename, agreementType) {
        try {
            const pdfUrl = swpdfAdmin.templatesUrl + filename;
            
            // Load PDF
            const loadingTask = pdfjsLib.getDocument(pdfUrl);
            const pdf = await loadingTask.promise;
            
            $('#progress-bar').css('width', '80%');
            
            detectedFields = [];
            
            // Scan all pages
            for (let i = 1; i <= pdf.numPages; i++) {
                const page = await pdf.getPage(i);
                const annotations = await page.getAnnotations();
                
                annotations.forEach(function(ann) {
                    if (ann.fieldType && ann.fieldName) {
                        detectedFields.push({
                            name: ann.fieldName,
                            type: ann.fieldType,
                            page: i,
                            rect: ann.rect
                        });
                    }
                });
            }
            
            $('#progress-bar').css('width', '100%');
            
            // Show preview
            showPreview(pdf, detectedFields, agreementType);
            
            $('#upload-progress').slideUp();
            $('#upload-template-form button[type="submit"]').prop('disabled', false).text('Upload & Detect Fields');
            
        } catch (error) {
            console.error('Error detecting fields:', error);
            $('#upload-message')
                .removeClass('notice-success')
                .addClass('notice notice-error')
                .html('<p>Error detecting fields: ' + error.message + '</p>')
                .slideDown();
            $('#upload-progress').slideUp();
        }
    }
    
    // Track manually added fields (with position data)
    let manualFields = [];
    let manualFieldCounter = 0;
    let currentSortBy = 'page'; // Default sort
    
    // Show preview and fields
    function showPreview(pdf, fields, agreementType) {
        previewPdf = pdf;
        manualFields = []; // Reset manual fields on new upload
        manualFieldCounter = 0;
        uploadPreviewPage = pdf.numPages; // Start on last page by default (where signature usually goes)
        $('#template-preview').slideDown();
        $('#field-count').text(fields.length);
        $('#shortcode-display').val('[swpdf_signature_form agreement_type="' + agreementType + '"]');
        
        // Render signature preview on last page
        renderUploadSignaturePreview(pdf, false, pdf.numPages);
        
        // Sort fields by page then label
        const sortedFields = sortFieldsList([...fields], currentSortBy);
        
        // Show fields list with editable labels and Maps To dropdown
        let fieldsList = '';
        
        // Unmapped fields notice
        fieldsList += '<div class="notice notice-info" style="margin-bottom: 15px; padding: 10px 12px;"><p style="margin: 0;">💡 <strong>Tip:</strong> Fields not mapped to a column are stored as agreement metadata and visible in agreement details / exports where supported.</p></div>';
        
        // Always show the header/instructions
        fieldsList += '<div style="margin-bottom: 15px;"><p><strong>📝 Edit labels, set required fields, map to database columns, or delete fields:</strong></p></div>';
        
        // Add info message for manual fields
        if (fields.length === 0) {
            fieldsList += '<div class="notice notice-warning" style="margin-bottom: 15px;"><p>📌 <strong>No fillable fields detected.</strong> Click "➕ Add Field" to manually create input fields that will be positioned on the PDF.</p></div>';
        }
        
        // Sort controls
        fieldsList += '<div style="margin-bottom: 10px; display: flex; align-items: center; gap: 10px;">';
        fieldsList += '<label style="font-weight: 500;">Sort by:</label>';
        fieldsList += '<select id="field-sort-by" class="regular-text" style="width: auto;">';
        fieldsList += '<option value="page"' + (currentSortBy === 'page' ? ' selected' : '') + '>Page</option>';
        fieldsList += '<option value="label"' + (currentSortBy === 'label' ? ' selected' : '') + '>Label</option>';
        fieldsList += '</select>';
        fieldsList += '</div>';
        
        // Always show the table (even if empty initially)
        fieldsList += '<table id="fields-table" class="wp-list-table widefat striped"><thead><tr><th width="15%">Field Name</th><th width="22%">Display Label</th><th width="18%">Maps To</th><th style="text-align:center;">Required</th><th>Type</th><th>Page</th><th>Action</th></tr></thead><tbody id="fields-tbody">';
        
        if (sortedFields.length > 0) {
            sortedFields.forEach(function(field, index) {
                const defaultLabel = field.name.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
                fieldsList += buildFieldRow(field.name, defaultLabel, field.type, field.page, false);
            });
        }
        
        fieldsList += '</tbody></table>';
        
        // Add Field button and Save button
        fieldsList += '<div style="margin-top: 15px; display: flex; gap: 10px; align-items: center;">';
        fieldsList += '<button type="button" id="add-manual-field-btn" class="button" title="Add a new text field that you can position on the PDF">➕ Add Field</button>';
        fieldsList += '<button type="button" id="save-field-labels" class="button button-primary">💾 Save All Settings</button>';
        fieldsList += '</div>';
        
        $('#detected-fields-list').html(fieldsList);
        
        // Bind sort change using event delegation
        $('#detected-fields-list').off('change', '#field-sort-by').on('change', '#field-sort-by', function() {
            currentSortBy = $(this).val();
            swpdfLog('Sort changed to:', currentSortBy, 'Fields count:', detectedFields.length);
            
            // FIRST: Collect all current values from DOM before rebuilding
            const currentValues = {};
            detectedFields.forEach(function(field) {
                currentValues[field.name] = {
                    label: $('.field-label-input[data-field-name="' + field.name + '"]').val() || field.name.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase()),
                    mapping: $('.field-mapping-select[data-field-name="' + field.name + '"]').val() || '',
                    metaKey: $('.field-meta-key-input[data-field-name="' + field.name + '"]').val() || '',
                    required: $('.field-required-checkbox[data-field-name="' + field.name + '"]').is(':checked')
                };
            });
            
            // THEN: Sort and rebuild
            const newSortedFields = sortFieldsList([...detectedFields], currentSortBy);
            let tbody = '';
            newSortedFields.forEach(function(field) {
                const vals = currentValues[field.name] || {};
                tbody += buildFieldRow(field.name, vals.label, field.type, field.page, field.isManual || false, vals.mapping, vals.metaKey);
            });
            $('#fields-tbody').html(tbody);
            
            // Restore required checkboxes state
            newSortedFields.forEach(function(field) {
                const vals = currentValues[field.name] || {};
                if (vals.required) {
                    $('.field-required-checkbox[data-field-name="' + field.name + '"]').prop('checked', true);
                } else {
                    $('.field-required-checkbox[data-field-name="' + field.name + '"]').prop('checked', false);
                }
            });
            
            swpdfLog('Rebuilt tbody with', newSortedFields.length, 'fields');
        });
        
        // Highlight field overlay when clicking/focusing on table row
        $('#detected-fields-list')
            .off('click', '#fields-tbody tr')
            .on('click', '#fields-tbody tr', function() {
                const fieldName = $(this).data('field-name');
                // Also check if field is on current preview page
                const field = detectedFields.find(f => f.name === fieldName);
                if (field && field.page !== uploadPreviewPage) {
                    // Switch to the field's page
                    uploadPreviewPage = field.page;
                    if (currentUploadPdf) {
                        renderUploadSignaturePreview(currentUploadPdf, true, uploadPreviewPage);
                    }
                }
                highlightFieldOverlay(fieldName);
                // Highlight the row
                $('#fields-tbody tr').removeClass('psf-row-selected');
                $(this).addClass('psf-row-selected');
            });
        
        // Also highlight on input focus
        $('#detected-fields-list')
            .off('focus', '.field-label-input, .field-mapping-select')
            .on('focus', '.field-label-input, .field-mapping-select', function() {
                const fieldName = $(this).data('field-name');
                const $row = $(this).closest('tr');
                const field = detectedFields.find(f => f.name === fieldName);
                if (field && field.page !== uploadPreviewPage) {
                    uploadPreviewPage = field.page;
                    if (currentUploadPdf) {
                        renderUploadSignaturePreview(currentUploadPdf, true, uploadPreviewPage);
                    }
                }
                highlightFieldOverlay(fieldName);
                $('#fields-tbody tr').removeClass('psf-row-selected');
                $row.addClass('psf-row-selected');
            });
        
        // Bind add field button
        $('#add-manual-field-btn').off('click').on('click', function() {
            addManualField();
        });

        // Delete field button handler
        $('#detected-fields-list')
            .off('click', '.delete-field-btn')
            .on('click', '.delete-field-btn', function() {
                const fieldName = $(this).data('field-name');
                const $row = $(this).closest('tr');
                
                if (confirm('Delete field "' + fieldName + '"? This field will not be shown to users.')) {
                    // Remove from detectedFields array
                    detectedFields = detectedFields.filter(f => f.name !== fieldName);
                    // Remove from manualFields array
                    manualFields = manualFields.filter(f => f.name !== fieldName);
                    // Remove row from table
                    $row.fadeOut(300, function() {
                        $(this).remove();
                        // Update field count
                        $('#field-count').text(detectedFields.length);
                    });
                    // Remove overlay
                    $('#field-overlay-' + fieldName.replace(/[^a-zA-Z0-9]/g, '_')).remove();
                    // Remove field box
                    $('#field-box-' + fieldName.replace(/[^a-zA-Z0-9]/g, '_')).remove();
                }
            });
        
        // Position field button handler - highlights the field box on canvas
        $('#detected-fields-list')
            .off('click', '.position-field-btn')
            .on('click', '.position-field-btn', function() {
                const fieldName = $(this).data('field-name');
                const boxId = '#field-box-' + fieldName.replace(/[^a-zA-Z0-9]/g, '_');
                const $box = $(boxId);
                
                if ($box.length) {
                    // Highlight the box
                    $('.manual-field-box-highlight').removeClass('manual-field-box-highlight');
                    $box.addClass('manual-field-box-highlight').css({
                        'border-color': '#e74c3c',
                        'background': 'rgba(231, 76, 60, 0.4)'
                    });
                    
                    // Scroll the preview container to show the box
                    const $container = $('#upload-sig-pdf-container');
                    const boxTop = $box.position().top;
                    $container.animate({ scrollTop: boxTop - 50 }, 300);
                    
                    // Flash animation
                    setTimeout(function() {
                        $box.css({
                            'border-color': '#0073aa',
                            'background': 'rgba(0, 115, 170, 0.2)'
                        });
                    }, 1500);
                }
            });

        // Highlight preview field when editing label
        $('#detected-fields-list')
            .off('focus', '.field-label-input')
            .on('focus', '.field-label-input', function() {
                const fieldName = $(this).data('field-name');
                if (highlightTimer) {
                    clearTimeout(highlightTimer);
                }
                highlightTimer = setTimeout(function() {
                    highlightPreviewField(fieldName);
                }, 150);
            })
            .off('blur', '.field-label-input')
            .on('blur', '.field-label-input', function() {
                clearPreviewHighlight();
            });
        
        // Bind save labels button
        $('#save-field-labels').on('click', function() {
            saveFieldLabels(agreementType, fields);
        });
        
        // Bind preview navigation for upload preview
        $('#prev-preview').off('click').on('click', function() {
            if (uploadPreviewPage > 1) {
                uploadPreviewPage--;
                renderUploadSignaturePreview(previewPdf, true, uploadPreviewPage);
            }
        });
        
        $('#next-preview').off('click').on('click', function() {
            if (uploadPreviewPage < previewPdf.numPages) {
                uploadPreviewPage++;
                renderUploadSignaturePreview(previewPdf, true, uploadPreviewPage);
            }
        });
        
        // Enable/disable navigation buttons
        $('#prev-preview').prop('disabled', uploadPreviewPage <= 1);
        $('#next-preview').prop('disabled', uploadPreviewPage >= previewPdf.numPages);
    }
    
    // Helper function to build a field row for the table (upload page)
    function buildFieldRow(fieldName, label, type, page, isManual, mapping = '', metaKey = '') {
        // Type mismatch warning check
        const typeWarning = getTypeMismatchWarning(type, mapping);
        
        let row = '<tr data-field-name="' + fieldName + '" data-is-manual="' + (isManual ? '1' : '0') + '" data-page="' + page + '">';
        row += '<td><code style="font-size: 11px;">' + fieldName + '</code>' + (isManual ? ' <span style="color: #0073aa; font-size: 10px;">(manual)</span>' : '') + '</td>';
        row += '<td><input type="text" class="regular-text field-label-input" data-field-name="' + fieldName + '" value="' + label + '" style="width: 100%;"></td>';
        row += '<td style="min-width: 180px;">';
        row += '<div class="psf-mapping-wrapper" data-field-name="' + fieldName + '">';
        row += '<select class="field-mapping-select" data-field-name="' + fieldName + '" style="width: ' + (mapping === 'meta' ? '45%' : '100%') + ';">';
        row += '<option value=""' + (mapping === '' ? ' selected' : '') + '>-- Auto --</option>';
        row += '<option value="customer_name"' + (mapping === 'customer_name' ? ' selected' : '') + '>📛 Customer Name</option>';
        row += '<option value="customer_email"' + (mapping === 'customer_email' ? ' selected' : '') + '>📧 Email</option>';
        row += '<option value="customer_phone"' + (mapping === 'customer_phone' ? ' selected' : '') + '>📱 Phone</option>';
        row += '<option value="stock_number"' + (mapping === 'stock_number' ? ' selected' : '') + '>🚗 Stock Number</option>';
        row += '<option value="meta"' + (mapping === 'meta' ? ' selected' : '') + '>🏷️ Custom Meta</option>';
        row += '</select>';
        row += '<input type="text" class="field-meta-key-input" data-field-name="' + fieldName + '" placeholder="meta_key" value="' + (metaKey || '') + '" style="width: 50%; margin-left: 4px; display: ' + (mapping === 'meta' ? 'inline-block' : 'none') + ';" pattern="[a-z0-9_]{2,40}" title="Lowercase letters, numbers, underscores. 2-40 chars.">';
        row += '<span class="psf-meta-key-error" style="display: none; color: #d63638; font-size: 11px;"></span>';
        row += typeWarning;
        row += '</div>';
        row += '</td>';
        row += '<td style="text-align:center;"><input type="checkbox" class="field-required-checkbox" data-field-name="' + fieldName + '" checked></td>';
        row += '<td>' + type + '</td>';
        row += '<td>' + page + '</td>';
        row += '<td>';
        if (isManual) {
            row += '<button type="button" class="button button-small position-field-btn" data-field-name="' + fieldName + '" title="Position this field on the PDF">📍</button> ';
        }
        row += '<button type="button" class="button button-small delete-field-btn" data-field-name="' + fieldName + '" title="Delete this field">🗑️</button>';
        row += '</td>';
        row += '</tr>';
        return row;
    }
    
    // Check for type mismatch and return warning HTML
    function getTypeMismatchWarning(fieldType, mapping) {
        if (!mapping || mapping === '' || mapping === 'meta') return '';
        
        const problematicTypes = ['checkbox', 'date', 'signature', 'Sig'];
        const dbColumns = ['customer_name', 'customer_email', 'customer_phone', 'stock_number'];
        
        if (problematicTypes.some(t => fieldType.toLowerCase().includes(t.toLowerCase())) && dbColumns.includes(mapping)) {
            return '<span class="psf-type-warning" title="This field type (' + fieldType + ') may not suit this column. Values might not display as expected." style="color: #dba617; cursor: help; margin-left: 4px;">⚠️</span>';
        }
        return '';
    }
    
    // Validate meta key format
    function validateMetaKey(key) {
        if (!key) return { valid: false, error: 'Meta key is required' };
        if (key.length < 2 || key.length > 40) return { valid: false, error: '2-40 characters required' };
        if (!/^[a-z0-9_]+$/.test(key)) return { valid: false, error: 'Only lowercase a-z, 0-9, _ allowed' };
        return { valid: true, error: '' };
    }
    
    // Handle mapping dropdown change (show/hide meta key input)
    $(document).on('change', '.field-mapping-select', function() {
        const $wrapper = $(this).closest('.psf-mapping-wrapper');
        const $metaInput = $wrapper.find('.field-meta-key-input');
        const fieldType = $(this).closest('tr').find('td:eq(4)').text();
        const mapping = $(this).val();
        
        if (mapping === 'meta') {
            $(this).css('width', '45%');
            $metaInput.show();
        } else {
            $(this).css('width', '100%');
            $metaInput.hide().val('');
            $wrapper.find('.psf-meta-key-error').hide();
        }
        
        // Update type warning
        $wrapper.find('.psf-type-warning').remove();
        const warning = getTypeMismatchWarning(fieldType, mapping);
        if (warning) {
            $wrapper.append(warning);
        }
    });
    
    // Validate meta key on input
    $(document).on('input', '.field-meta-key-input', function() {
        const key = $(this).val();
        const $error = $(this).siblings('.psf-meta-key-error');
        const validation = validateMetaKey(key);
        
        if (!validation.valid && key.length > 0) {
            $error.text(validation.error).show();
            $(this).css('border-color', '#d63638');
        } else {
            $error.hide();
            $(this).css('border-color', '');
        }
    });
    
    // Add a new manual field
    function addManualField() {
        manualFieldCounter++;
        const fieldName = 'manual_field_' + manualFieldCounter;
        const defaultLabel = 'Custom Field ' + manualFieldCounter;
        const currentPage = 1; // Default to page 1, can be changed
        
        // Add to detectedFields array so it gets saved
        const newField = {
            name: fieldName,
            type: 'text',
            page: currentPage,
            isManual: true,
            // Default position (center of page, will be adjusted by user)
            position: {
                x: 100,
                y: 400,
                width: 150,
                height: 20
            }
        };
        detectedFields.push(newField);
        manualFields.push(newField);
        
        // Add row to table
        const row = buildFieldRow(fieldName, defaultLabel, 'text', currentPage, true);
        $('#fields-tbody').append(row);
        
        // Update field count
        $('#field-count').text(detectedFields.length);
        
        // Add draggable box to the signature preview canvas for this field
        addFieldBoxToCanvas(newField);
        
        // Scroll to show the new row
        const $newRow = $('tr[data-field-name="' + fieldName + '"]');
        $newRow.css('background-color', '#ffffcc');
        setTimeout(function() {
            $newRow.css('background-color', '');
        }, 2000);
    }
    
    // Add a draggable field box to the signature canvas
    function addFieldBoxToCanvas(field) {
        const $wrapper = $('#upload-sig-pdf-wrapper');
        const canvas = document.getElementById('upload-sig-pdf-canvas');
        if (!canvas || !$wrapper.length) return;
        
        // Create the field box element
        const boxId = 'field-box-' + field.name.replace(/[^a-zA-Z0-9]/g, '_');
        
        // Remove if exists
        $('#' + boxId).remove();
        
        // Calculate screen position from PDF coordinates
        const screenX = field.position.x * uploadSigPdfScale;
        const screenWidth = field.position.width * uploadSigPdfScale;
        const screenHeight = field.position.height * uploadSigPdfScale;
        const screenY = (uploadSigPdfPageHeight - field.position.y - field.position.height) * uploadSigPdfScale;
        
        const $box = $('<div>')
            .attr('id', boxId)
            .attr('data-field-name', field.name)
            .css({
                position: 'absolute',
                left: screenX + 'px',
                top: screenY + 'px',
                width: screenWidth + 'px',
                height: screenHeight + 'px',
                border: '2px dashed #0073aa',
                background: 'rgba(0, 115, 170, 0.2)',
                cursor: 'move',
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
                fontSize: '9px',
                color: '#0073aa',
                fontWeight: 'bold',
                zIndex: 15
            })
            .html('📝 ' + field.name.replace('manual_field_', 'F'));
        
        // Add resize handle
        $box.append('<div class="field-resize-handle" style="position: absolute; right: -4px; bottom: -4px; width: 10px; height: 10px; background: #0073aa; cursor: se-resize; border-radius: 2px;"></div>');
        
        $wrapper.append($box);
        
        // Setup dragging for this field box
        setupFieldBoxDragging($box, field);
    }
    
    // Setup drag and resize for a field box
    function setupFieldBoxDragging($box, field) {
        const $wrapper = $('#upload-sig-pdf-wrapper');
        let isDragging = false;
        let isResizing = false;
        let startX, startY, startLeft, startTop, startWidth, startHeight;
        
        $box.off('mousedown').on('mousedown', function(e) {
            // Select this field for position editing
            selectManualField(field);
            
            if ($(e.target).hasClass('field-resize-handle')) {
                isResizing = true;
                startX = e.pageX;
                startY = e.pageY;
                startWidth = $box.width();
                startHeight = $box.height();
            } else {
                isDragging = true;
                startX = e.pageX;
                startY = e.pageY;
                startLeft = parseFloat($box.css('left')) || 0;
                startTop = parseFloat($box.css('top')) || 0;
            }
            e.preventDefault();
            e.stopPropagation();
        });
        
        $(document).on('mousemove.fieldbox' + field.name, function(e) {
            const canvas = document.getElementById('upload-sig-pdf-canvas');
            if (!canvas) return;
            
            if (isDragging) {
                const dx = e.pageX - startX;
                const dy = e.pageY - startY;
                let newLeft = Math.max(0, Math.min(startLeft + dx, canvas.width - $box.width()));
                let newTop = Math.max(0, Math.min(startTop + dy, canvas.height - $box.height()));
                $box.css({ left: newLeft + 'px', top: newTop + 'px' });
                updateFieldPositionFromBox($box, field);
            } else if (isResizing) {
                const dx = e.pageX - startX;
                const dy = e.pageY - startY;
                $box.css({ 
                    width: Math.max(30, startWidth + dx) + 'px', 
                    height: Math.max(15, startHeight + dy) + 'px' 
                });
                updateFieldPositionFromBox($box, field);
            }
        });
        
        $(document).on('mouseup.fieldbox' + field.name, function() {
            isDragging = false;
            isResizing = false;
        });
    }
    
    // Update field position data from box screen position
    function updateFieldPositionFromBox($box, field) {
        const screenX = parseFloat($box.css('left')) || 0;
        const screenY = parseFloat($box.css('top')) || 0;
        const screenWidth = $box.outerWidth();
        const screenHeight = $box.outerHeight();
        
        // Convert screen position to PDF coordinates
        const pdfX = Math.round(screenX / uploadSigPdfScale);
        const pdfWidth = Math.round(screenWidth / uploadSigPdfScale);
        const pdfHeight = Math.round(screenHeight / uploadSigPdfScale);
        const pdfY = Math.round(uploadSigPdfPageHeight - (screenY / uploadSigPdfScale) - pdfHeight);
        
        // Update field position
        field.position = {
            x: Math.max(0, pdfX),
            y: Math.max(0, pdfY),
            width: Math.max(20, pdfWidth),
            height: Math.max(10, pdfHeight)
        };
        
        // Update the field in detectedFields array
        const idx = detectedFields.findIndex(f => f.name === field.name);
        if (idx !== -1) {
            detectedFields[idx] = field;
        }
        
        // Also update in manualFields array
        const mIdx = manualFields.findIndex(f => f.name === field.name);
        if (mIdx !== -1) {
            manualFields[mIdx] = field;
        }
        
        // Update the position inputs panel if this field is selected
        if (selectedManualField && selectedManualField.name === field.name) {
            $('#field-pos-x').val(field.position.x);
            $('#field-pos-y').val(field.position.y);
            $('#field-pos-width').val(field.position.width);
            $('#field-pos-height').val(field.position.height);
        }
    }
    
    async function renderPreviewPage(pageNum) {
        const page = await previewPdf.getPage(pageNum);
        const canvas = document.getElementById('preview-canvas');
        const context = canvas.getContext('2d');
        
        const viewport = page.getViewport({ scale: previewScale });
        canvas.width = viewport.width;
        canvas.height = viewport.height;
        
        if (previewRenderTask) {
            try {
                previewRenderTask.cancel();
            } catch (e) {
                // ignore cancel errors
            }
        }
        
        previewRenderTask = page.render({
            canvasContext: context,
            viewport: viewport
        });
        
        try {
            await previewRenderTask.promise;
        } catch (e) {
            // ignore render cancellation errors
        }

        renderPreviewOverlays(pageNum, viewport);
        
        $('#preview-page-info').text('Page ' + pageNum + ' of ' + previewPdf.numPages);
        $('#prev-preview').prop('disabled', pageNum <= 1);
        $('#next-preview').prop('disabled', pageNum >= previewPdf.numPages);
    }

    function renderPreviewOverlays(pageNum, viewport) {
        const overlay = $('#preview-field-overlay');
        const canvas = $('#preview-canvas');
        const container = $('#pdf-preview-container');

        overlay.empty();

        // Align overlay to canvas position/size
        const canvasPos = canvas.position();
        overlay.css({
            left: canvasPos.left + 'px',
            top: canvasPos.top + 'px',
            width: canvas.width() + 'px',
            height: canvas.height() + 'px'
        });

        detectedFields.forEach(function(field) {
            if (field.page !== pageNum || !field.rect) {
                return;
            }

            const [x1, y1, x2, y2] = field.rect;
            const x = x1 * viewport.scale;
            const y = viewport.height - (y2 * viewport.scale);
            const width = (x2 - x1) * viewport.scale;
            const height = (y2 - y1) * viewport.scale;

            const marker = $('<div>')
                .addClass('preview-field-marker')
                .attr('data-field-name', field.name)
                .css({
                    left: x + 'px',
                    top: y + 'px',
                    width: width + 'px',
                    height: height + 'px'
                });

            if (activePreviewField === field.name) {
                const input = $('.field-label-input[data-field-name="' + field.name + '"]');
                const displayLabel = input.length ? input.val() : field.name;
                const label = $('<div>')
                    .addClass('preview-field-label')
                    .text(displayLabel);
                marker.append(label).addClass('active');
            }
            overlay.append(marker);
        });

        if (activePreviewField) {
            scrollToPreviewField(activePreviewField);
        }
    }

    function highlightPreviewField(fieldName) {
        if (activePreviewField === fieldName) {
            return;
        }
        activePreviewField = fieldName;

        $('.preview-field-marker').removeClass('active');
        const marker = $('.preview-field-marker[data-field-name="' + fieldName + '"]');
        marker.addClass('active');
        marker.find('.preview-field-label').remove();
        const input = $('.field-label-input[data-field-name="' + fieldName + '"]');
        const displayLabel = input.length ? input.val() : fieldName;
        marker.append($('<div>').addClass('preview-field-label').text(displayLabel));
        scrollToPreviewField(fieldName);
    }

    function clearPreviewHighlight() {
        activePreviewField = null;
        $('.preview-field-marker').removeClass('active');
        $('.preview-field-label').remove();
    }

    function scrollToPreviewField(fieldName) {
        const marker = $('.preview-field-marker[data-field-name="' + fieldName + '"]');
        if (marker.length === 0) {
            return;
        }

        const container = $('#pdf-preview-container')[0];
        const containerRect = container.getBoundingClientRect();
        const markerRect = marker[0].getBoundingClientRect();

        const scrollTop = container.scrollTop + (markerRect.top - containerRect.top) - 120;
        const scrollLeft = container.scrollLeft + (markerRect.left - containerRect.left) - 120;

        $(container).animate({
            scrollTop: Math.max(scrollTop, 0),
            scrollLeft: Math.max(scrollLeft, 0)
        }, 300);
    }
    
    // Sort fields list
    function sortFieldsList(fields, sortBy) {
        return fields.sort((a, b) => {
            if (sortBy === 'page') {
                // Primary sort by page, secondary by Y position (top to bottom)
                if (a.page !== b.page) return a.page - b.page;
                // PDF Y coordinates: higher Y = higher on page, so sort descending
                const aY = a.rect ? a.rect[3] : 0; // rect[3] is top Y
                const bY = b.rect ? b.rect[3] : 0;
                if (aY !== bY) return bY - aY; // Descending (top of page first)
                // If same Y, sort by X (left to right)
                const aX = a.rect ? a.rect[0] : 0;
                const bX = b.rect ? b.rect[0] : 0;
                return aX - bX;
            } else if (sortBy === 'label') {
                // Sort by label (use name as fallback)
                const labelA = (a.name || '').replace(/_/g, ' ').toLowerCase();
                const labelB = (b.name || '').replace(/_/g, ' ').toLowerCase();
                return labelA.localeCompare(labelB);
            }
            return 0;
        });
    }
    
    // Save custom field labels
    function saveFieldLabels(agreementType, fields) {
        const fieldLabels = {};
        const fieldRequired = {};
        const fieldMappings = {};
        const fieldMetaKeys = {};
        const fieldsList = [];
        
        // Validate meta keys before saving
        let hasInvalidMetaKey = false;
        $('.field-mapping-select').each(function() {
            const fieldName = $(this).data('field-name');
            const mapping = $(this).val();
            if (mapping === 'meta') {
                const metaKey = $('.field-meta-key-input[data-field-name="' + fieldName + '"]').val();
                const validation = validateMetaKey(metaKey);
                if (!validation.valid) {
                    hasInvalidMetaKey = true;
                    $('.field-meta-key-input[data-field-name="' + fieldName + '"]').css('border-color', '#d63638');
                    $('.psf-mapping-wrapper[data-field-name="' + fieldName + '"] .psf-meta-key-error').text(validation.error).show();
                }
            }
        });
        
        if (hasInvalidMetaKey) {
            alert('❌ Please fix invalid meta key values before saving.');
            return;
        }
        
        // Only save labels for fields that still exist (not deleted)
        $('.field-label-input').each(function() {
            const fieldName = $(this).data('field-name');
            const label = $(this).val().trim();
            if (label) {
                fieldLabels[fieldName] = label;
            }
        });
        
        // Collect required checkboxes
        $('.field-required-checkbox').each(function() {
            const fieldName = $(this).data('field-name');
            fieldRequired[fieldName] = $(this).is(':checked');
        });
        
        // Collect field mappings and meta keys
        $('.field-mapping-select').each(function() {
            const fieldName = $(this).data('field-name');
            const mapping = $(this).val();
            if (mapping) {
                fieldMappings[fieldName] = mapping;
                // If meta mapping, also store the meta key
                if (mapping === 'meta') {
                    const metaKey = $('.field-meta-key-input[data-field-name="' + fieldName + '"]').val();
                    if (metaKey) {
                        fieldMetaKeys[fieldName] = metaKey;
                    }
                }
            }
        });
        
        // Get signature settings from upload form
        const signatureSettings = {
            x: parseInt($('#upload-sig-pos-x').val()) || 72,
            y: parseInt($('#upload-sig-pos-y').val()) || 68,
            width: parseInt($('#upload-sig-width').val()) || 120,
            height: parseInt($('#upload-sig-height').val()) || 35,
            page: uploadPreviewPage || 1
        };
        
        // Get date settings from upload form
        const dateSettings = {
            enabled: $('#upload-date-enabled').is(':checked'),
            x: parseInt($('#upload-date-pos-x').val()) || 350,
            y: parseInt($('#upload-date-pos-y').val()) || 68,
            fontSize: parseInt($('#upload-date-size').val()) || 10,
            page: uploadPreviewPage || 1
        };
        
        // Store COMPLETE field structure - includes ALL field data
        // This is the canonical source of truth for all field configuration
        detectedFields.forEach(function(field) {
            const fieldName = field.name;
            const fieldData = {
                name: fieldName,
                type: field.type || 'text',
                page: field.page || 1,
                label: fieldLabels[fieldName] || fieldName.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase()),
                required: fieldRequired[fieldName] || false,
                maps_to: fieldMappings[fieldName] || '',
                meta_key: (fieldMappings[fieldName] === 'meta' && fieldMetaKeys[fieldName]) ? fieldMetaKeys[fieldName] : ''
            };
            // Include position data for manual fields
            if (field.isManual && field.position) {
                fieldData.isManual = true;
                fieldData.position = field.position;
            }
            fieldsList.push(fieldData);
        });
        
        // Build save data
        const saveData = {
            action: 'swpdf_save_field_labels',
            nonce: swpdfAdmin.nonce,
            agreement_type: agreementType,
            field_labels: JSON.stringify(fieldLabels),
            field_required: JSON.stringify(fieldRequired),
            field_mappings: JSON.stringify(fieldMappings),
            field_meta_keys: JSON.stringify(fieldMetaKeys),
            fields_list: JSON.stringify(fieldsList),
            signature_settings: JSON.stringify(signatureSettings),
            date_settings: JSON.stringify(dateSettings)
        };
        
        // If this is a new upload, include template info to register it
        if (window.pendingTemplateUpload && window.pendingTemplateUpload.agreement_type === agreementType) {
            saveData.template_name = window.pendingTemplateUpload.template_name;
            saveData.filename = window.pendingTemplateUpload.filename;
        }
        
        $.ajax({
            url: swpdfAdmin.ajaxUrl,
            type: 'POST',
            data: saveData,
            success: function(response) {
                if (response.success) {
                    // Clear pending upload
                    window.pendingTemplateUpload = null;
                    alert('✅ Template saved successfully!');
                    // Redirect to templates list
                    window.location.href = window.location.pathname + '?page=swpdf-templates&tab=list';
                } else {
                    alert('❌ Error saving: ' + (response.data.message || 'Unknown error'));
                }
            },
            error: function() {
                alert('❌ Error saving settings');
            }
        });
    }
    
    // Duplicate template
    $('.duplicate-template').on('click', function() {
        const $btn = $(this);
        const type = $btn.data('type');
        
        if (!confirm('Create a copy of this template with all its settings?')) {
            return;
        }
        
        $btn.prop('disabled', true).text('Duplicating...');
        
        $.ajax({
            url: swpdfAdmin.ajaxUrl,
            type: 'POST',
            data: {
                action: 'swpdf_duplicate_template',
                nonce: swpdfAdmin.nonce,
                agreement_type: type
            },
            success: function(response) {
                if (response.success) {
                    alert('✅ Template duplicated! New template: ' + response.data.new_name);
                    location.reload();
                } else {
                    alert('Error: ' + (response.data.message || 'Failed to duplicate template'));
                    $btn.prop('disabled', false).text('📋 Duplicate');
                }
            },
            error: function() {
                alert('Error duplicating template. Please try again.');
                $btn.prop('disabled', false).text('📋 Duplicate');
            }
        });
    });
    
    // Delete template
    $('.delete-template').on('click', function() {
        const $btn = $(this);
        const type = $btn.data('type');
        const filename = $btn.data('filename');
        
        if (!confirm('Are you sure you want to delete this template? This cannot be undone.')) {
            return;
        }
        
        $btn.prop('disabled', true).text('Deleting...');
        
        $.ajax({
            url: swpdfAdmin.ajaxUrl,
            type: 'POST',
            data: {
                action: 'swpdf_delete_pdf_template',
                nonce: swpdfAdmin.nonce,
                agreement_type: type,
                filename: filename
            },
            success: function(response) {
                if (response.success) {
                    alert('Template deleted successfully!');
                    location.reload();
                } else {
                    alert('Error: ' + (response.data.message || 'Failed to delete template'));
                    $btn.prop('disabled', false).text('Delete');
                }
            },
            error: function() {
                alert('Error deleting template. Please try again.');
                $btn.prop('disabled', false).text('Delete');
            }
        });
    });
    
    // Edit template labels (use event delegation for dynamically loaded buttons)
    $(document).on('click', '.edit-template-labels', function() {
        const $btn = $(this);
        const type = $btn.data('type');
        const filename = $btn.data('filename');
        
        swpdfLog('=== EDIT TEMPLATE CLICKED ===');
        swpdfLog('Agreement Type:', type);
        swpdfLog('Filename:', filename);
        
        // CRITICAL: Clear previous state before loading new template
        clearEditModalState();
        
        $btn.prop('disabled', true).text('Loading...');
        
        // Load PDF and detect fields
        $.ajax({
            url: swpdfAdmin.ajaxUrl,
            type: 'POST',
            data: {
                action: 'swpdf_get_template_for_edit',
                nonce: swpdfAdmin.nonce,
                agreement_type: type,
                filename: filename
            },
            success: function(response) {
                swpdfLog('Edit template AJAX response:', response);
                swpdfLog('Fields list count:', response.data?.fields_list?.length || 0);
                swpdfLog('Signature settings received:', response.data?.signature_settings);
                
                if (response.success) {
                    // Set the current agreement type BEFORE showing modal
                    currentAgreementType = type;
                    showEditLabelsModal(type, filename, response.data);
                } else {
                    alert('Error loading template fields: ' + (response.data ? response.data.message : 'Unknown error'));
                }
                $btn.prop('disabled', false).text('Edit Labels');
            },
            error: function(xhr, status, error) {
                console.error('AJAX error:', status, error);
                alert('Error loading template: ' + error);
                $btn.prop('disabled', false).text('Edit Labels');
            }
        });
    });
    
    // Clear all edit modal state to prevent cross-template contamination
    function clearEditModalState() {
        swpdfLog('Clearing edit modal state');
        window.editModalFieldsList = null;
        window.editModalFilename = null;
        window.editModalSignatureSettings = null;
        window.editModalDateSettings = null;
        sigPdfDoc = null;
        sigPdfScale = 1;
        sigPdfPageHeight = 792;
        currentAgreementType = null;
        
        // Remove event handlers that might persist
        $(document).off('mousemove.sigbox mouseup.sigbox');
        $(document).off('mousemove.editdatebox mouseup.editdatebox');
        $('#sig-pos-x, #sig-pos-y, #sig-width, #sig-height').off('change');
        $('#edit-date-pos-x, #edit-date-pos-y, #edit-date-size').off('change');
        $('#edit-date-enabled').off('change');
    }
    
    function showEditLabelsModal(agreementType, filename, data) {
        swpdfLog('=== showEditLabelsModal START ===');
        swpdfLog('Agreement Type:', agreementType);
        swpdfLog('Current Agreement Type (should match):', currentAgreementType);
        
        const existingLabels = data.field_labels || {};
        const existingRequired = data.field_required || {};
        const fieldsList = data.fields_list || [];
        
        // CRITICAL: Get signature settings specifically for THIS agreement type
        // Do NOT use cached/previous values
        const signatureSettings = data.signature_settings || { x: 72, y: 68, width: 120, height: 35, page: 0 };
        const dateSettings = data.date_settings || { enabled: false, x: 350, y: 68, fontSize: 10, page: 0 };
        
        swpdfLog('Signature Settings for', agreementType, ':', signatureSettings);
        swpdfLog('Date Settings for', agreementType, ':', dateSettings);
        swpdfLog('Fields List count:', fieldsList.length);
        
        // If no fields but template exists, allow editing signature at least
        if (fieldsList.length === 0) {
            swpdfLog('WARNING: No fields_list found for', agreementType);
            // Don't block - allow signature positioning even without fields
            // alert('No fields found for this template. Please re-upload the PDF to detect fields.');
            // return;
        }
        
        // Store fields list and filename for editing - FRESH copies, not references
        window.editModalFieldsList = fieldsList.length > 0 ? JSON.parse(JSON.stringify(fieldsList)) : [];
        window.editModalFilename = filename;
        // CRITICAL: Store signature settings as fresh copy for THIS template only
        window.editModalSignatureSettings = JSON.parse(JSON.stringify(signatureSettings));
        window.editModalDateSettings = JSON.parse(JSON.stringify(dateSettings));
        
        swpdfLog('Stored editModalSignatureSettings:', window.editModalSignatureSettings);
        
        // Build edit form with visual signature positioner
        let formHtml = '';
        
        // Signature Position Settings with Visual Editor
        formHtml += '<div style="background: #f0f6fc; border: 1px solid #c3d9ed; padding: 15px; margin-bottom: 20px; border-radius: 5px;">';
        formHtml += '<h4 style="margin-top: 0; color: #1d4ed8;">✍️ Signature Position - Drag the box to position</h4>';
        formHtml += '<div style="display: flex; gap: 20px; align-items: flex-start;">';
        
        // PDF Preview with draggable signature box - show full document
        formHtml += '<div style="flex: 1; position: relative; max-width: 600px;">';
        formHtml += '<div id="sig-pdf-container" style="position: relative; border: 2px solid #ccc; background: #525659; overflow: auto; max-height: 700px; min-height: 400px;">';
        formHtml += '<div id="sig-pdf-wrapper" style="position: relative; display: inline-block;">';
        formHtml += '<canvas id="sig-pdf-canvas" style="display: block;"></canvas>';
        formHtml += '<div id="sig-drag-box" style="position: absolute; border: 2px dashed #e74c3c; background: rgba(231, 76, 60, 0.3); cursor: move; display: flex; align-items: center; justify-content: center; font-size: 10px; color: #c0392b; font-weight: bold; z-index: 10;">✍️ SIG</div>';
        formHtml += '<div id="edit-date-drag-box" style="position: absolute; border: 2px dashed #27ae60; background: rgba(39, 174, 96, 0.3); cursor: move; display: flex; align-items: center; justify-content: center; font-size: 10px; color: #1e8449; font-weight: bold; z-index: 10;">📅 DATE</div>';
        formHtml += '</div>';
        formHtml += '</div>';
        formHtml += '<p style="font-size: 11px; color: #666; margin-top: 5px;">👆 Drag <span style="color: #e74c3c; font-weight: bold;">red box</span> = signature. Drag <span style="color: #27ae60; font-weight: bold;">green box</span> = date. Drag corner to resize.</p>';
        formHtml += '</div>';
        
        // Position values
        formHtml += '<div style="width: 150px; position: sticky; top: 20px;">';
        // Signature position inputs
        formHtml += '<div style="background: #fdf2f2; padding: 10px; border-radius: 4px; border: 1px solid #e74c3c; margin-bottom: 10px;">';
        formHtml += '<strong style="color: #c0392b; font-size: 12px;">✍️ Signature Position</strong>';
        formHtml += '<div style="margin-top: 8px;"><label style="display: block; font-size: 10px; color: #666;">X Position</label><input type="number" id="sig-pos-x" value="' + signatureSettings.x + '" style="width: 100%; padding: 4px; font-size: 12px;"></div>';
        formHtml += '<div style="margin-top: 5px;"><label style="display: block; font-size: 10px; color: #666;">Y (from bottom)</label><input type="number" id="sig-pos-y" value="' + signatureSettings.y + '" style="width: 100%; padding: 4px; font-size: 12px;"></div>';
        formHtml += '<div style="margin-top: 5px;"><label style="display: block; font-size: 10px; color: #666;">Width</label><input type="number" id="sig-width" value="' + signatureSettings.width + '" style="width: 100%; padding: 4px; font-size: 12px;"></div>';
        formHtml += '<div style="margin-top: 5px;"><label style="display: block; font-size: 10px; color: #666;">Height</label><input type="number" id="sig-height" value="' + signatureSettings.height + '" style="width: 100%; padding: 4px; font-size: 12px;"></div>';
        formHtml += '</div>';
        // Date position inputs
        var dateChecked = dateSettings.enabled ? ' checked' : '';
        var dateOpacity = dateSettings.enabled ? '1' : '0.5';
        var datePointerEvents = dateSettings.enabled ? 'auto' : 'none';
        formHtml += '<div style="background: #f2fdf4; padding: 10px; border-radius: 4px; border: 1px solid #27ae60; margin-bottom: 10px;">';
        formHtml += '<label style="display: flex; align-items: center; gap: 5px; cursor: pointer; margin-bottom: 8px;">';
        formHtml += '<input type="checkbox" id="edit-date-enabled"' + dateChecked + ' style="margin: 0;">';
        formHtml += '<strong style="color: #1e8449; font-size: 12px;">📅 Draw Date Here</strong>';
        formHtml += '</label>';
        formHtml += '<p style="font-size: 9px; color: #856404; margin: 0 0 8px 0; background: #fff8e5; padding: 4px; border-radius: 3px;">⚠️ Only enable if PDF has no date field!</p>';
        formHtml += '<div id="edit-date-position-inputs" style="opacity: ' + dateOpacity + '; pointer-events: ' + datePointerEvents + ';">';
        formHtml += '<div><label style="display: block; font-size: 10px; color: #666;">X Position</label><input type="number" id="edit-date-pos-x" value="' + (dateSettings.x || 350) + '" style="width: 100%; padding: 4px; font-size: 12px;"></div>';
        formHtml += '<div style="margin-top: 5px;"><label style="display: block; font-size: 10px; color: #666;">Y (from bottom)</label><input type="number" id="edit-date-pos-y" value="' + (dateSettings.y || 68) + '" style="width: 100%; padding: 4px; font-size: 12px;"></div>';
        formHtml += '<div style="margin-top: 5px;"><label style="display: block; font-size: 10px; color: #666;">Font Size</label><input type="number" id="edit-date-size" value="' + (dateSettings.fontSize || 10) + '" min="6" max="24" style="width: 100%; padding: 4px; font-size: 12px;"></div>';
        formHtml += '</div>';
        formHtml += '</div>';
        formHtml += '</div>';
        
        formHtml += '</div>'; // end flex
        formHtml += '</div>'; // end signature section
        
        // Field Mapping Help Section
        formHtml += '<div style="background: #fff8e5; border: 1px solid #ffcc00; padding: 15px; margin-bottom: 20px; border-radius: 5px;">';
        formHtml += '<h4 style="margin-top: 0; color: #856404;">📋 Field Mapping - How data appears in Signed Agreements</h4>';
        formHtml += '<p style="font-size: 12px; color: #666; margin-bottom: 10px;">The <strong>PDF Field Name</strong> (in the table below) determines which column the data appears in on the Signed Agreements page. Make sure your PDF uses these field names:</p>';
        formHtml += '<div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; font-size: 12px;">';
        formHtml += '<div style="background: #fff; padding: 10px; border-radius: 4px;"><strong>📛 Customer Name:</strong><br><code>Name_1</code>, <code>name</code>, <code>customer_name</code>, <code>full_name</code>, <code>client_name</code></div>';
        formHtml += '<div style="background: #fff; padding: 10px; border-radius: 4px;"><strong>📧 Email:</strong><br><code>Primary_email</code>, <code>email</code>, <code>customer_email</code>, <code>e_mail</code></div>';
        formHtml += '<div style="background: #fff; padding: 10px; border-radius: 4px;"><strong>📱 Phone:</strong><br><code>Preferred_phone</code>, <code>phone</code>, <code>customer_phone</code>, <code>undefined</code></div>';
        formHtml += '<div style="background: #fff; padding: 10px; border-radius: 4px;"><strong>🚗 Stock Number:</strong><br><code>Stock_number_on_website</code>, <code>stock_number</code>, <code>stock</code></div>';
        formHtml += '</div>';
        formHtml += '<p style="font-size: 11px; color: #856404; margin-top: 10px; margin-bottom: 0;">💡 <strong>Tip:</strong> Use the "Maps To" dropdown to specify which database column each field should save to. This overrides automatic detection.</p>';
        formHtml += '</div>';
        
        // Unmapped fields notice
        formHtml += '<div class="notice notice-info" style="margin-bottom: 15px; padding: 10px 12px;"><p style="margin: 0;">💡 Fields not mapped to a column are stored as agreement metadata and visible in agreement details / exports where supported.</p></div>';
        
        // Get existing field mappings and meta keys
        const existingMappings = data.field_mappings || {};
        const existingMetaKeys = data.field_meta_keys || {};
        
        // Calculate mapping stats and build notice
        const stats = countMappingStats(fieldsList, (fieldName) => existingMappings[fieldName] || '');
        formHtml += buildStatsNotice(stats);
        
        // Column preview box
        formHtml += buildColumnPreview();
        
        // Bulk actions toolbar (includes presets and auto-label)
        formHtml += buildBulkToolbar();
        
        // Sort controls row
        formHtml += '<div style="margin-bottom: 10px; display: flex; align-items: center; gap: 10px;">';
        formHtml += '<label style="font-weight: 500;">Sort by:</label>';
        formHtml += '<select id="edit-field-sort-by" class="regular-text" style="width: auto;">';
        formHtml += '<option value="page" selected>Page</option>';
        formHtml += '<option value="label">Label</option>';
        formHtml += '<option value="mapped">Mapping Status</option>';
        formHtml += '</select>';
        formHtml += '</div>';
        
        formHtml += '<p style="margin-bottom: 15px;"><strong>📝 Edit labels, set required fields, map to database columns, or delete fields:</strong></p>';
        
        // Table with sticky header
        formHtml += '<div class="psf-table-wrapper" style="max-height: 450px; overflow-y: auto; border: 1px solid #c3c4c7; border-radius: 4px;">';
        formHtml += '<table class="wp-list-table widefat striped psf-field-table" style="margin: 0;">';
        formHtml += '<thead style="position: sticky; top: 0; z-index: 5; background: #f6f7f7;">';
        formHtml += '<tr>';
        formHtml += '<th width="18%">PDF Field Name</th>';
        formHtml += '<th width="22%">Display Label</th>';
        formHtml += '<th width="18%">Maps To</th>';
        formHtml += '<th width="15%">Saved As</th>';
        formHtml += '<th width="7%" style="text-align:center;">Required</th>';
        formHtml += '<th width="7%">Type</th>';
        formHtml += '<th width="5%">Page</th>';
        formHtml += '<th width="8%">Action</th>';
        formHtml += '</tr>';
        formHtml += '</thead>';
        formHtml += '<tbody id="edit-fields-tbody">';
        
        // Sort fields by page then name
        const sortedFieldsList = sortFieldsList([...fieldsList], 'page');
        
        sortedFieldsList.forEach(function(field) {
            const currentLabel = existingLabels[field.name] || field.name.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
            const isRequired = existingRequired[field.name] !== undefined ? existingRequired[field.name] : false;
            const currentMapping = existingMappings[field.name] || '';
            const currentMetaKey = existingMetaKeys[field.name] || '';
            const typeWarning = getTypeMismatchWarning(field.type, currentMapping);
            const savedAsPreview = getSavedAsPreview(currentMapping, currentMetaKey, field.name);
            const rowBadges = getRowBadges(currentMapping, isRequired, field.type);
            
            formHtml += '<tr data-field-name="' + escapeHtml(field.name) + '" data-page="' + field.page + '" data-mapping="' + currentMapping + '">';
            formHtml += '<td><code style="font-size: 10px;">' + escapeHtml(field.name) + '</code></td>';
            formHtml += '<td><input type="text" class="regular-text field-label-edit-input" data-field-name="' + escapeHtml(field.name) + '" value="' + escapeHtml(currentLabel) + '" style="width: 100%;"></td>';
            formHtml += '<td style="min-width: 160px;">';
            formHtml += '<div class="psf-mapping-wrapper" data-field-name="' + escapeHtml(field.name) + '">';
            formHtml += '<select class="field-mapping-select" data-field-name="' + escapeHtml(field.name) + '" style="width: ' + (currentMapping === 'meta' ? '45%' : '100%') + ';">';
            formHtml += '<option value=""' + (currentMapping === '' ? ' selected' : '') + '>-- Auto --</option>';
            formHtml += '<option value="customer_name"' + (currentMapping === 'customer_name' ? ' selected' : '') + '>📛 Customer Name</option>';
            formHtml += '<option value="customer_email"' + (currentMapping === 'customer_email' ? ' selected' : '') + '>📧 Email</option>';
            formHtml += '<option value="customer_phone"' + (currentMapping === 'customer_phone' ? ' selected' : '') + '>📱 Phone</option>';
            formHtml += '<option value="stock_number"' + (currentMapping === 'stock_number' ? ' selected' : '') + '>🚗 Stock Number</option>';
            formHtml += '<option value="meta"' + (currentMapping === 'meta' ? ' selected' : '') + '>🏷️ Custom Meta</option>';
            formHtml += '</select>';
            formHtml += '<input type="text" class="field-meta-key-input" data-field-name="' + escapeHtml(field.name) + '" placeholder="meta_key" value="' + escapeHtml(currentMetaKey) + '" style="width: 50%; margin-left: 4px; display: ' + (currentMapping === 'meta' ? 'inline-block' : 'none') + ';" pattern="[a-z0-9_]{2,40}" title="Lowercase letters, numbers, underscores. 2-40 chars.">';
            formHtml += '<span class="psf-meta-key-error" style="display: none; color: #d63638; font-size: 11px;"></span>';
            formHtml += typeWarning;
            formHtml += '</div>';
            formHtml += '</td>';
            formHtml += '<td class="psf-saved-as-cell" style="font-size: 11px;">' + savedAsPreview + '</td>';
            formHtml += '<td style="text-align:center;"><input type="checkbox" class="field-required-checkbox" data-field-name="' + escapeHtml(field.name) + '" ' + (isRequired ? 'checked' : '') + '></td>';
            formHtml += '<td style="font-size: 11px;">' + escapeHtml(field.type) + '</td>';
            formHtml += '<td>' + field.page + '</td>';
            formHtml += '<td><button type="button" class="button button-small delete-edit-field-btn" data-field-name="' + escapeHtml(field.name) + '" title="Delete this field">🗑️</button></td>';
            formHtml += '</tr>';
        });
        
        formHtml += '</tbody></table>';
        formHtml += '</div>'; // Close table wrapper
        
        $('#edit-labels-content').html(formHtml);
        $('#edit-labels-modal').fadeIn();
        
        // Store agreement type for saving
        $('#edit-labels-modal').data('agreement-type', agreementType);
        
        // Bind sort change for edit modal (with new mapping status option)
        $('#edit-field-sort-by').on('change', function() {
            const sortBy = $(this).val();
            const $tbody = $('#edit-fields-tbody');
            const rows = $tbody.find('tr').get();
            
            rows.sort(function(a, b) {
                if (sortBy === 'page') {
                    const pageA = parseInt($(a).data('page')) || 0;
                    const pageB = parseInt($(b).data('page')) || 0;
                    if (pageA !== pageB) return pageA - pageB;
                    return $(a).data('field-name').localeCompare($(b).data('field-name'));
                } else if (sortBy === 'mapped') {
                    // Unmapped first, then mapped
                    const mappingA = $(a).find('.field-mapping-select').val() || '';
                    const mappingB = $(b).find('.field-mapping-select').val() || '';
                    if ((mappingA === '') !== (mappingB === '')) {
                        return mappingA === '' ? -1 : 1;
                    }
                    return $(a).data('field-name').localeCompare($(b).data('field-name'));
                } else {
                    const labelA = $(a).find('.field-label-edit-input').val().toLowerCase();
                    const labelB = $(b).find('.field-label-edit-input').val().toLowerCase();
                    return labelA.localeCompare(labelB);
                }
            });
            
            $.each(rows, function(idx, row) {
                $tbody.append(row);
            });
        });
        
        // Bind bulk actions
        $('#psf-apply-bulk').on('click', function() {
            const action = $('#psf-bulk-action').val();
            if (!action) {
                showSaveFeedback('info', 'Please select a bulk action.');
                return;
            }
            
            switch(action) {
                case 'require_all':
                    $('.field-required-checkbox').prop('checked', true);
                    updateAllRowBadges();
                    break;
                case 'optional_all':
                    $('.field-required-checkbox').prop('checked', false);
                    updateAllRowBadges();
                    break;
                case 'clear_mappings':
                    if (confirm('Clear all field mappings? This will reset all fields to "Auto" and remove meta keys.')) {
                        $('.field-mapping-select').val('').trigger('change');
                    }
                    break;
            }
            
            // Reset dropdown
            $('#psf-bulk-action').val('');
            updateStatsNotice();
            updateDirtyState();
            updateColumnPreview();
        });
        
        // Bind preset application - canonical button #psf-preset-basic-contact
        $('#psf-preset-basic-contact').on('click', function() {
            applyBasicContactPreset();
        });
        
        // Bind auto-label button
        $('#psf-auto-label').on('click', function() {
            autoLabelFields();
        });
        
        // Bind field search/filter
        $('#psf-field-filter').on('input', function() {
            const filter = $(this).val().toLowerCase().trim();
            const $rows = $('#edit-fields-tbody tr');
            
            if (filter === '') {
                $rows.show();
            } else {
                $rows.each(function() {
                    const fieldName = $(this).data('field-name').toLowerCase();
                    const label = $(this).find('.field-label-edit-input').val().toLowerCase();
                    const mapping = $(this).find('.field-mapping-select option:selected').text().toLowerCase();
                    
                    if (fieldName.includes(filter) || label.includes(filter) || mapping.includes(filter)) {
                        $(this).show();
                    } else {
                        $(this).hide();
                    }
                });
            }
        });
        
        // Live update "Saved As" column and badges when mapping changes
        $('#edit-labels-content').on('change', '.field-mapping-select', function() {
            const fieldName = $(this).data('field-name');
            const mapping = $(this).val();
            const metaKey = $('.field-meta-key-input[data-field-name="' + fieldName + '"]').val();
            const $row = $(this).closest('tr');
            
            // Update Saved As preview
            $row.find('.psf-saved-as-cell').html(getSavedAsPreview(mapping, metaKey, fieldName));
            
            // Update row data attribute
            $row.attr('data-mapping', mapping);
            
            // Update badges
            const isRequired = $row.find('.field-required-checkbox').is(':checked');
            const fieldType = $row.find('td').eq(5).text();
            $row.find('.psf-status-cell').html(getRowBadges(mapping, isRequired, fieldType));
            
            // Update stats notice
            updateStatsNotice();
            
            // Update dirty state and column preview
            updateDirtyState();
            updateColumnPreview();
        });
        
        // Live update "Saved As" when meta key changes
        $('#edit-labels-content').on('input', '.field-meta-key-input', function() {
            const fieldName = $(this).data('field-name');
            const metaKey = $(this).val();
            const mapping = $('.field-mapping-select[data-field-name="' + fieldName + '"]').val();
            const $row = $(this).closest('tr');
            
            // Update Saved As preview
            $row.find('.psf-saved-as-cell').html(getSavedAsPreview(mapping, metaKey, fieldName));
            
            // Update dirty state
            updateDirtyState();
        });
        
        // Track changes on label inputs
        $('#edit-labels-content').on('input', '.field-label-edit-input', function() {
            updateDirtyState();
            updateColumnPreview();
        });
        
        // Update badges when required checkbox changes
        $('#edit-labels-content').on('change', '.field-required-checkbox', function() {
            const $row = $(this).closest('tr');
            const fieldName = $(this).data('field-name');
            const mapping = $('.field-mapping-select[data-field-name="' + fieldName + '"]').val();
            const isRequired = $(this).is(':checked');
            const fieldType = $row.find('td').eq(5).text();
            
            $row.find('.psf-status-cell').html(getRowBadges(mapping, isRequired, fieldType));
            
            // Update dirty state
            updateDirtyState();
        });
        
        // Initialize dirty state tracking after form is fully built
        setTimeout(function() {
            STATE.initialHash = captureFormState();
            STATE.isDirty = false;
            updateColumnPreview();
            updateDirtyState();
            setupBeforeUnload();
        }, 100);
        
        // Load PDF preview and setup draggable signature box
        // Pass the SPECIFIC signature settings for THIS template
        swpdfLog('About to load PDF preview with signature settings:', signatureSettings);
        setTimeout(() => {
            loadSignaturePdfPreview(filename, signatureSettings, agreementType);
        }, 100);
        
        // Bind delete buttons
        $('#edit-labels-content').off('click', '.delete-edit-field-btn').on('click', '.delete-edit-field-btn', function() {
            const fieldName = $(this).data('field-name');
            const $row = $(this).closest('tr');
            
            if (confirm('Delete field "' + fieldName + '"? This field will no longer be shown to users.')) {
                // Remove from fields list
                window.editModalFieldsList = window.editModalFieldsList.filter(f => f.name !== fieldName);
                // Remove row
                $row.fadeOut(300, function() {
                    $(this).remove();
                    // Update stats and UI after removal
                    updateStatsNotice();
                    updateDirtyState();
                    updateColumnPreview();
                });
            }
        });
    }
    
    // Clear all edit modal state to prevent cross-template contamination (moved definition)
    function clearEditModalStateExt() {
        STATE.isDirty = false;
        STATE.initialHash = '';
        STATE.coreMappings = {};
        STATE.metaMappings = {};
        STATE.labels = {};
        STATE.duplicateColumns = [];
        STATE.duplicateFields = [];
        $('#psf-unsaved-indicator, .psf-dirty-badge').remove();
        $('.psf-duplicate-notice').remove();
        $(window).off('beforeunload.psf');
    }
    
    /**
     * Update all row badges (used after bulk actions)
     */
    function updateAllRowBadges() {
        $('#edit-fields-tbody tr').each(function() {
            const $row = $(this);
            const fieldName = $row.data('field-name');
            const mapping = $row.find('.field-mapping-select').val();
            const isRequired = $row.find('.field-required-checkbox').is(':checked');
            const fieldType = $row.find('td').eq(5).text();
            
            $row.find('.psf-status-cell').html(getRowBadges(mapping, isRequired, fieldType));
        });
    }
    
    /**
     * Update the stats notice based on current mappings
     */
    function updateStatsNotice() {
        const $rows = $('#edit-fields-tbody tr');
        let mapped = 0;
        let unmapped = 0;
        let customMeta = 0;
        
        $rows.each(function() {
            const mapping = $(this).find('.field-mapping-select').val();
            if (mapping && mapping !== '') {
                mapped++;
                if (mapping === 'meta') customMeta++;
            } else {
                unmapped++;
            }
        });
        
        const total = $rows.length;
        const stats = { mapped, unmapped, customMeta, total };
        
        // Replace existing notice
        $('.psf-field-stats').replaceWith(buildStatsNotice(stats));
    }
    
    // Close modal - CLEAR STATE to prevent contamination
    $('#close-edit-modal, #cancel-edit-labels').on('click', function() {
        // Check for unsaved changes
        if (PSF_MAPPING_STATE && PSF_MAPPING_STATE.isDirty) {
            if (!confirm('You have unsaved changes. Are you sure you want to close?')) {
                return;
            }
        }
        
        swpdfLog('Modal closed - clearing state');
        clearEditModalState();
        clearEditModalStateExt();
        $('#edit-labels-modal').fadeOut();
    });
    
    // Save edited labels - with UX feedback
    $('#save-edited-labels').on('click', function() {
        const $saveBtn = $(this);
        const agreementType = $('#edit-labels-modal').data('agreement-type');
        swpdfLog('=== SAVING LABELS ===');
        swpdfLog('Agreement Type:', agreementType);
        swpdfLog('Current Agreement Type (tracked):', currentAgreementType);
        
        // Safety check - these should match
        if (currentAgreementType && currentAgreementType !== agreementType) {
            console.error('PSF MISMATCH: Saving to', agreementType, 'but loaded', currentAgreementType);
        }
        
        const fieldLabels = {};
        const fieldRequired = {};
        const fieldMappings = {};
        const fieldMetaKeys = {};
        
        // Remove previous save feedback
        $('.psf-save-feedback').remove();
        
        // Check for duplicate core column mappings before saving
        if (!validateDuplicateMappings()) {
            showSaveFeedback('error', 'Please fix duplicate column mappings before saving.');
            return;
        }
        
        // Validate meta keys before saving
        let hasInvalidMetaKey = false;
        $('.field-mapping-select').each(function() {
            const fieldName = $(this).data('field-name');
            const mapping = $(this).val();
            if (mapping === 'meta') {
                const metaKey = $('.field-meta-key-input[data-field-name="' + fieldName + '"]').val();
                const validation = validateMetaKey(metaKey);
                if (!validation.valid) {
                    hasInvalidMetaKey = true;
                    $('.field-meta-key-input[data-field-name="' + fieldName + '"]').css('border-color', '#d63638');
                    $('.psf-mapping-wrapper[data-field-name="' + fieldName + '"] .psf-meta-key-error').text(validation.error).show();
                }
            }
        });
        
        if (hasInvalidMetaKey) {
            showSaveFeedback('error', 'Please fix invalid meta key values before saving.');
            return;
        }
        
        // Show saving state
        const originalBtnText = $saveBtn.text();
        $saveBtn.prop('disabled', true).html('<span class="spinner is-active" style="margin: 0 5px 0 0; float: none;"></span> Saving...');
        
        // Collect signature position settings from INPUT FIELDS (current values)
        const originalSettings = window.editModalSignatureSettings || {};
        const signatureSettings = {
            x: parseInt($('#sig-pos-x').val()) || 72,
            y: parseInt($('#sig-pos-y').val()) || 68,
            width: parseInt($('#sig-width').val()) || 120,
            height: parseInt($('#sig-height').val()) || 35,
            page: originalSettings.page || 0
        };
        
        // Collect date position settings from edit modal
        const originalDateSettings = window.editModalDateSettings || {};
        const dateSettings = {
            enabled: $('#edit-date-enabled').is(':checked'),
            x: parseInt($('#edit-date-pos-x').val()) || 350,
            y: parseInt($('#edit-date-pos-y').val()) || 68,
            fontSize: parseInt($('#edit-date-size').val()) || 10,
            page: originalDateSettings.page || 0
        };
        
        swpdfLog('Signature Settings to save:', signatureSettings);
        swpdfLog('Date Settings to save:', dateSettings);
        
        // Only collect labels for remaining fields
        $('.field-label-edit-input').each(function() {
            const fieldName = $(this).data('field-name');
            const label = $(this).val().trim();
            if (label) {
                fieldLabels[fieldName] = label;
            }
        });
        
        // Collect required checkboxes
        $('.field-required-checkbox').each(function() {
            const fieldName = $(this).data('field-name');
            fieldRequired[fieldName] = $(this).is(':checked');
        });
        
        // Collect field mappings and meta keys
        $('.field-mapping-select').each(function() {
            const fieldName = $(this).data('field-name');
            const mapping = $(this).val();
            if (mapping) {
                fieldMappings[fieldName] = mapping;
                if (mapping === 'meta') {
                    const metaKey = $('.field-meta-key-input[data-field-name="' + fieldName + '"]').val();
                    if (metaKey) {
                        fieldMetaKeys[fieldName] = metaKey;
                    }
                }
            }
        });
        
        // Get updated fields list (with deleted fields removed)
        // CRITICAL: Merge collected DOM values back into fieldsList before saving
        const fieldsList = window.editModalFieldsList || [];
        
        // Update each field in the list with current DOM values
        fieldsList.forEach(function(field) {
            const fieldName = field.name;
            // Update label
            if (fieldLabels[fieldName] !== undefined) {
                field.label = fieldLabels[fieldName];
            }
            // Update required
            if (fieldRequired[fieldName] !== undefined) {
                field.required = fieldRequired[fieldName];
            }
            // Update mapping - use empty string if not mapped
            field.maps_to = fieldMappings[fieldName] || '';
            // Update meta_key
            if (field.maps_to === 'meta' && fieldMetaKeys[fieldName]) {
                field.meta_key = fieldMetaKeys[fieldName];
            } else {
                field.meta_key = '';
            }
        });
        
        swpdfLog('=== Saving Signature Settings ===', signatureSettings);
        swpdfLog('=== Fields List with merged mappings ===', fieldsList);
        
        $.ajax({
            url: swpdfAdmin.ajaxUrl,
            type: 'POST',
            data: {
                action: 'swpdf_save_field_labels',
                nonce: swpdfAdmin.nonce,
                agreement_type: agreementType,
                field_labels: JSON.stringify(fieldLabels),
                field_required: JSON.stringify(fieldRequired),
                field_mappings: JSON.stringify(fieldMappings),
                field_meta_keys: JSON.stringify(fieldMetaKeys),
                fields_list: JSON.stringify(fieldsList),
                signature_settings: JSON.stringify(signatureSettings),
                date_settings: JSON.stringify(dateSettings)
            },
            success: function(response) {
                $saveBtn.prop('disabled', false).text(originalBtnText);
                
                if (response.success) {
                    showSaveFeedback('success', 'Field labels saved successfully!');
                    
                    // Close modal after short delay so user sees success message
                    setTimeout(function() {
                        clearEditModalState();
                        clearEditModalStateExt();
                        $('#edit-labels-modal').fadeOut();
                        location.reload();
                    }, 1500);
                } else {
                    // Show server-side duplicate error with details
                    let errorMsg = response.data.message || 'Failed to save. Please try again.';
                    if (response.data.duplicate_columns) {
                        errorMsg += ' Columns: ' + response.data.duplicate_columns.join(', ');
                    }
                    showSaveFeedback('error', errorMsg);
                    
                    // Highlight affected rows from server response
                    if (response.data.duplicate_fields) {
                        highlightDuplicateFields(response.data.duplicate_fields);
                    }
                }
            },
            error: function(xhr, status, error) {
                $saveBtn.prop('disabled', false).text(originalBtnText);
                showSaveFeedback('error', 'Network error. Please check your connection and try again.');
                console.error('Save error:', status, error);
            }
        });
    });
    
    /**
     * Show save feedback notice in modal footer
     */
    function showSaveFeedback(type, message) {
        const icons = { 'success': '✅', 'error': '❌', 'info': 'ℹ️' };
        const classes = { 'success': 'notice-success', 'error': 'notice-error', 'info': 'notice-info' };
        const icon = icons[type] || 'ℹ️';
        const noticeClass = classes[type] || 'notice-info';
        
        // Remove existing feedback
        $('.psf-save-feedback').remove();
        
        // Create feedback notice
        const $notice = $('<div class="psf-save-feedback notice ' + noticeClass + ' inline" style="margin: 0 15px 0 0; padding: 8px 12px; display: inline-block;">')
            .html('<p style="margin: 0;">' + icon + ' ' + escapeHtml(message) + '</p>');
        
        // Insert before save button
        $('#save-edited-labels').before($notice);
        
        // Auto-remove non-success messages after 5 seconds
        if (type !== 'success') {
            setTimeout(function() {
                $notice.fadeOut(300, function() { $(this).remove(); });
            }, 5000);
        }
    }
    
    /**
     * Highlight duplicate fields from server response
     * @param {Object} duplicateFields - {column: [fieldname1, fieldname2, ...]}
     */
    function highlightDuplicateFields(duplicateFields) {
        // Remove any existing server-side duplicate highlights
        $('.psf-server-duplicate').remove();
        $('.psf-row-duplicate').removeClass('psf-row-duplicate');
        
        // Highlight each affected field
        Object.keys(duplicateFields).forEach(function(column) {
            const fieldNames = duplicateFields[column];
            const columnLabel = CORE_COLUMN_LABELS[column] || column;
            
            fieldNames.forEach(function(fieldName) {
                const $row = $('#edit-fields-tbody tr[data-field-name="' + fieldName + '"]');
                if ($row.length) {
                    $row.addClass('psf-row-duplicate');
                    const $wrapper = $row.find('.psf-mapping-wrapper');
                    if ($wrapper.find('.psf-server-duplicate').length === 0) {
                        $wrapper.append('<span class="psf-server-duplicate psf-duplicate-warning">⚠️ Server: Duplicate mapping to ' + escapeHtml(columnLabel) + '</span>');
                    }
                }
            });
        });
    }
    
    // PDF Preview for signature positioning
    let sigPdfDoc = null;
    let sigPdfScale = 1;
    let sigPdfPageHeight = 792; // Default letter size
    let sigPdfAgreementType = null; // Track which template this preview belongs to
    
    async function loadSignaturePdfPreview(filename, signatureSettings, agreementType) {
        swpdfLog('=== loadSignaturePdfPreview START ===');
        swpdfLog('Filename:', filename);
        swpdfLog('Agreement Type:', agreementType);
        swpdfLog('Signature Settings:', signatureSettings);
        
        // Store the agreement type this preview is for
        sigPdfAgreementType = agreementType;
        
        try {
            const pdfUrl = swpdfAdmin.templatesUrl + filename + '?v=' + Date.now();
            const loadingTask = pdfjsLib.getDocument(pdfUrl);
            sigPdfDoc = await loadingTask.promise;
            
            // Determine which page to show (use saved page or default to last)
            const savedPage = signatureSettings.page || 0;
            const pageNum = savedPage > 0 ? Math.min(savedPage, sigPdfDoc.numPages) : sigPdfDoc.numPages;
            swpdfLog('Rendering page:', pageNum, 'of', sigPdfDoc.numPages);
            
            const page = await sigPdfDoc.getPage(pageNum);
            const viewport = page.getViewport({ scale: 1 });
            
            // Calculate scale to fit in container (600px wide to match upload flow)
            const containerWidth = 600;
            sigPdfScale = containerWidth / viewport.width;
            sigPdfPageHeight = viewport.height;
            
            const scaledViewport = page.getViewport({ scale: sigPdfScale });
            
            const canvas = document.getElementById('sig-pdf-canvas');
            const ctx = canvas.getContext('2d');
            canvas.width = scaledViewport.width;
            canvas.height = scaledViewport.height;
            
            await page.render({
                canvasContext: ctx,
                viewport: scaledViewport
            }).promise;
            
            // CRITICAL: Update input fields with the CORRECT values BEFORE positioning box
            $('#sig-pos-x').val(signatureSettings.x || 72);
            $('#sig-pos-y').val(signatureSettings.y || 68);
            $('#sig-width').val(signatureSettings.width || 120);
            $('#sig-height').val(signatureSettings.height || 35);
            
            swpdfLog('Input fields set to:', {
                x: $('#sig-pos-x').val(),
                y: $('#sig-pos-y').val(),
                width: $('#sig-width').val(),
                height: $('#sig-height').val()
            });
            
            // Position the signature drag box using the provided settings
            updateSigBoxFromSettings(signatureSettings);
            
            // Position the date drag box using loaded settings
            const editDateSettings = window.editModalDateSettings || { enabled: false, x: 350, y: 68, fontSize: 10, page: 0 };
            updateEditDateBoxFromSettings(editDateSettings);
            // Show/hide date box based on enabled
            if (!editDateSettings.enabled) {
                $('#edit-date-drag-box').hide();
            }
            
            // Setup dragging
            setupSigBoxDragging();
            setupEditDateBoxDragging();
            
            // Update inputs when changed manually
            $('#sig-pos-x, #sig-pos-y, #sig-width, #sig-height').off('change').on('change', function() {
                updateSigBoxFromInputs();
                updateDirtyState();
            });
            
            // Date position input changes
            $('#edit-date-pos-x, #edit-date-pos-y, #edit-date-size').off('change').on('change', function() {
                updateEditDateBoxFromInputs();
                updateDirtyState();
            });
            
            // Date checkbox toggle in edit modal
            $('#edit-date-enabled').off('change').on('change', function() {
                const enabled = $(this).is(':checked');
                if (enabled) {
                    $('#edit-date-position-inputs').css({ opacity: 1, pointerEvents: 'auto' });
                    $('#edit-date-drag-box').show();
                    updateEditDateBoxFromInputs();
                } else {
                    $('#edit-date-position-inputs').css({ opacity: 0.5, pointerEvents: 'none' });
                    $('#edit-date-drag-box').hide();
                }
                updateDirtyState();
            });
            
        } catch (error) {
            console.error('Error loading PDF for signature preview:', error);
            $('#sig-pdf-container').html('<p style="padding: 20px; color: #999;">Could not load PDF preview</p>');
        }
    }
    
    function updateSigBoxFromSettings(settings) {
        const $box = $('#sig-drag-box');
        const canvas = document.getElementById('sig-pdf-canvas');
        if (!canvas) return;
        
        // Convert PDF coordinates to screen coordinates
        // PDF Y is from bottom of page, screen Y is from top of canvas
        // sigPdfPageHeight is the original PDF page height in PDF points
        const screenX = settings.x * sigPdfScale;
        const screenWidth = settings.width * sigPdfScale;
        const screenHeight = settings.height * sigPdfScale;
        
        // PDF Y is distance from bottom of page
        // Screen Y is distance from top of canvas
        // screenY = (pageHeight - pdfY - pdfHeight) * scale
        const screenY = (sigPdfPageHeight - settings.y - settings.height) * sigPdfScale;
        
        swpdfLog('Sig box position:', { 
            pdfSettings: settings,
            screenX, screenY, screenWidth, screenHeight, 
            canvasHeight: canvas.height, 
            pdfPageHeight: sigPdfPageHeight,
            scale: sigPdfScale 
        });
        
        // Ensure box is visible (clamp to canvas bounds)
        const clampedX = Math.max(0, Math.min(screenX, canvas.width - screenWidth));
        const clampedY = Math.max(0, Math.min(screenY, canvas.height - screenHeight));
        
        $box.css({
            left: clampedX + 'px',
            top: clampedY + 'px',
            width: Math.max(30, screenWidth) + 'px',
            height: Math.max(15, screenHeight) + 'px',
            display: 'flex'
        });
    }
    
    function updateSigBoxFromInputs() {
        const settings = {
            x: parseInt($('#sig-pos-x').val()) || 72,
            y: parseInt($('#sig-pos-y').val()) || 68,
            width: parseInt($('#sig-width').val()) || 120,
            height: parseInt($('#sig-height').val()) || 35
        };
        updateSigBoxFromSettings(settings);
    }
    
    function updateInputsFromBox() {
        const $box = $('#sig-drag-box');
        const canvas = document.getElementById('sig-pdf-canvas');
        if (!canvas) return;
        
        const screenX = parseFloat($box.css('left')) || 0;
        const screenY = parseFloat($box.css('top')) || 0;
        const screenWidth = $box.outerWidth();
        const screenHeight = $box.outerHeight();
        
        // Convert screen coordinates to PDF coordinates
        // screenY = (pageHeight - pdfY - pdfHeight) * scale
        // So: pdfY = pageHeight - (screenY / scale) - pdfHeight
        const pdfX = Math.round(screenX / sigPdfScale);
        const pdfWidth = Math.round(screenWidth / sigPdfScale);
        const pdfHeight = Math.round(screenHeight / sigPdfScale);
        const pdfY = Math.round(sigPdfPageHeight - (screenY / sigPdfScale) - pdfHeight);
        
        // Ensure positive values
        $('#sig-pos-x').val(Math.max(0, pdfX));
        $('#sig-pos-y').val(Math.max(0, pdfY));
        $('#sig-width').val(Math.max(20, pdfWidth));
        $('#sig-height').val(Math.max(10, pdfHeight));
        updateDirtyState();
    }
    
    function setupSigBoxDragging() {
        const $box = $('#sig-drag-box');
        let isDragging = false;
        let isResizing = false;
        let startX, startY, startLeft, startTop, startWidth, startHeight;
        
        // Add resize handle
        if ($box.find('.resize-handle').length === 0) {
            $box.append('<div class="resize-handle" style="position: absolute; right: -4px; bottom: -4px; width: 12px; height: 12px; background: #e74c3c; cursor: se-resize; border-radius: 2px;"></div>');
        }
        
        // Dragging
        $box.on('mousedown', function(e) {
            if ($(e.target).hasClass('resize-handle')) {
                // Start resizing
                isResizing = true;
                startX = e.pageX;
                startY = e.pageY;
                startWidth = $box.width();
                startHeight = $box.height();
            } else {
                // Start dragging
                isDragging = true;
                startX = e.pageX;
                startY = e.pageY;
                startLeft = parseFloat($box.css('left')) || 0;
                startTop = parseFloat($box.css('top')) || 0;
            }
            e.preventDefault();
        });
        
        $(document).on('mousemove.sigbox', function(e) {
            const canvas = document.getElementById('sig-pdf-canvas');
            if (!canvas) return;
            if (isDragging) {
                const dx = e.pageX - startX;
                const dy = e.pageY - startY;
                let newLeft = startLeft + dx;
                let newTop = startTop + dy;
                
                // Constrain to canvas bounds
                const maxLeft = canvas.width - $box.width();
                const maxTop = canvas.height - $box.height();
                newLeft = Math.max(0, Math.min(newLeft, maxLeft));
                newTop = Math.max(0, Math.min(newTop, maxTop));
                
                $box.css({ left: newLeft + 'px', top: newTop + 'px' });
                updateInputsFromBox();
            } else if (isResizing) {
                const dx = e.pageX - startX;
                const dy = e.pageY - startY;
                let newWidth = Math.max(30, startWidth + dx);
                let newHeight = Math.max(15, startHeight + dy);
                
                $box.css({ width: newWidth + 'px', height: newHeight + 'px' });
                updateInputsFromBox();
            }
        });
        
        $(document).on('mouseup.sigbox', function() {
            isDragging = false;
            isResizing = false;
        });
    }
    
    // Upload page: Signature preview variables
    let uploadSigPdfScale = 1;
    let uploadSigPdfPageHeight = 792;
    let uploadSigBaseScale = 1; // Base scale before zoom
    let currentUploadPdf = null; // Store PDF for re-rendering on zoom
    
    // Render signature preview for upload page
    async function renderUploadSignaturePreview(pdf, preservePositions = false, targetPage = null) {
        try {
            currentUploadPdf = pdf;
            // Use target page if specified, otherwise default to last page on first load
            const pageNum = targetPage || uploadPreviewPage || pdf.numPages;
            uploadPreviewPage = pageNum;
            const page = await pdf.getPage(pageNum);
            const viewport = page.getViewport({ scale: 1 });
            
            // Calculate base scale (fit to ~600px wide at 100% zoom)
            const baseWidth = 600;
            uploadSigBaseScale = baseWidth / viewport.width;
            uploadSigPdfPageHeight = viewport.height;
            
            // Apply zoom level
            uploadSigPdfScale = uploadSigBaseScale * uploadZoomLevel;
            
            const scaledViewport = page.getViewport({ scale: uploadSigPdfScale });
            
            const canvas = document.getElementById('upload-sig-pdf-canvas');
            if (!canvas) return;
            
            const ctx = canvas.getContext('2d');
            canvas.width = scaledViewport.width;
            canvas.height = scaledViewport.height;
            
            await page.render({
                canvasContext: ctx,
                viewport: scaledViewport
            }).promise;
            
            // Render detected field overlays for this page
            renderDetectedFieldOverlays(pageNum);
            
            // Position the signature drag box
            if (!preservePositions) {
                const defaultSettings = { x: 72, y: 68, width: 120, height: 35 };
                updateUploadSigBoxFromSettings(defaultSettings);
                // Position date box
                const defaultDateSettings = { x: 350, y: 68, fontSize: 10 };
                updateUploadDateBoxFromSettings(defaultDateSettings);
            } else {
                // Re-position based on current input values
                updateUploadSigBoxFromInputs();
                updateUploadDateBoxFromInputs();
                // Re-position all manual field boxes
                reRenderManualFieldBoxes();
            }
            
            // Setup dragging for upload page
            setupUploadSigBoxDragging();
            setupUploadDateBoxDragging();
            
            // Update inputs when changed manually
            $('#upload-sig-pos-x, #upload-sig-pos-y, #upload-sig-width, #upload-sig-height').off('change').on('change', function() {
                updateUploadSigBoxFromInputs();
            });
            
            // Date position input changes
            $('#upload-date-pos-x, #upload-date-pos-y, #upload-date-size').off('change').on('change', function() {
                updateUploadDateBoxFromInputs();
            });
            
            // Date checkbox toggle handler
            $('#upload-date-enabled').off('change').on('change', function() {
                const enabled = $(this).is(':checked');
                if (enabled) {
                    $('#date-position-inputs').css({ opacity: 1, pointerEvents: 'auto' });
                    $('#upload-date-drag-box').show();
                } else {
                    $('#date-position-inputs').css({ opacity: 0.5, pointerEvents: 'none' });
                    $('#upload-date-drag-box').hide();
                }
            });
            
            // Apply initial date box visibility based on checkbox
            if (!$('#upload-date-enabled').is(':checked')) {
                $('#upload-date-drag-box').hide();
            }
            
            // Update zoom display
            $('#zoom-level-display').text(Math.round(uploadZoomLevel * 100) + '%');
            
            // Update page info
            $('#preview-page-info').text('Page ' + pageNum + ' of ' + pdf.numPages);
            
            // Update navigation button states
            $('#prev-preview').prop('disabled', pageNum <= 1);
            $('#next-preview').prop('disabled', pageNum >= pdf.numPages);
            
        } catch (error) {
            console.error('Error loading PDF for upload signature preview:', error);
        }
    }
    
    // Re-render all manual field boxes after zoom
    function reRenderManualFieldBoxes() {
        manualFields.forEach(function(field) {
            const boxId = 'field-box-' + field.name.replace(/[^a-zA-Z0-9]/g, '_');
            const $box = $('#' + boxId);
            if ($box.length && field.position) {
                const screenX = field.position.x * uploadSigPdfScale;
                const screenWidth = field.position.width * uploadSigPdfScale;
                const screenHeight = field.position.height * uploadSigPdfScale;
                const screenY = (uploadSigPdfPageHeight - field.position.y - field.position.height) * uploadSigPdfScale;
                
                $box.css({
                    left: screenX + 'px',
                    top: screenY + 'px',
                    width: screenWidth + 'px',
                    height: screenHeight + 'px'
                });
            }
        });
    }
    
    // Render detected field overlays on the PDF preview
    function renderDetectedFieldOverlays(pageNum) {
        // Remove existing detected field overlays
        $('.detected-field-overlay').remove();
        
        const $container = $('#upload-sig-pdf-wrapper');
        if (!$container.length) return;
        
        // Filter fields for current page
        const pageFields = detectedFields.filter(f => f.page === pageNum);
        
        pageFields.forEach(function(field) {
            if (!field.rect) return;
            
            // PDF rect is [x1, y1, x2, y2] from bottom-left
            const x1 = field.rect[0];
            const y1 = field.rect[1];
            const x2 = field.rect[2];
            const y2 = field.rect[3];
            
            const width = (x2 - x1) * uploadSigPdfScale;
            const height = (y2 - y1) * uploadSigPdfScale;
            const left = x1 * uploadSigPdfScale;
            // Convert from PDF coords (origin bottom-left) to screen coords (origin top-left)
            const top = (uploadSigPdfPageHeight - y2) * uploadSigPdfScale;
            
            const safeId = field.name.replace(/[^a-zA-Z0-9]/g, '_');
            
            const $overlay = $('<div class="detected-field-overlay" data-field-name="' + field.name + '" id="field-overlay-' + safeId + '"></div>');
            $overlay.css({
                position: 'absolute',
                left: left + 'px',
                top: top + 'px',
                width: Math.max(width, 20) + 'px',
                height: Math.max(height, 12) + 'px',
                border: '2px solid rgba(52, 152, 219, 0.7)',
                background: 'rgba(52, 152, 219, 0.15)',
                pointerEvents: 'none',
                zIndex: 5,
                fontSize: '9px',
                color: '#2980b9',
                overflow: 'hidden',
                whiteSpace: 'nowrap',
                textOverflow: 'ellipsis',
                padding: '1px 3px',
                boxSizing: 'border-box'
            });
            
            // Show abbreviated field name
            const shortName = field.name.length > 12 ? field.name.substring(0, 10) + '...' : field.name;
            $overlay.text(shortName);
            
            $container.append($overlay);
        });
    }
    
    // Highlight a specific field overlay (when editing in table)
    function highlightFieldOverlay(fieldName) {
        // Reset all overlays to default style
        $('.detected-field-overlay').css({
            border: '2px solid rgba(52, 152, 219, 0.7)',
            background: 'rgba(52, 152, 219, 0.15)',
            color: '#2980b9',
            fontWeight: 'normal'
        });
        
        if (!fieldName) return;
        
        const safeId = fieldName.replace(/[^a-zA-Z0-9]/g, '_');
        const $overlay = $('#field-overlay-' + safeId);
        
        if ($overlay.length) {
            // Highlight selected field in orange/yellow
            $overlay.css({
                border: '3px solid #f39c12',
                background: 'rgba(243, 156, 18, 0.4)',
                color: '#d35400',
                fontWeight: 'bold',
                zIndex: 6
            });
            
            // Scroll to the field if needed
            const $scrollContainer = $('#upload-sig-pdf-container');
            const overlayOffset = $overlay.position();
            const containerHeight = $scrollContainer.height();
            
            if (overlayOffset.top < $scrollContainer.scrollTop() || 
                overlayOffset.top > $scrollContainer.scrollTop() + containerHeight - 50) {
                $scrollContainer.animate({
                    scrollTop: overlayOffset.top - 100
                }, 200);
            }
        }
    }
    
    // Zoom controls
    $(document).on('click', '#zoom-in-btn', function() {
        uploadZoomLevel = Math.min(3.0, uploadZoomLevel + 0.25);
        if (currentUploadPdf) renderUploadSignaturePreview(currentUploadPdf, true, uploadPreviewPage);
    });
    
    $(document).on('click', '#zoom-out-btn', function() {
        uploadZoomLevel = Math.max(0.5, uploadZoomLevel - 0.25);
        if (currentUploadPdf) renderUploadSignaturePreview(currentUploadPdf, true, uploadPreviewPage);
    });
    
    $(document).on('click', '#zoom-fit-btn', function() {
        uploadZoomLevel = 1.0;
        if (currentUploadPdf) renderUploadSignaturePreview(currentUploadPdf, true, uploadPreviewPage);
    });
    
    $(document).on('click', '#zoom-150-btn', function() {
        uploadZoomLevel = 1.5;
        if (currentUploadPdf) renderUploadSignaturePreview(currentUploadPdf, true, uploadPreviewPage);
    });
    
    $(document).on('click', '#zoom-200-btn', function() {
        uploadZoomLevel = 2.0;
        if (currentUploadPdf) renderUploadSignaturePreview(currentUploadPdf, true, uploadPreviewPage);
    });
    
    // Field position inputs (for selected manual field)
    $(document).on('change', '#field-pos-x, #field-pos-y, #field-pos-width, #field-pos-height', function() {
        if (!selectedManualField) return;
        
        // Update field position from inputs
        selectedManualField.position = {
            x: parseInt($('#field-pos-x').val()) || 100,
            y: parseInt($('#field-pos-y').val()) || 400,
            width: parseInt($('#field-pos-width').val()) || 150,
            height: parseInt($('#field-pos-height').val()) || 20
        };
        
        // Update in detectedFields array
        const idx = detectedFields.findIndex(f => f.name === selectedManualField.name);
        if (idx !== -1) {
            detectedFields[idx] = selectedManualField;
        }
        
        // Update visual box
        const boxId = 'field-box-' + selectedManualField.name.replace(/[^a-zA-Z0-9]/g, '_');
        const $box = $('#' + boxId);
        if ($box.length) {
            const screenX = selectedManualField.position.x * uploadSigPdfScale;
            const screenWidth = selectedManualField.position.width * uploadSigPdfScale;
            const screenHeight = selectedManualField.position.height * uploadSigPdfScale;
            const screenY = (uploadSigPdfPageHeight - selectedManualField.position.y - selectedManualField.position.height) * uploadSigPdfScale;
            
            $box.css({
                left: screenX + 'px',
                top: screenY + 'px',
                width: screenWidth + 'px',
                height: screenHeight + 'px'
            });
        }
    });
    
    // Select a manual field for position editing
    function selectManualField(field) {
        selectedManualField = field;
        
        // Show position panel
        $('#selected-field-position').show();
        $('#selected-field-name').text(field.name.replace('manual_field_', 'Field '));
        
        // Fill in current position
        $('#field-pos-x').val(field.position.x || 100);
        $('#field-pos-y').val(field.position.y || 400);
        $('#field-pos-width').val(field.position.width || 150);
        $('#field-pos-height').val(field.position.height || 20);
        
        // Highlight the box
        $('.manual-field-selected').removeClass('manual-field-selected').css({
            'border-color': '#0073aa',
            'background': 'rgba(0, 115, 170, 0.2)'
        });
        
        const boxId = 'field-box-' + field.name.replace(/[^a-zA-Z0-9]/g, '_');
        $('#' + boxId).addClass('manual-field-selected').css({
            'border-color': '#e74c3c',
            'background': 'rgba(231, 76, 60, 0.3)'
        });
    }
    
    function updateUploadSigBoxFromSettings(settings) {
        const $box = $('#upload-sig-drag-box');
        const canvas = document.getElementById('upload-sig-pdf-canvas');
        if (!canvas) return;
        
        const screenX = settings.x * uploadSigPdfScale;
        const screenWidth = settings.width * uploadSigPdfScale;
        const screenHeight = settings.height * uploadSigPdfScale;
        const screenY = (uploadSigPdfPageHeight - settings.y - settings.height) * uploadSigPdfScale;
        
        const clampedX = Math.max(0, Math.min(screenX, canvas.width - screenWidth));
        const clampedY = Math.max(0, Math.min(screenY, canvas.height - screenHeight));
        
        $box.css({
            left: clampedX + 'px',
            top: clampedY + 'px',
            width: Math.max(30, screenWidth) + 'px',
            height: Math.max(15, screenHeight) + 'px',
            display: 'flex'
        });
    }
    
    function updateUploadSigBoxFromInputs() {
        const settings = {
            x: parseInt($('#upload-sig-pos-x').val()) || 72,
            y: parseInt($('#upload-sig-pos-y').val()) || 68,
            width: parseInt($('#upload-sig-width').val()) || 120,
            height: parseInt($('#upload-sig-height').val()) || 35
        };
        updateUploadSigBoxFromSettings(settings);
    }
    
    function updateUploadInputsFromBox() {
        const $box = $('#upload-sig-drag-box');
        const canvas = document.getElementById('upload-sig-pdf-canvas');
        if (!canvas) return;
        
        const screenX = parseFloat($box.css('left')) || 0;
        const screenY = parseFloat($box.css('top')) || 0;
        const screenWidth = $box.outerWidth();
        const screenHeight = $box.outerHeight();
        
        const pdfX = Math.round(screenX / uploadSigPdfScale);
        const pdfWidth = Math.round(screenWidth / uploadSigPdfScale);
        const pdfHeight = Math.round(screenHeight / uploadSigPdfScale);
        const pdfY = Math.round(uploadSigPdfPageHeight - (screenY / uploadSigPdfScale) - pdfHeight);
        
        $('#upload-sig-pos-x').val(Math.max(0, pdfX));
        $('#upload-sig-pos-y').val(Math.max(0, pdfY));
        $('#upload-sig-width').val(Math.max(20, pdfWidth));
        $('#upload-sig-height').val(Math.max(10, pdfHeight));
    }
    
    function setupUploadSigBoxDragging() {
        const $box = $('#upload-sig-drag-box');
        let isDragging = false;
        let isResizing = false;
        let startX, startY, startLeft, startTop, startWidth, startHeight;
        
        // Add resize handle
        if ($box.find('.resize-handle').length === 0) {
            $box.append('<div class="resize-handle" style="position: absolute; right: -4px; bottom: -4px; width: 12px; height: 12px; background: #e74c3c; cursor: se-resize; border-radius: 2px;"></div>');
        }
        
        $box.off('mousedown').on('mousedown', function(e) {
            if ($(e.target).hasClass('resize-handle')) {
                isResizing = true;
                startX = e.pageX;
                startY = e.pageY;
                startWidth = $box.width();
                startHeight = $box.height();
            } else {
                isDragging = true;
                startX = e.pageX;
                startY = e.pageY;
                startLeft = parseFloat($box.css('left')) || 0;
                startTop = parseFloat($box.css('top')) || 0;
            }
            e.preventDefault();
        });
        
        $(document).off('mousemove.uploadsigbox').on('mousemove.uploadsigbox', function(e) {
            const canvas = document.getElementById('upload-sig-pdf-canvas');
            if (!canvas) return;
            
            if (isDragging) {
                const dx = e.pageX - startX;
                const dy = e.pageY - startY;
                let newLeft = Math.max(0, Math.min(startLeft + dx, canvas.width - $box.width()));
                let newTop = Math.max(0, Math.min(startTop + dy, canvas.height - $box.height()));
                $box.css({ left: newLeft + 'px', top: newTop + 'px' });
                updateUploadInputsFromBox();
            } else if (isResizing) {
                const dx = e.pageX - startX;
                const dy = e.pageY - startY;
                $box.css({ 
                    width: Math.max(30, startWidth + dx) + 'px', 
                    height: Math.max(15, startHeight + dy) + 'px' 
                });
                updateUploadInputsFromBox();
            }
        });
        
        $(document).off('mouseup.uploadsigbox').on('mouseup.uploadsigbox', function() {
            isDragging = false;
            isResizing = false;
        });
    }
    
    // ========== DATE BOX FUNCTIONS (Edit Modal) ==========
    
    function updateEditDateBoxFromSettings(settings) {
        const $box = $('#edit-date-drag-box');
        const canvas = document.getElementById('sig-pdf-canvas');
        if (!canvas) return;
        
        const fontSize = settings.fontSize || 10;
        // Calculate width based on date format "01/27/26" - approximately 8 characters
        const charWidth = fontSize * 0.6;
        const boxWidth = charWidth * 8 + 8; // 8 chars + padding
        const boxHeight = fontSize + 6;
        
        const screenX = settings.x * sigPdfScale;
        const screenWidth = boxWidth * sigPdfScale;
        const screenHeight = boxHeight * sigPdfScale;
        const screenY = (sigPdfPageHeight - settings.y - boxHeight) * sigPdfScale;
        
        const clampedX = Math.max(0, Math.min(screenX, canvas.width - screenWidth));
        const clampedY = Math.max(0, Math.min(screenY, canvas.height - screenHeight));
        
        $box.css({
            left: clampedX + 'px',
            top: clampedY + 'px',
            width: Math.max(30, screenWidth) + 'px',
            height: Math.max(12, screenHeight) + 'px',
            display: 'flex',
            fontSize: Math.max(8, fontSize * sigPdfScale * 0.8) + 'px'
        });
    }
    
    function updateEditDateBoxFromInputs() {
        const settings = {
            x: parseInt($('#edit-date-pos-x').val()) || 350,
            y: parseInt($('#edit-date-pos-y').val()) || 68,
            fontSize: parseInt($('#edit-date-size').val()) || 10
        };
        updateEditDateBoxFromSettings(settings);
    }
    
    function updateEditDateInputsFromBox() {
        const $box = $('#edit-date-drag-box');
        const canvas = document.getElementById('sig-pdf-canvas');
        if (!canvas) return;
        
        const screenX = parseFloat($box.css('left')) || 0;
        const screenY = parseFloat($box.css('top')) || 0;
        
        // Convert screen coordinates to PDF coordinates
        const pdfX = screenX / sigPdfScale;
        const fontSize = parseInt($('#edit-date-size').val()) || 10;
        const boxHeight = fontSize + 6;
        const pdfY = sigPdfPageHeight - (screenY / sigPdfScale) - boxHeight;
        
        $('#edit-date-pos-x').val(Math.max(0, Math.round(pdfX)));
        $('#edit-date-pos-y').val(Math.max(0, Math.round(pdfY)));
        updateDirtyState();
    }
    
    function setupEditDateBoxDragging() {
        const $box = $('#edit-date-drag-box');
        let isDragging = false;
        let startX, startY, startLeft, startTop;
        
        $box.off('mousedown.editdatebox').on('mousedown.editdatebox', function(e) {
            isDragging = true;
            startX = e.pageX;
            startY = e.pageY;
            startLeft = parseFloat($box.css('left')) || 0;
            startTop = parseFloat($box.css('top')) || 0;
            e.preventDefault();
        });
        
        $(document).off('mousemove.editdatebox').on('mousemove.editdatebox', function(e) {
            const canvas = document.getElementById('sig-pdf-canvas');
            if (!canvas || !isDragging) return;
            
            const dx = e.pageX - startX;
            const dy = e.pageY - startY;
            let newLeft = Math.max(0, Math.min(startLeft + dx, canvas.width - $box.width()));
            let newTop = Math.max(0, Math.min(startTop + dy, canvas.height - $box.height()));
            $box.css({ left: newLeft + 'px', top: newTop + 'px' });
            updateEditDateInputsFromBox();
        });
        
        $(document).off('mouseup.editdatebox').on('mouseup.editdatebox', function() {
            isDragging = false;
        });
    }
    
    // ========== DATE BOX FUNCTIONS (Upload Page) ==========
    
    function updateUploadDateBoxFromSettings(settings) {
        const $box = $('#upload-date-drag-box');
        const canvas = document.getElementById('upload-sig-pdf-canvas');
        if (!canvas) return;
        
        const fontSize = settings.fontSize || 10;
        // Calculate width based on date format "01/27/26" - approximately 8 characters
        const charWidth = fontSize * 0.6;
        const boxWidth = charWidth * 8 + 8; // 8 chars + padding
        const boxHeight = fontSize + 6;
        
        const screenX = settings.x * uploadSigPdfScale;
        const screenWidth = boxWidth * uploadSigPdfScale;
        const screenHeight = boxHeight * uploadSigPdfScale;
        const screenY = (uploadSigPdfPageHeight - settings.y - boxHeight) * uploadSigPdfScale;
        
        const clampedX = Math.max(0, Math.min(screenX, canvas.width - screenWidth));
        const clampedY = Math.max(0, Math.min(screenY, canvas.height - screenHeight));
        
        $box.css({
            left: clampedX + 'px',
            top: clampedY + 'px',
            width: Math.max(30, screenWidth) + 'px',
            height: Math.max(12, screenHeight) + 'px',
            display: 'flex',
            fontSize: Math.max(8, fontSize * uploadSigPdfScale * 0.8) + 'px'
        });
    }
    
    function updateUploadDateBoxFromInputs() {
        const settings = {
            x: parseInt($('#upload-date-pos-x').val()) || 350,
            y: parseInt($('#upload-date-pos-y').val()) || 68,
            fontSize: parseInt($('#upload-date-size').val()) || 10
        };
        updateUploadDateBoxFromSettings(settings);
    }
    
    function updateUploadDateInputsFromBox() {
        const $box = $('#upload-date-drag-box');
        const canvas = document.getElementById('upload-sig-pdf-canvas');
        if (!canvas) return;
        
        const screenX = parseFloat($box.css('left')) || 0;
        const screenY = parseFloat($box.css('top')) || 0;
        const screenHeight = parseFloat($box.css('height')) || 16;
        
        // Convert screen coordinates to PDF coordinates
        const pdfX = screenX / uploadSigPdfScale;
        const fontSize = parseInt($('#upload-date-size').val()) || 10;
        const boxHeight = fontSize + 6;
        const pdfY = uploadSigPdfPageHeight - (screenY / uploadSigPdfScale) - boxHeight;
        
        $('#upload-date-pos-x').val(Math.max(0, Math.round(pdfX)));
        $('#upload-date-pos-y').val(Math.max(0, Math.round(pdfY)));
    }
    
    function setupUploadDateBoxDragging() {
        const $box = $('#upload-date-drag-box');
        let isDragging = false;
        let startX, startY, startLeft, startTop;
        
        $box.off('mousedown.datebox').on('mousedown.datebox', function(e) {
            isDragging = true;
            startX = e.pageX;
            startY = e.pageY;
            startLeft = parseFloat($box.css('left')) || 0;
            startTop = parseFloat($box.css('top')) || 0;
            e.preventDefault();
        });
        
        $(document).off('mousemove.uploaddatebox').on('mousemove.uploaddatebox', function(e) {
            const canvas = document.getElementById('upload-sig-pdf-canvas');
            if (!canvas || !isDragging) return;
            
            const dx = e.pageX - startX;
            const dy = e.pageY - startY;
            let newLeft = Math.max(0, Math.min(startLeft + dx, canvas.width - $box.width()));
            let newTop = Math.max(0, Math.min(startTop + dy, canvas.height - $box.height()));
            $box.css({ left: newLeft + 'px', top: newTop + 'px' });
            updateUploadDateInputsFromBox();
        });
        
        $(document).off('mouseup.uploaddatebox').on('mouseup.uploaddatebox', function() {
            isDragging = false;
        });
    }
    
})(jQuery);



