/**
 * Aysa Internal Linking Management
 * 
 * Handles the internal linking functionality in technical optimization
 * 
 * @package Aysa
 * @since 1.0.0
 */

(function($) {
    'use strict';

    class AysaInternalLinking {
        constructor() {
            this.settings = {};
            this.isProcessing = false;
            this.activePreviewRequest = null;
            this.init();
        }

        init() {
            // API Configuration
            const configuredBase = typeof window.AYSA_API_BASE === 'string' && window.AYSA_API_BASE.trim() !== ''
                ? window.AYSA_API_BASE.trim().replace(/\/+$/, '')
                : 'https://api.aysa.ai';
            this.apiBaseUrl = window.aysaInternalLinking?.apiBaseUrl || `${configuredBase}/api/aysa-plugin/internal-linking`;
            this.projectId = window.aysaInternalLinking?.projectId || this.getCurrentProjectId();
            
            console.log('🔗 API Base URL:', this.apiBaseUrl);
            console.log('🏗️ Project ID:', this.projectId);
            
            this.bindEvents();
            this.initSubtabs();
            this.loadSettings();
            this.loadReport();
            // Buttons no longer needed - history integrated directly in reports
            
            // Don't auto-load process results - only load reports data
        }

        bindEvents() {
            // Settings events - use event delegation for better reliability
            $(document).on('click', '#aysa-save-internal-linking-settings', this.saveSettings.bind(this));
            $(document).on('click', '#aysa-reset-internal-linking-settings', this.resetSettings.bind(this));
            
            // Preview events
            $('#aysa-preview-internal-links').on('click', this.previewLinks.bind(this));
            
            // Processing events
            $(document).on('click', '#aysa-preview-all-content', this.previewAllContent.bind(this));
            $(document).on('click', '#aysa-approve-changes', this.processAllContent.bind(this));
            $(document).on('click', '#aysa-close-preview, #aysa-cancel-preview', this.closePreviewModal.bind(this));
            // Close preview when clicking outside modal content (on overlay)
            $(document).on('click', '#aysa-preview-modal .aysa-modal-overlay', (e) => {
                // Only close when clicking directly on the overlay background
                if (e.target && e.currentTarget && e.target === e.currentTarget) {
                    this.closePreviewModal();
                }
            });
            // ESC key closes preview modal
            $(document).on('keydown', (e) => {
                if (e.key === 'Escape') {
                    this.closePreviewModal();
                }
            });
            
            // Debug/Cache events
            $(document).on('click', '#aysa-clear-protection-cache', this.clearProtectionCache.bind(this));
            
            // Reporting events
            $(document).on('click', '#aysa-refresh-reports', this.loadReport.bind(this));
            // Delete all links in project
            $(document).on('click', '#aysa-delete-all-links', async () => {
                if (!confirm('Are you sure you want to delete ALL internal links for this project? This cannot be undone.')) return;
                try {
                    const base = this.apiBaseUrl;
                    const url = `${base}/links/all?projectId=${this.projectId}`;
                    const response = await fetch(url, { method: 'DELETE' });
                    const result = await response.json();
                    if (result.success) {
                        const count = (result.data && (result.data.deletedCount || result.deletedCount)) || 0;
                        this.showNotification(`Deleted ${count} links from this project`, 'success');
                        
                        // Remove ALL aysa-internal-link anchors from content
                        try {
                            console.log('🧹 Removing ALL internal links from content...');
                            const unlinkResponse = await $.post(window.aysaInternalLinking?.ajaxUrl || window.aysaAjax?.ajaxUrl || ajaxurl, {
                                action: 'aysa_internal_linking_remove_all_links',
                                nonce: this.getNonce()
                            });
                            console.log('✅ Unlink all response:', unlinkResponse);
                            if (unlinkResponse.success) {
                                console.log('🧹 Successfully removed ALL links from', unlinkResponse.data?.removedFrom || 0, 'content items');
                                console.log('🧹 Auto-clearing cache and refreshing data...');
                                
                                // Clear internal linking cache automatically (silent)
                                this.clearCacheSilent();
                                
                                // Reload the report data to reflect changes
                                setTimeout(() => {
                                    // Force clear both old table and new grouped sections
                                    $('#aysa-keyword-stats-table tbody').empty();
                                    $('.aysa-group-container').remove();
                                    $('#aysa-keyword-stats-table').show(); // Show original table temporarily
                                    
                                    // Update stats counters
                                    $('.aysa-total-keywords').text('0');
                                    $('.aysa-total-links').text('0');
                                    $('#aysa-total-keywords').text('0');
                                    $('#aysa-total-links').text('0');
                                    
                                    // Show empty state message
                                    $('#aysa-keyword-stats-table tbody').html(`
                                        <tr>
                                            <td colspan="6" class="aysa-no-data" style="text-align: center; padding: 40px; color: #666;">
                                                🎉 All internal links have been deleted successfully!<br>
                                                <small style="margin-top: 10px; display: block;">Process content again to create new internal links.</small>
                                            </td>
                                        </tr>
                                    `);
                                    
                                    // Optional: Reload from database to verify (but should be empty)
                                    setTimeout(() => {
                                        this.loadReport();
                                    }, 1000);
                                }, 500);
                            } else {
                                console.warn('⚠️ Unlink all failed:', unlinkResponse.data?.message || 'Unknown error');
                            }
                        } catch (e2) {
                            console.error('❌ Error removing all links from content:', e2);
                        }
                    } else {
                        throw new Error(result.message || 'Delete failed');
                    }
                } catch (e) {
                    this.showNotification('Delete all failed: ' + e.message, 'error');
                }
            });
            
            // Modal events
            $(document).on('click', '.aysa-modal-close', this.closeModal.bind(this));
            $(window).on('click', (e) => {
                if ($(e.target).hasClass('aysa-modal')) {
                    this.closeModal();
                }
            });
            
            // Enable/disable functionality
            $(document).on('change', '#aysa-internal-linking-enabled', this.toggleFunctionality.bind(this));
            $(document).on('click', '.aysa-il-subtab-btn', this.switchSubtab.bind(this));
        }

        initSubtabs() {
            const activeTab = $('.aysa-il-subtab-btn.active').data('il-tab') || 'operations-report';
            this.activateSubtab(activeTab);
        }

        switchSubtab(e) {
            e.preventDefault();
            const tab = $(e.currentTarget).data('il-tab');
            this.activateSubtab(tab);
        }

        activateSubtab(tab) {
            $('.aysa-il-subtab-btn').removeClass('active');
            $(`.aysa-il-subtab-btn[data-il-tab="${tab}"]`).addClass('active');
            $('.aysa-il-subtab-panel').removeClass('active');
            $(`.aysa-il-subtab-panel[data-il-panel="${tab}"]`).addClass('active');
        }

        setOpsInlineMessage(message, type = 'info') {
            const $box = $('#aysa-il-ops-inline-message');
            if (!$box.length) return;
            if (!message) {
                $box.hide().text('');
                return;
            }
            const palette = {
                info: { border: '#d5e3f6', bg: '#f4f8ff', fg: '#27466f' },
                warning: { border: '#f4d8a8', bg: '#fff8e9', fg: '#7a4e0a' },
                success: { border: '#cfe7d3', bg: '#effaf1', fg: '#1e5d2f' },
                error: { border: '#f1c9c9', bg: '#fff2f2', fg: '#7d1d1d' }
            };
            const tone = palette[type] || palette.info;
            $box.css({
                borderColor: tone.border,
                background: tone.bg,
                color: tone.fg
            }).text(message).show();
        }

        loadSettings() {
            this.showLoading('Loading settings...');
            
            // Load settings from WordPress via AJAX
            $.ajax({
                url: window.aysaInternalLinking?.ajaxUrl || window.aysaAjax?.ajaxUrl || ajaxurl,
                type: 'POST',
                data: {
                    action: 'aysa_internal_linking_get_settings',
                    nonce: this.getNonce()
                },
                success: (response) => {
                    console.log('📥 Settings loaded from WordPress:', response);
                    
                    let settings;
                    if (response.success && response.data) {
                        settings = response.data;
                        // Enforce current preset in UI (managed by dynamic backend rules).
                        settings.max_links_per_keyword = 1;
                        settings.max_links_per_entity = 3;
                        console.log('🔧 Enabled setting value:', settings.enabled);
                    } else {
                        // Use defaults if no saved settings
                        settings = {
                            enabled: false,
                            max_links_per_keyword: 1, // Max entities per keyword
                            max_links_per_entity: 3,
                            matching_type: 'both',
                            process_posts: true,
                            process_pages: true,
                            process_categories: true,
                            process_products: true,
                            case_sensitive: false,
                            ignore_existing_links: true,
                            priority_by_authority: true,
                            excluded_post_ids: '',
                            excluded_url_patterns: ''
                        };
                    }

                    // Apply settings to form
                    console.log('🔄 Applying settings to form elements...');
                    Object.keys(settings).forEach(key => {
                        let elementId;
                        
                        // Special case for 'enabled' field
                        if (key === 'enabled') {
                            elementId = '#aysa-internal-linking-enabled';
                        } else {
                            elementId = `#aysa-${key.replace(/_/g, '-')}`;
                        }
                        
                        const element = $(elementId);
                        const value = settings[key];
                        
                        console.log(`🔍 Looking for ${key} -> ${elementId}:`, element.length > 0 ? '✅ Found' : '❌ Missing');
                        
                        if (element.length > 0) {
                            if (element.attr('type') === 'checkbox') {
                                element.prop('checked', Boolean(value));
                                console.log(`✅ Applied setting ${key}=${value} to ${elementId}, checked=${Boolean(value)}`);
                            } else {
                                // Special handling for excluded_url_patterns array
                                if (key === 'excluded_url_patterns' && Array.isArray(value)) {
                                    element.val(value.join('\n'));
                                } else {
                                    element.val(value);
                                }
                                console.log(`✅ Applied setting ${key}=${value} to ${elementId}`);
                            }
                        } else {
                            console.warn(`⚠️ Element not found for setting ${key}: ${elementId}`);
                        }
                    });

                    this.settings = settings;
                    this.updateUI();
                    this.hideLoading();
                },
                error: (xhr, status, error) => {
                    console.error('❌ Failed to load settings:', error);
                    this.hideLoading();
                    // Load defaults on error
                    this.loadDefaultSettings();
                }
            });
        }

        loadDefaultSettings() {
            const defaultSettings = {
                enabled: false,
                max_links_per_keyword: 1, // Max entities per keyword
                max_links_per_entity: 3, // Article cap; dynamic rules still apply for page/product
                matching_type: 'both',
                process_posts: true,
                process_pages: true,
                process_categories: true,
                process_products: true,
                case_sensitive: false,
                ignore_existing_links: true,
                priority_by_authority: true,
                excluded_post_ids: ''
            };

            Object.keys(defaultSettings).forEach(key => {
                let elementId;
                
                // Special case for 'enabled' field
                if (key === 'enabled') {
                    elementId = '#aysa-internal-linking-enabled';
                } else {
                    elementId = `#aysa-${key.replace(/_/g, '-')}`;
                }
                
                const element = $(elementId);
                const value = defaultSettings[key];
                
                if (element.length > 0) {
                    if (element.attr('type') === 'checkbox') {
                        element.prop('checked', Boolean(value));
                    } else {
                        element.val(value);
                    }
                }
            });

            this.settings = defaultSettings;
            this.updateUI();
        }

        saveSettings(event) {
            console.log('💾 Save Settings called');
            console.log('🖱️ Event details:', {
                type: event?.type,
                target: event?.target?.id,
                currentTarget: event?.currentTarget?.id,
                clientX: event?.clientX,
                clientY: event?.clientY
            });
            
            // Prevent any potential issues
            if (event) {
                event.preventDefault();
                event.stopPropagation();
            }
            
            // Check if save button exists 
            const saveButton = $('#aysa-save-internal-linking-settings');
            console.log('Save button exists:', saveButton.length > 0);
            console.log('Save button offset:', saveButton.offset());
            console.log('Save button dimensions:', {
                width: saveButton.outerWidth(),
                height: saveButton.outerHeight()
            });
            
            const formData = this.collectFormData();
            console.log('Form data collected:', formData);
            
            this.showLoading('Saving settings...');

            const ajaxData = {
                action: 'aysa_internal_linking_save_settings',
                nonce: this.getNonce(),
                ...formData
            };
            
            console.log('AJAX data to send:', ajaxData);

            $.ajax({
                url: window.aysaInternalLinking?.ajaxUrl || window.aysaAjax?.ajaxUrl || ajaxurl,
                type: 'POST',
                data: ajaxData,
                success: (response) => {
                    console.log('✅ Save settings response:', response);
                    console.log('🔍 Server saved case_sensitive as:', response.data?.case_sensitive_value);
                    console.log('🔍 Full saved settings from server:', response.data?.saved_settings);
                    this.hideLoading();
                    
                    if (response.success) {
                        this.settings = formData;
                        this.updateUI();
                        this.showNotification('Settings saved successfully!', 'success');
                        
                        // Force reload settings from server to verify
                        console.log('🔄 Reloading settings from server to verify...');
                        setTimeout(() => {
                            this.loadSettings();
                        }, 500);
                    } else {
                        console.error('❌ Save settings failed:', response);
                        this.showNotification('Error saving settings: ' + (response.data?.message || 'Unknown error'), 'error');
                    }
                },
                error: (xhr, status, error) => {
                    console.error('❌ Save settings AJAX error:', { xhr, status, error });
                    this.hideLoading();
                    this.showNotification('Error saving settings: ' + error, 'error');
                }
            });
        }

        resetSettings() {
            if (confirm('Are you sure you want to reset all settings to defaults?')) {
                this.loadSettings();
                this.showNotification('Settings reset to defaults', 'info');
            }
        }

        previewLinks() {
            const content = $('#aysa-preview-content').val().trim();
            
            if (!content) {
                this.showNotification('Please enter some content to preview', 'warning');
                return;
            }

            this.showLoading('Generating preview...');

            $.ajax({
                url: window.aysaInternalLinking?.ajaxUrl || window.aysaAjax?.ajaxUrl || ajaxurl,
                type: 'POST',
                data: {
                    action: 'aysa_internal_linking_preview',
                    nonce: this.getNonce(),
                    entity_id: 0,
                    entity_type: 'preview',
                    content: content
                },
                success: (response) => {
                    this.hideLoading();
                    
                    if (response.success) {
                        this.displayPreviewResults(response.data);
                        $('#aysa-process-all-content').show();
                    } else {
                        this.showNotification('Error generating preview: ' + (response.data?.message || 'Unknown error'), 'error');
                    }
                },
                error: (xhr, status, error) => {
                    this.hideLoading();
                    this.showNotification('Error generating preview: ' + error, 'error');
                }
            });
        }

        displayPreviewResults(data) {
            $('#aysa-original-content-display').html(this.escapeHtml(data.original_content));
            $('#aysa-processed-content-display').html(data.processed_content);
            $('#aysa-links-found-count').text(`${data.links_found} internal links found`);
            $('#aysa-preview-results').show();
        }

        displayProcessResults(data) {
            // Keep one source of truth in UI: KPI cards + report table.
            // Show only a compact "Last run" summary to avoid duplicate blocks.
            const keywordsCount = Number(data.main_keywords_found || 0) + Number(data.secondary_keywords_found || 0);
            const linksAdded = Number(data.links_added || 0);
            const itemsScanned = Number(data.content_items_scanned || 0);
            const executionTime = data.execution_time ? `${data.execution_time}s` : 'N/A';
            const summaryText = this.escapeHtml(data.summary || 'Internal linking process completed.');
            const processedItems = Array.isArray(data.processed_items) ? data.processed_items : [];

            // Sync top KPI cards immediately after run so values are never contradictory.
            $('#aysa-total-keywords').text(keywordsCount);
            $('#aysa-total-links').text(linksAdded);

            const detailsHtml = processedItems.length > 0
                ? `
                    <details style="margin-top:10px;">
                        <summary style="cursor:pointer;color:#2271b1;font-weight:600;">Updated content (${processedItems.length})</summary>
                        <ul style="margin:8px 0 0 18px;max-height:180px;overflow:auto;">
                            ${processedItems.slice(0, 20).map(item => `
                                <li style="margin:4px 0;">
                                    ${this.escapeHtml(item.title || 'Untitled')}
                                    <span style="color:#5f6b7a;">(${this.escapeHtml(item.type || 'item')}, +${Number(item.links_added || 0)} links)</span>
                                </li>
                            `).join('')}
                            ${processedItems.length > 20 ? `<li style="color:#5f6b7a;">... and ${processedItems.length - 20} more</li>` : ''}
                        </ul>
                    </details>
                `
                : '';

            const html = `
                <div class="aysa-il-last-run-box" style="margin-top:10px;padding:12px 14px;border:1px solid #d5e3f6;border-radius:8px;background:#f8fbff;">
                    <div style="display:flex;flex-wrap:wrap;gap:14px;align-items:center;">
                        <strong style="color:#1d4f91;">Last run</strong>
                        <span><strong>${keywordsCount}</strong> keywords</span>
                        <span><strong>${linksAdded}</strong> links added</span>
                        <span><strong>${itemsScanned}</strong> items scanned</span>
                        <span><strong>${executionTime}</strong> runtime</span>
                    </div>
                    <div style="margin-top:8px;color:#36506f;">${summaryText}</div>
                    ${detailsHtml}
                </div>
            `;

            $('#aysa-il-last-run-summary').html(html).show();

            // Refresh report data after server-side persistence.
            setTimeout(() => {
                console.log('🔄 Refreshing reports with new process data...');
                this.loadReport();
            }, 1200);
        }
        
        /**
         * Filter link mappings to include only actual links that were created
         * This prevents saving skipped/duplicate entries to the database
         */
        filterActualLinksCreated(linkMappings, actualLinksAdded) {
            console.log(`🔍 Filtering mappings: ${linkMappings.length} total mappings, ${actualLinksAdded} actual links created`);
            
            // If no links were actually added, return empty array
            if (actualLinksAdded === 0) {
                console.log('⏭️ No actual links were created, returning empty mappings');
                return [];
            }
            
            // If the number of mappings equals actual links, all were successful
            if (linkMappings.length === actualLinksAdded) {
                console.log('✅ All mappings were successful, returning all');
                return linkMappings.map(mapping => ({
                    keyword: mapping.keyword,
                    isMain: mapping.is_main || false,
                    isSecondary: mapping.is_secondary || false,
                    sourceContentId: mapping.source_content_id,
                    sourceContentType: mapping.source_content_type,
                    sourceContentTitle: mapping.source_content_title,
                    sourceContentUrl: mapping.source_content_url,
                    targetPage: mapping.target_page,
                    targetType: mapping.target_type,
                    targetUrl: mapping.target_url,
                    hasGeneratedLink: mapping.has_generated_link || false,
                    linkPosition: mapping.link_position || null
                }));
            }
            
            // If fewer links were created than mappings, take only the first N successful ones
            // This assumes the successful ones are at the beginning of the array
            console.log(`⚠️ Only ${actualLinksAdded} of ${linkMappings.length} mappings were successful, taking first ${actualLinksAdded}`);
            return linkMappings.slice(0, actualLinksAdded).map(mapping => ({
                keyword: mapping.keyword,
                isMain: mapping.is_main || false,
                isSecondary: mapping.is_secondary || false,
                sourceContentId: mapping.source_content_id,
                sourceContentType: mapping.source_content_type,
                sourceContentTitle: mapping.source_content_title,
                sourceContentUrl: mapping.source_content_url,
                targetPage: mapping.target_page,
                targetType: mapping.target_type,
                targetUrl: mapping.target_url,
                hasGeneratedLink: mapping.has_generated_link || false,
                linkPosition: mapping.link_position || null
            }));
        }

        async saveResultsToDatabase(data) {
            try {
                // Internal linking authoritative storage is now local WordPress DB (server-side).
                // Keep client-side snapshot only for quick UI fallback/history.
                console.log('💾 Saving internal linking run snapshot locally (WordPress is source of truth)...');
                this.saveResultsToLocalStorage(data);
                return { success: true, data: { storage: 'local' } };
            } catch (error) {
                console.error('❌ Failed to save to database:', error);
                console.log('📦 Falling back to localStorage...');
                this.saveResultsToLocalStorage(data);
                return { success: true, data: { storage: 'local_fallback' } };
            }
        }

        saveResultsToLocalStorage(data) {
            try {
                // Get existing results from localStorage
                let existingResults = JSON.parse(localStorage.getItem('aysa_internal_linking_results') || '[]');
                
                // Add new result with timestamp
                const newResult = {
                    ...data,
                    id: Date.now(), // Unique ID for this run
                    timestamp: new Date().toISOString()
                };
                
                existingResults.unshift(newResult); // Add to beginning
                
                // Keep only last 10 results to avoid localStorage bloat
                if (existingResults.length > 10) {
                    existingResults = existingResults.slice(0, 10);
                }
                
                localStorage.setItem('aysa_internal_linking_results', JSON.stringify(existingResults));
                console.log('[AYSA] Internal linking results saved to localStorage');
            } catch (error) {
                console.error('[AYSA] Error saving to localStorage:', error);
            }
        }

        loadResultsFromLocalStorage() {
            try {
                return JSON.parse(localStorage.getItem('aysa_internal_linking_results') || '[]');
            } catch (error) {
                console.error('[AYSA] Error loading from localStorage:', error);
                return [];
            }
        }

        displayLinkMappingsTable(linkMappings) {
            if (!linkMappings || linkMappings.length === 0) {
                return '<p style="color: #666; text-align: center; padding: 20px;">No link mappings found.</p>';
            }

            return `
                <div class="link-mappings-table" style="margin-top: 20px;">
                    <h4 style="color: #333; margin-bottom: 15px;">🔗 Exact Link Mappings Created:</h4>
                    <div style="max-height: 400px; overflow-y: auto; border: 1px solid #ddd; border-radius: 4px;">
                        <table style="width: 100%; border-collapse: collapse; font-size: 13px;">
                            <thead style="background: #f8f9fa; position: sticky; top: 0;">
                                <tr>
                                    <th style="padding: 10px; text-align: left; border-bottom: 1px solid #ddd; font-weight: bold;">Keyword</th>
                                    <th style="padding: 10px; text-align: left; border-bottom: 1px solid #ddd; font-weight: bold;">Source</th>
                                    <th style="padding: 10px; text-align: left; border-bottom: 1px solid #ddd; font-weight: bold;">Target</th>
                                    <th style="padding: 10px; text-align: left; border-bottom: 1px solid #ddd; font-weight: bold;">Type</th>
                                </tr>
                            </thead>
                            <tbody>
                                ${linkMappings.map(mapping => `
                                    <tr style="border-bottom: 1px solid #eee;">
                                        <td style="padding: 8px; font-family: monospace; font-weight: bold; color: #2271b1;">
                                            ${mapping.keyword}
                                            ${mapping.has_generated_link ? '<span style="color: #ff8c00; font-size: 10px; margin-left: 5px;" title="Link was auto-generated">🔗</span>' : ''}
                                            ${mapping.is_main ? '<span style="color: #00a32a; font-size: 10px; margin-left: 5px;" title="Main keyword">⭐</span>' : ''}
                                            ${mapping.is_secondary ? '<span style="color: #666; font-size: 10px; margin-left: 5px;" title="Secondary keyword">⚪</span>' : ''}
                                        </td>
                                        <td style="padding: 8px;">
                                            <div style="font-weight: bold;">${mapping.source_content_title}</div>
                                            <div style="color: #666; font-size: 11px;">${mapping.source_content_type} #${mapping.source_content_id}</div>
                                        </td>
                                        <td style="padding: 8px;">
                                            <div style="font-weight: bold;">${mapping.target_page}</div>
                                            <div style="color: #666; font-size: 11px;">
                                                <a href="${mapping.target_url}" target="_blank" style="color: #0073aa; text-decoration: none;">
                                                    ${mapping.target_url}
                                                </a>
                                            </div>
                                        </td>
                                        <td style="padding: 8px;">
                                            <span style="
                                                background: ${this.getTypeColor(mapping.target_type)};
                                                color: white;
                                                padding: 2px 6px;
                                                border-radius: 10px;
                                                font-size: 10px;
                                                font-weight: bold;
                                                text-transform: uppercase;
                                            ">${mapping.target_type}</span>
                                        </td>
                                    </tr>
                                `).join('')}
                            </tbody>
                        </table>
                    </div>
                </div>
            `;
        }

        getTypeColor(type) {
            const colors = {
                'Product': '#e74c3c',
                'Page': '#3498db', 
                'Post': '#2ecc71',
                'Category': '#f39c12'
            };
            return colors[type] || '#95a5a6';
        }

        getCurrentProjectId() {
            // Prefer explicit config
            if (window.aysaInternalLinking && window.aysaInternalLinking.projectId) {
                return parseInt(window.aysaInternalLinking.projectId, 10);
            }
            // aysaParams from PHP
            if (typeof window.aysaParams !== 'undefined' && window.aysaParams.project_id) {
                return parseInt(window.aysaParams.project_id, 10);
            }
            // localStorage
            try {
                const stored = localStorage.getItem('aysa_project_id');
                if (stored && parseInt(stored, 10) > 0) return parseInt(stored, 10);
            } catch (e) {}
            // hidden input
            const hidden = document.querySelector('input[name="project_id"]');
            if (hidden && parseInt(hidden.value, 10) > 0) return parseInt(hidden.value, 10);
            // fallback: resolve by domain (sync XHR avoided; leave null and handle later)
            console.warn('⚠️ Project ID not found; returning null');
            return null;
        }

        getCurrentSettings() {
            return {
                enabled: $('#aysa-internal-linking-enabled').is(':checked'),
                maxLinksPerKeyword: parseInt($('#aysa-max-links-per-keyword').val()) || 3,
                maxLinksPerEntity: parseInt($('#aysa-max-links-per-entity').val()) || 3,
                matchingType: $('#aysa-matching-type').val() || 'both',
                processPages: $('#aysa-process-pages').is(':checked'),
                processPosts: $('#aysa-process-posts').is(':checked'),
                processCategories: $('#aysa-process-categories').is(':checked'),
                processProducts: $('#aysa-process-products').is(':checked'),
                caseInsensitive: !$('#aysa-case-sensitive').is(':checked'),
                ignoreExistingLinks: $('#aysa-ignore-existing-links').is(':checked'),
                priorityByAuthority: $('#aysa-priority-by-authority').is(':checked')
            };
        }

        convertApiResultToFrontendFormat(apiResult) {
            // Convert database result format to expected frontend format
            try {
                console.log('🔄 Converting API result:', apiResult);
                
                const converted = {
                    success: true,
                    main_keywords_found: apiResult.mainKeywordsFound || 0,
                    secondary_keywords_found: apiResult.secondaryKeywordsFound || 0,
                    total_keywords_found: apiResult.totalKeywordsFound || apiResult.mainKeywordsFound || 0,
                    content_items_scanned: apiResult.contentItemsScanned || 0,
                    links_added: apiResult.linksAdded || 0,
                    summary: apiResult.summary || 'Results loaded from database',
                    timestamp: apiResult.runDate || new Date().toISOString(),
                    run_id: apiResult.id,
                    link_mappings: [], // Will be loaded separately if needed
                    processed_items: [],
                    keywords_processed: [] // Add empty array for compatibility
                };
                
                console.log('✅ Converted result:', converted);
                return converted;
            } catch (error) {
                console.error('❌ Error converting API result:', error);
                return {
                    success: false,
                    message: 'Error loading results from database'
                };
            }
        }

        addHistoryButton() {
            // DEPRECATED: History is now integrated directly in reports
            console.log('📝 addHistoryButton called but no longer needed - history integrated in reports');
        }

        async reloadFromDatabase() {
            // DEPRECATED: Auto-refresh handled by loadReport() 
            console.log('📝 reloadFromDatabase called but using loadReport() instead');
            this.loadReport();
        }

        async showLinkingHistory() {
            // DEPRECATED: History is now shown directly in reports
            console.log('📝 showLinkingHistory called but history now integrated in reports');
            this.showNotification('📊 History is now integrated directly in the reports above!', 'info');
        }

        async loadHistoryFromDatabase(page = 1, perPage = 20) {
            try {
                const url = `${this.apiBaseUrl}/history?projectId=${this.projectId}&page=${page}&perPage=${perPage}`;
                console.log('🌐 Making API request to:', url);
                
                const response = await fetch(url, {
                    method: 'GET',
                    headers: {
                        'Content-Type': 'application/json',
                        'Accept': 'application/json'
                    }
                });
                
                console.log('📡 API Response status:', response.status);
                
                if (!response.ok) {
                    const errorText = await response.text();
                    console.error('❌ API Error Response:', errorText);
                    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
                }
                
                const result = await response.json();
                console.log('📊 API Response data:', result);
                
                if (result.success) {
                    const runs = result.data.runs || [];
                    console.log('✅ Successfully loaded', runs.length, 'runs from database');
                    
                    // Debug first result to see structure
                    if (runs.length > 0) {
                        const firstRun = runs[0];
                        console.log('🔍 First run structure:', firstRun);
                        console.log('🔍 First run keys:', Object.keys(firstRun));
                        
                        // Look for any arrays that might contain link mappings
                        Object.keys(firstRun).forEach(key => {
                            const value = firstRun[key];
                            if (Array.isArray(value) && value.length > 0) {
                                console.log(`📋 Found array ${key} with ${value.length} items. First item:`, value[0]);
                            }
                        });
                    }
                    
                    return runs;
                } else {
                    throw new Error(result.message || 'Failed to load history');
                }
            } catch (error) {
                console.error('❌ Failed to load history from database:', error);
                console.log('📦 Falling back to localStorage...');
                
                // Fallback to localStorage
                return this.loadResultsFromLocalStorage();
            }
        }

        async loadResultsFromDatabase() {
            try {
                console.log('🔄 Loading latest results from database...');
                const results = await this.loadHistoryFromDatabase(1, 1);
                
                if (results.length > 0) {
                    const latestResult = results[0];
                    console.log('📊 Latest result loaded from database:', latestResult);
                    
                    // Try to load detailed run data with link mappings
                    try {
                        const detailedResult = await this.loadRunDetails(latestResult.id);
                        if (detailedResult) {
                            console.log('📋 Detailed result with links loaded:', detailedResult);
                            const formattedResult = this.convertDetailedApiResultToFrontendFormat(detailedResult);
                            this.displayProcessResults(formattedResult);
                            console.log('✅ Detailed results displayed successfully');
                            return;
                        }
                    } catch (detailError) {
                        console.warn('⚠️ Could not load detailed result, using summary:', detailError);
                    }
                    
                    // Fallback to summary data
                    const formattedResult = this.convertApiResultToFrontendFormat(latestResult);
                    this.displayProcessResults(formattedResult);
                    console.log('✅ Summary results displayed successfully');
                } else {
                    console.log('📝 No previous results found in database');
                }
            } catch (error) {
                console.warn('⚠️ Could not load initial results from database:', error);
                
                // Fallback to localStorage
                try {
                    const localResults = this.loadResultsFromLocalStorage();
                    if (localResults.length > 0) {
                        console.log('📦 Using localStorage fallback');
                        this.displayProcessResults(localResults[0]);
                    }
                } catch (localError) {
                    console.warn('⚠️ LocalStorage fallback also failed:', localError);
                }
            }
        }

        async loadRunDetails(runId) {
            try {
                const url = `${this.apiBaseUrl}/run-details/${runId}?projectId=${this.projectId}`;
                console.log('🔍 Loading run details from:', url);
                
                const response = await fetch(url, {
                    method: 'GET',
                    headers: {
                        'Content-Type': 'application/json',
                        'Accept': 'application/json'
                    }
                });
                
                if (!response.ok) {
                    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
                }
                
                const result = await response.json();
                console.log('📊 Raw run details response:', result);
                console.log('🔍 Response keys:', Object.keys(result));
                
                if (result.success) {
                    console.log('✅ Success response, extracting data:', result.data);
                    console.log('🔍 Data keys:', Object.keys(result.data || {}));
                    
                    // Look for link mappings in the data
                    if (result.data) {
                        const allKeys = Object.keys(result.data);
                        const linkMappingKeys = allKeys.filter(key => 
                            key.toLowerCase().includes('link') || 
                            key.toLowerCase().includes('mapping')
                        );
                        console.log('🔗 Potential link mapping keys:', linkMappingKeys);
                        
                        // Check each potential key
                        linkMappingKeys.forEach(key => {
                            console.log(`🔍 ${key}:`, result.data[key]);
                        });
                    }
                    
                    return result.data;
                } else {
                    throw new Error(result.message || 'Failed to load run details');
                }
            } catch (error) {
                console.error('❌ Failed to load run details:', error);
                return null;
            }
        }

        /**
         * Load all individual link entries from the database
         * Uses new direct endpoint to get all links for project
         */
        async loadAllIndividualLinks() {
            try {
                const url = `${this.apiBaseUrl}/links?projectId=${this.projectId}`;
                console.log('🔗 Loading all individual links from direct endpoint:', url);
                
                const response = await fetch(url, {
                    method: 'GET',
                    headers: {
                        'Content-Type': 'application/json',
                        'Accept': 'application/json'
                    }
                });
                
                if (!response.ok) {
                    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
                }
                
                const result = await response.json();
                console.log('🔗 Individual links response:', result);
                
                if (result.success && result.data) {
                    console.log(`✅ Loaded ${result.data.length} individual link entries directly from InternalLinks table`);
                    
                    // Normalize field names for consistency across API responses
                    const normalizedLinks = result.data.map(link => ({
                        ...link,
                        // Normalize field names for consistency
                        createdAt: link.createdAt || link.created_at || link.runDate || link.timestamp,
                        keyword: link.keyword,
                        targetPageTitle: link.targetPageTitle || link.targetTitle,
                        targetPageUrl: link.targetPageUrl || link.targetUrl,
                        targetPageType: link.targetPageType || link.targetType,
                        sourceContentTitle: link.sourceContentTitle || link.sourceTitle,
                        sourceContentUrl: link.sourceContentUrl || link.sourceUrl,
                        sourceContentType: link.sourceContentType || link.sourceType
                    }));
                    
                    return normalizedLinks;
                } else {
                    console.warn('⚠️ No individual links found or request failed');
                    return [];
                }
            } catch (error) {
                console.error('❌ Error loading individual links from direct endpoint:', error);
                console.log('🔄 Falling back to aggregation method...');
                
                // Fallback to old aggregation method if direct endpoint fails
                return await this.loadAllIndividualLinksFallback();
            }
        }

        /**
         * Get total links count from API endpoint
         */
        async getTotalLinksFromAPI() {
            try {
                const projectId = this.getCurrentProjectId();
                if (!projectId) {
                    console.warn('⚠️ No project ID found for API call');
                    return null;
                }

                const apiUrl = `${this.apiBaseUrl}/links?projectId=${projectId}`;
                console.log('🔗 Getting total links count from API:', apiUrl);

                const response = await fetch(apiUrl, {
                    method: 'GET',
                    headers: {
                        'Content-Type': 'application/json'
                    }
                });

                if (!response.ok) {
                    console.warn('⚠️ API request failed:', response.status, response.statusText);
                    return null;
                }

                const data = await response.json();
                console.log('📊 API response for total links:', data);

                // Count the number of entries in the response
                const totalCount = Array.isArray(data) ? data.length : 0;
                console.log(`✅ Total links count from API: ${totalCount}`);
                
                return totalCount;

            } catch (error) {
                console.error('❌ Error fetching total links from API:', error);
                return null;
            }
        }

        /**
         * Fallback method: Load individual links by aggregating run details
         * Used if direct endpoint fails
         */
        async loadAllIndividualLinksFallback() {
            try {
                console.log('🔗 Loading individual links via run aggregation (fallback)...');
                
                const historyResults = await this.loadHistoryFromDatabase(1, 100);
                if (!historyResults || historyResults.length === 0) {
                    console.warn('⚠️ No history found, cannot load individual links');
                    return [];
                }
                
                const allIndividualLinks = [];
                
                for (const run of historyResults) {
                    try {
                        const runDetails = await this.loadRunDetails(run.id);
                        if (runDetails && runDetails.links) {
                            runDetails.links.forEach(link => {
                                allIndividualLinks.push({
                                    ...link,
                                    runId: run.id,
                                    runDate: run.runDate || run.timestamp,
                                    createdAt: link.createdAt || link.created_at || run.runDate || run.timestamp,
                                    keyword: link.keyword,
                                    targetPageTitle: link.targetPageTitle || link.targetTitle || link.sourceContentTitle,
                                    targetPageUrl: link.targetPageUrl || link.targetUrl || link.sourceContentUrl,
                                    targetPageType: link.targetPageType || link.targetType || link.sourceContentType,
                                    sourceContentTitle: link.sourceContentTitle || link.sourceTitle,
                                    sourceContentUrl: link.sourceContentUrl || link.sourceUrl,
                                    sourceContentType: link.sourceContentType || link.sourceType
                                });
                            });
                        }
                    } catch (error) {
                        console.warn(`⚠️ Failed to load details for run ${run.id}:`, error);
                    }
                }
                
                console.log(`✅ Fallback: Aggregated ${allIndividualLinks.length} individual links`);
                return allIndividualLinks;
                
            } catch (error) {
                console.error('❌ Error in fallback method:', error);
                return [];
            }
        }

        convertDetailedApiResultToFrontendFormat(detailedResult) {
            try {
                console.log('🔄 Converting detailed API result:', detailedResult);
                
                const run = detailedResult.run;
                const links = detailedResult.links || [];
                
                const converted = {
                    success: true,
                    main_keywords_found: run.mainKeywordsFound || 0,
                    secondary_keywords_found: run.secondaryKeywordsFound || 0,
                    total_keywords_found: run.totalKeywordsFound || run.mainKeywordsFound || 0,
                    content_items_scanned: run.contentItemsScanned || 0,
                    links_added: run.linksAdded || 0,
                    summary: run.summary || 'Results loaded from database',
                    timestamp: run.runDate || new Date().toISOString(),
                    run_id: run.id,
                    link_mappings: links.map(link => ({
                        keyword: link.keyword,
                        is_main: link.isMain,
                        is_secondary: link.isSecondary,
                        source_content_id: link.sourceContentId,
                        source_content_type: link.sourceContentType,
                        source_content_title: link.sourceContentTitle,
                        source_content_url: link.sourceContentUrl,
                        target_page: link.targetPage,
                        target_type: link.targetType,
                        target_url: link.targetUrl,
                        has_generated_link: link.hasGeneratedLink
                    })),
                    processed_items: [],
                    keywords_processed: []
                };
                
                console.log('✅ Converted detailed result:', converted);
                return converted;
            } catch (error) {
                console.error('❌ Error converting detailed API result:', error);
                return this.convertApiResultToFrontendFormat(detailedResult.run || detailedResult);
            }
        }

        displayHistoryModal(results) {
            const historyHtml = `
                <div class="aysa-linking-history" style="
                    position: fixed;
                    top: 50%;
                    left: 50%;
                    transform: translate(-50%, -50%);
                    background: white;
                    border: 1px solid #ddd;
                    border-radius: 8px;
                    padding: 20px;
                    max-width: 90vw;
                    max-height: 90vh;
                    overflow-y: auto;
                    z-index: 10000;
                    box-shadow: 0 10px 30px rgba(0,0,0,0.3);
                ">
                    <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; border-bottom: 1px solid #eee; padding-bottom: 15px;">
                        <h3 style="margin: 0; color: #2271b1;">📊 Internal Linking History</h3>
                        <button class="aysa-modal-close" style="
                            background: #dc3545;
                            color: white;
                            border: none;
                            border-radius: 4px;
                            padding: 5px 10px;
                            cursor: pointer;
                            font-size: 16px;
                        ">✕</button>
                    </div>
                    
                    <div style="margin-bottom: 15px;">
                        <button class="aysa-toggle-all button button-secondary">
                            Toggle All
                        </button>
                        <button class="aysa-clear-history button button-secondary" style="margin-left: 10px; background: #dc3545; color: white;">
                            Clear History
                        </button>
                    </div>
                    
                    ${results.map((result, index) => {
                        // Handle different date formats from API vs localStorage
                        let date;
                        if (result.runDate) {
                            date = new Date(result.runDate);
                        } else if (result.timestamp) {
                            date = new Date(result.timestamp);
                        } else {
                            date = new Date();
                        }
                        
                        // Handle different field names from API vs localStorage
                        const mainKeywords = result.mainKeywordsFound || result.main_keywords_found || 0;
                        const linksAdded = result.linksAdded || result.links_added || 0;
                        const itemsScanned = result.contentItemsScanned || result.content_items_scanned || 0;
                        const summary = result.summary || 'No summary available';
                        
                        return `
                            <div class="history-item" style="
                                border: 1px solid #ddd;
                                border-radius: 6px;
                                margin-bottom: 15px;
                                background: #f8f9fa;
                            ">
                                <div class="aysa-history-item-header" data-index="${index}" style="
                                    padding: 15px;
                                    cursor: pointer;
                                    background: ${index === 0 ? '#e3f2fd' : '#f8f9fa'};
                                    border-radius: 6px 6px 0 0;
                                ">
                                    <div style="display: flex; justify-content: space-between; align-items: center;">
                                        <div>
                                            <strong>Run #${index + 1}</strong> - ${date.toLocaleString()}
                                            ${index === 0 ? '<span style="color: #00a32a; font-size: 12px; margin-left: 10px;">[LATEST]</span>' : ''}
                                        </div>
                                        <div style="display: flex; gap: 15px;">
                                            <span style="color: #2271b1; font-weight: bold;">${mainKeywords} keywords</span>
                                            <span style="color: #00a32a; font-weight: bold;">${linksAdded} links</span>
                                            <span style="color: #ff8c00; font-weight: bold;">${itemsScanned} items</span>
                                        </div>
                                    </div>
                                </div>
                                
                                <div class="aysa-history-item-content" style="padding: 15px; background: white; border-radius: 0 0 6px 6px; ${index !== 0 ? 'display: none;' : ''}">
                                    <div style="margin-bottom: 10px; color: #666; font-style: italic;">
                                        ${summary}
                                    </div>
                                    ${result.link_mappings && result.link_mappings.length > 0 ? 
                                        this.displayLinkMappingsTable(result.link_mappings) : 
                                        '<p style="color: #666; text-align: center;">No links were created in this run.</p>'
                                    }
                                </div>
                            </div>
                        `;
                    }).join('')}
                </div>
            `;

            // Remove existing history modal
            $('.aysa-linking-history').remove();
            
            // Add overlay
            $('body').append(`
                <div class="aysa-history-overlay" style="
                    position: fixed;
                    top: 0;
                    left: 0;
                    width: 100%;
                    height: 100%;
                    background: rgba(0,0,0,0.5);
                    z-index: 9999;
                "></div>
            `);
            
            // Add history modal
            $('body').append(historyHtml);
            
            // Bind event listeners using jQuery
            this.bindHistoryModalEvents();
        }

        bindHistoryModalEvents() {
            // Close modal button
            $('.aysa-modal-close').on('click', function() {
                $('.aysa-linking-history, .aysa-history-overlay').remove();
            });
            
            // Close on overlay click
            $('.aysa-history-overlay').on('click', function() {
                $('.aysa-linking-history, .aysa-history-overlay').remove();
            });
            
            // Toggle all items
            $('.aysa-toggle-all').on('click', function() {
                $('.aysa-history-item-content').toggle();
            });
            
            // Clear history
            $('.aysa-clear-history').on('click', function() {
                if (confirm('Are you sure you want to clear all history?')) {
                    localStorage.removeItem('aysa_internal_linking_results');
                    $('.aysa-linking-history, .aysa-history-overlay').remove();
                    alert('History cleared!');
                }
            });
            
            // Toggle individual items
            $('.aysa-history-item-header').on('click', function() {
                $(this).next('.aysa-history-item-content').toggle();
            });
        }
        
        clearProtectionCache() {
            console.log('🧹 Clearing internal linking cache...');
            
            if (!confirm('Are you sure you want to clear the internal linking cache? This will reset link counters and logs.')) {
                return;
            }
            
            this.clearCacheSilent();
        }
        
        clearCacheSilent() {
            console.log('🧹 Clearing internal linking cache (silent)...');
            
            const ajaxUrl = window.aysaInternalLinking?.ajaxUrl || window.aysaAjax?.ajaxUrl || ajaxurl;
            const nonce = this.getNonce();
            const data = {
                action: 'aysa_internal_linking_clear_cache',
                nonce
            };
            
            $.post(ajaxUrl, data)
                .done((response) => {
                    console.log('✅ Clear cache response (silent):', response);
                    // No notification - silent operation
                })
                .fail((xhr, status, error) => {
                    console.error('❌ Clear cache failed (silent):', { xhr, status, error });
                    // No notification - silent operation
                });
        }

        async previewAllContent() {
            try {
                console.log('🔍 Starting content preview...');
                this.setOpsInlineMessage('');
                if (this.settings.enabled) {
                    this.setOpsInlineMessage('Internal linking enabled. Starting full processing now...', 'info');
                    this.processAllContent();
                    return;
                }
                this.showNotification('Internal linking is disabled. Running analysis preview only.', 'info');
                
                // Ensure clean modal state before showing
                this.closePreviewModal();
                // Show preview modal fresh
                $('#aysa-preview-modal').show();
                // Ensure overlay is visible even if previously hidden by other handlers
                $('#aysa-preview-modal .aysa-modal-overlay').css('display', 'flex');
                $('#aysa-preview-loading').show();
                $('#aysa-preview-content-container').hide();
                $('#aysa-approve-changes').hide();
                
                // Abort previous preview request if still running
                if (this.activePreviewRequest && this.activePreviewRequest.abort) {
                    try { this.activePreviewRequest.abort(); } catch (e) {}
                }
                // Get preview data (without actually applying changes)
                this.activePreviewRequest = $.ajax({
                    url: window.aysaInternalLinking?.ajaxUrl || window.aysaAjax?.ajaxUrl || ajaxurl,
                    type: 'POST',
                    data: {
                        action: 'aysa_internal_linking_preview',
                        nonce: this.getNonce(),
                        project_id: this.projectId || null
                    },
                    timeout: 60000 // 1 minute for preview
                });
                const response = await this.activePreviewRequest;
                
                if (response.success) {
                    this.setOpsInlineMessage('Analysis finished. Review changes in modal and approve when ready.', 'success');
                    this.displayPreviewResults(response.data);
                } else {
                    throw new Error(response.message || 'Failed to generate preview');
                }
                
            } catch (error) {
                // Suppress error UI if the request was intentionally aborted
                const aborted = (error && (error.statusText === 'abort' || error === 'abort'));
                if (!aborted) {
                    console.error('❌ Preview failed:', error);
                    const msg = (error && (error.message || error.statusText || error.responseText)) || 'Unknown error';
                    this.showNotification('Failed to generate preview: ' + msg, 'error');
                    this.setOpsInlineMessage('Analyze failed: ' + msg, 'error');
                    this.closePreviewModal();
                }
            } finally {
                this.activePreviewRequest = null;
            }
        }
        
        displayPreviewResults(data) {
            console.log('📊 Displaying preview results:', data);
            
            // Guard: if modal not visible (user closed), skip rendering
            if (!$('#aysa-preview-modal').is(':visible')) {
                return;
            }
            // Hide loading, show content
            $('#aysa-preview-loading').hide();
            $('#aysa-preview-content-container').show();
            $('#aysa-approve-changes').show();
            
            // Update summary stats
            $('#aysa-preview-total-keywords').text(data.total_keywords_found || 0);
            $('#aysa-preview-total-links').text(data.links_to_be_added || 0);
            $('#aysa-preview-content-items').text(data.content_items_scanned || 0);
            
            // Show detailed changes
            const changesList = $('#aysa-preview-changes-list');
            changesList.empty();
            
            if (data.preview_changes && data.preview_changes.length > 0) {
                data.preview_changes.forEach(change => {
                    const changeItem = $(`
                        <div class="aysa-preview-change-item">
                            <div class="aysa-preview-change-header">
                                <div class="aysa-preview-change-title">${change.content_title}</div>
                                <div class="aysa-preview-change-count">${change.links_count} links</div>
                            </div>
                            <div class="aysa-preview-content-diff">
                                <strong>Changes:</strong><br>
                                ${this.formatPreviewChanges(change.changes)}
                            </div>
                        </div>
                    `);
                    changesList.append(changeItem);
                });
            } else {
                changesList.html(`
                    <div class="aysa-preview-change-item">
                        <p style="text-align: center; color: #666; margin: 0;">
                            🔍 No changes found. No internal links will be added with current settings.
                        </p>
                    </div>
                `);
                $('#aysa-approve-changes').hide(); // Hide approve button if no changes
            }
        }
        
        formatPreviewChanges(changes) {
            if (!changes || changes.length === 0) {
                return 'No changes';
            }
            
            return changes.map(change => {
                const keyword = change.keyword || 'Unknown';
                const targetTitle = change.target_title || 'Unknown';
                return `• Keyword "<strong>${keyword}</strong>" → Link to "<span class="aysa-preview-added-link">${targetTitle}</span>"`;
            }).join('<br>');
        }
        
        closePreviewModal() {
            console.log('🔴 Closing preview modal...');
            // Abort any in-flight preview request
            if (this.activePreviewRequest && this.activePreviewRequest.abort) {
                try { this.activePreviewRequest.abort(); } catch (e) {}
                this.activePreviewRequest = null;
            }
            $('#aysa-preview-modal').hide();
            
            // Reset modal state completely
            $('#aysa-preview-loading').show();
            $('#aysa-preview-content-container').hide();
            $('#aysa-approve-changes').hide();
            $('#aysa-preview-stats').empty();
            $('#aysa-preview-changes-list').empty();
            
            console.log('✅ Preview modal closed and reset');
        }

        processAllContent() {
            if (!this.settings.enabled) {
                this.showNotification('Please enable internal linking first', 'warning');
                return;
            }

            // Close preview modal 
            this.closePreviewModal();

            this.isProcessing = true;
            this.updateUI();
            this.showLoading('Processing all content... This may take a while.');

            $.ajax({
                url: window.aysaInternalLinking?.ajaxUrl || window.aysaAjax?.ajaxUrl || ajaxurl,
                type: 'POST',
                data: {
                    action: 'aysa_internal_linking_process',
                    nonce: this.getNonce()
                },
                timeout: 300000, // 5 minutes
                success: (response) => {
                    this.isProcessing = false;
                    this.updateUI();
                    this.hideLoading();
                    
                    if (response.success) {
                        this.setOpsInlineMessage(response.data?.summary || 'Internal linking processing completed.', 'success');
                        // Save to database first, fallback to localStorage
                        this.saveResultsToDatabase(response.data).then(() => {
                            console.log('✅ Results saved to database successfully');
                        }).catch((error) => {
                            console.warn('⚠️ Database save failed, using localStorage fallback');
                        });
                        
                        this.displayProcessResults(response.data);
                        this.showNotification(response.data.summary || 'Processing completed successfully!', 'success');
                        this.loadReport(); // Refresh the report
                    } else {
                        this.setOpsInlineMessage('Processing failed: ' + (response.data?.message || 'Unknown error'), 'error');
                        this.showNotification('Error processing content: ' + (response.data?.message || 'Unknown error'), 'error');
                    }
                },
                error: (xhr, status, error) => {
                    this.isProcessing = false;
                    this.updateUI();
                    this.hideLoading();
                    
                    if (status === 'timeout') {
                        this.setOpsInlineMessage('Processing timed out. Partial results may have been applied.', 'warning');
                        this.showNotification('Processing timed out. Some content may have been processed.', 'warning');
                    } else {
                        this.setOpsInlineMessage('Processing error: ' + error, 'error');
                        this.showNotification('Error processing content: ' + error, 'error');
                    }
                }
            });
        }

        async loadReport() {
            try {
                console.log('📊 Loading report from local WordPress database...');
                const localReport = await this.loadLocalWordPressReport();
                if (localReport) {
                    this.displayReport(localReport);
                    return;
                }
                this.displayBasicReport();
            } catch (error) {
                console.warn('⚠️ Failed to load local report, using basic report:', error);
                this.displayBasicReport();
            }
        }

        async loadLocalWordPressReport() {
            try {
                const ajaxUrl = window.aysaInternalLinking?.ajaxUrl || window.aysaAjax?.ajaxUrl || ajaxurl;
                const nonce = this.getNonce();
                const response = await $.post(ajaxUrl, {
                    action: 'aysa_internal_linking_get_report',
                    nonce: nonce
                });
                if (!response || !response.success || !response.data) {
                    return null;
                }
                return response.data;
            } catch (error) {
                console.warn('⚠️ Local WordPress report request failed:', error);
                return null;
            }
        }

        async displayReportWithHistory(historyResults) {
            console.log('📊 Displaying report with historical data...');
            
            // Sort by timestamp to get most recent first
            const sortedResults = historyResults.sort((a, b) => {
                const dateA = new Date(a.runDate || a.timestamp || 0);
                const dateB = new Date(b.runDate || b.timestamp || 0);
                return dateB - dateA; // Newest first
            });
            
            // For totals display: Keywords from most recent, Links cumulative from all runs
            let totalKeywords = 0;
            let totalLinks = 0;
            const allKeywordStats = new Map();
            
            // Get keywords count from most recent run only
            if (sortedResults.length > 0) {
                const mostRecentRun = sortedResults[0];
                const mainKeywords = mostRecentRun.mainKeywordsFound || mostRecentRun.main_keywords_found || 0;
                const secondaryKeywords = mostRecentRun.secondaryKeywordsFound || mostRecentRun.secondary_keywords_found || 0;
                totalKeywords = mainKeywords + secondaryKeywords;
                console.log(`📊 Using most recent run keywords: ${totalKeywords} (${mainKeywords} main + ${secondaryKeywords} secondary)`);
            }
            
            // ✨ NEW: Calculate keyword statistics from actual database entries (not run summaries)
            console.log('🔗 Loading individual link entries for accurate keyword statistics...');
            let individualLinks = await this.loadAllIndividualLinks();
            // Filter by project only if items actually include a project id field.
            // The endpoint is already scoped by projectId, so don't over-filter when field is absent.
            if (Array.isArray(individualLinks) && this.projectId != null) {
                const containsProjectField = individualLinks.some(l => (l && (l.projectId != null || l.ProjectId != null || l.project_id != null)));
                if (containsProjectField) {
                    individualLinks = individualLinks.filter(l => {
                        const pid = l.projectId || l.ProjectId || l.project_id;
                        return String(pid) === String(this.projectId);
                    });
                }
            }
            
            if (individualLinks && individualLinks.length > 0) {
                console.log(`📊 Processing ${individualLinks.length} individual link entries from database`);
                
                // Count links per keyword from actual database entries
                individualLinks.forEach(link => {
                    const keyword = link.keyword;
                    if (!keyword) {
                        console.warn('⚠️ Link entry has no keyword:', link);
                        return;
                    }
                    
                    if (allKeywordStats.has(keyword)) {
                        const existing = allKeywordStats.get(keyword);
                        existing.totalLinks += 1;
                        
                        // Update last placement to most recent
                        const linkDate = new Date(link.createdAt || link.created_at || 0);
                        const existingDate = new Date(existing.lastPlacement || 0);
                        if (linkDate > existingDate) {
                            existing.lastPlacement = link.createdAt || link.created_at || 'Unknown';
                        }
                        
                        console.log(`📈 Updated "${keyword}": now ${existing.totalLinks} links total`);
                    } else {
                        const newStat = {
                            keyword: keyword,
                            // Source side (where link was placed)
                            sourceTitle: link.sourceContentTitle || link.sourceTitle || link.sourceTitleText || 'Source',
                            sourceUrl: link.sourceContentUrl || link.sourceUrl || link.source || '#',
                            sourceType: link.sourceContentType || link.sourceType || link.source_type || '',
                            // Target side (what was linked to)
                            targetTitle: link.targetPageTitle || link.targetTitle || link.target || link.targetPage || 'Unknown',
                            targetUrl: link.targetPageUrl || link.targetUrl || link.target_page_url || '#',
                            targetType: link.targetPageType || link.targetType || link.target_type || 'page',
                            totalLinks: 1,
                            lastPlacement: link.createdAt || link.created_at || 'Unknown'
                        };
                        allKeywordStats.set(keyword, newStat);
                        console.log(`➕ Added new keyword "${keyword}": 1 link`);
                    }
                });
                
                console.log(`✅ Keyword statistics calculated from ${individualLinks.length} actual database entries`);
            } else {
                console.log('⚠️ No individual links found in database');
            }
            
            // Get real total links count from API instead of cumulative calculation
            const realTotalLinks = await this.getTotalLinksFromAPI();
            totalLinks = realTotalLinks !== null ? realTotalLinks : totalLinks;

            // Update stats (keywords from most recent, links from API)
            $('#aysa-total-keywords').text(totalKeywords);
            $('#aysa-total-links').text(totalLinks);
            
            console.log(`📊 Final totals - Keywords: ${totalKeywords} (most recent), Links: ${totalLinks} (from API)`);
            console.log(`📋 Keyword statistics processed:`, allKeywordStats.size, 'unique keywords');
            
            // Add appropriate tooltip indicators
            if (sortedResults.length > 0) {
                const mostRecentDate = sortedResults[0].runDate || sortedResults[0].timestamp;
                if (mostRecentDate) {
                    const formattedDate = this.formatDate(mostRecentDate);
                    $('#aysa-total-keywords').attr('title', `From most recent run: ${formattedDate}`);
                    $('#aysa-total-links').attr('title', `Total from all ${sortedResults.length} runs (cumulative)`);
                }
            }
            
            const statusElement = $('#aysa-linking-status');
            if (this.settings?.enabled) {
                statusElement.text('Active').addClass('active').removeClass('inactive');
            } else {
                statusElement.text('Disabled').addClass('inactive').removeClass('active');
            }

            // Update table with keyword statistics
            const tableBody = $('#aysa-keyword-stats-table tbody');
            tableBody.empty();

            console.log('📊 Final keyword stats size:', allKeywordStats.size);
            console.log('📊 All keyword stats map:', allKeywordStats);
            
            if (allKeywordStats.size > 0) {
                const keywordArray = Array.from(allKeywordStats.values());
                console.log('📋 Keyword array for table:', keywordArray);
                // Group keywords by target type
                const groupedData = this.groupKeywordsByTargetType(keywordArray);
                
                // Render grouped table with collapse/expand
                this.renderGroupedTable(tableBody, groupedData);
                
                // Bind delete-by-keyword
                $(document).off('click', '.aysa-keyword-delete').on('click', '.aysa-keyword-delete', async (e) => {
                    const keyword = $(e.currentTarget).data('keyword');
                    if (!keyword) return;
                    if (!confirm(`Delete all links for keyword "${keyword}"?`)) return;
                    try {
                        const base = this.apiBaseUrl;
                        const url = `${base}/links/by-keyword?keyword=${encodeURIComponent(keyword)}&projectId=${this.projectId}`;
                        const res = await fetch(url, { method: 'DELETE' });
                        const json = await res.json();
                        if (json.success) {
                            const count = (json.data && json.data.deletedCount) || json.deletedCount || 0;
                            this.showNotification(`Deleted ${count} links for "${keyword}"`, 'success');
                            try {
                                console.log('🔧 Removing links from content for deleted keyword:', { keyword });
                                // Remove links by keyword from content after keyword-level API delete.
                                const unlinkResponse = await $.post(window.aysaInternalLinking?.ajaxUrl || window.aysaAjax?.ajaxUrl || ajaxurl, {
                                    action: 'aysa_internal_linking_remove_links',
                                    nonce: this.getNonce(),
                                    keyword: keyword
                                });
                                console.log('✅ Unlink response:', unlinkResponse);
                                if (unlinkResponse.success) {
                                    console.log('🧹 Successfully removed links from', unlinkResponse.data?.removedFrom || 0, 'content items');
                                    console.log('🧹 Auto-clearing cache and refreshing data...');
                                    
                                    // Clear internal linking cache automatically (silent)
                                    this.clearCacheSilent();
                                    
                                    // Reload the report data to reflect changes
                                    setTimeout(() => {
                                        this.loadReport();
                                    }, 500);
                                } else {
                                    console.warn('⚠️ Unlink failed:', unlinkResponse.data?.message || 'Unknown error');
                                }
                            } catch (e2) {
                                console.error('❌ Error removing links from content:', e2);
                            }
                            this.loadReport();
                        } else {
                            throw new Error(json.message || 'Delete failed');
                        }
                    } catch (err) {
                        this.showNotification('Delete failed: ' + err.message, 'error');
                    }
                });
            } else {
                if (totalLinks > 0) {
                    tableBody.append('<tr><td colspan="6" style="text-align:center; color:#666; padding:20px;">✅ Links found in history, but detailed keyword mapping is being loaded...</td></tr>');
                } else {
                    tableBody.append('<tr><td colspan="6" style="text-align:center; color:#666; padding:20px;">No internal links have been created yet. Process content to see keyword statistics here.</td></tr>');
                }
            }
        }

        /**
         * Load source information for all keywords and display in Source column
         */
        async loadSourcesForAllKeywords() {
            console.log('🔍 Loading source information for all keywords...');
            
            // Get all keyword elements
            const keywordElements = $('.aysa-source-links[data-keyword]');
            
            // Process each keyword element
            for (let i = 0; i < keywordElements.length; i++) {
                const element = keywordElements[i];
                const $element = $(element);
                const keyword = $element.data('keyword');
                
                if (!keyword) continue;
                
                try {
                    // Load source information for this keyword
                    const sourceData = await this.loadSourcesForKeyword(keyword);
                    this.displaySourcesInColumn($element, sourceData);
                } catch (error) {
                    console.error(`❌ Failed to load sources for keyword "${keyword}":`, error);
                    $element.html('<span style="color: #dc3545;">Error loading sources</span>');
                }
            }
        }

        /**
         * Load source information for a specific keyword
         */
        async loadSourcesForKeyword(keyword) {
            try {
                const url = `${this.apiBaseUrl}/search-links?keyword=${encodeURIComponent(keyword)}&projectId=${this.projectId}`;
                console.log(`🔗 Loading sources for keyword "${keyword}" from:`, url);
                
                const response = await fetch(url, {
                    method: 'GET',
                    headers: {
                        'Content-Type': 'application/json',
                        'Accept': 'application/json'
                    }
                });

                if (!response.ok) {
                    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
                }

                const result = await response.json();
                
                if (result.success && result.data) {
                    return result.data;
                } else {
                    throw new Error(result.message || 'Failed to load sources');
                }
            } catch (error) {
                console.error(`❌ Error loading sources for keyword "${keyword}":`, error);
                throw error;
            }
        }

        /**
         * Display sources in the Source column with delete buttons for each
         */
        displaySourcesInColumn($element, sourceData) {
            const keyword = $element.data('keyword');
            
            if (!sourceData || !Array.isArray(sourceData) || sourceData.length === 0) {
                $element.html('<span style="color: #666; font-style: italic;">No sources found</span>');
                return;
            }

            // Group sources by unique source content (using correct API response fields)
            const sourceGroups = new Map();
            
            sourceData.forEach(link => {
                console.log('🔍 Processing link data:', link); // Debug log
                
                // Use correct field names from API response
                const sourceKey = `${link.sourceContentTitle || 'Unknown'}_${link.sourceContentId || 'unknown'}`;
                
                if (!sourceGroups.has(sourceKey)) {
                    sourceGroups.set(sourceKey, {
                        title: link.sourceContentTitle || 'Unknown Source',
                        type: link.sourceContentType || 'unknown',
                        id: link.sourceContentId || 'unknown',
                        url: link.sourceContentUrl || '#',
                        links: []
                    });
                }
                
                sourceGroups.get(sourceKey).links.push(link);
            });

            console.log('📋 Source groups created:', sourceGroups); // Debug log

            // Create HTML for sources
            const sourcesHtml = Array.from(sourceGroups.values()).map(source => {
                const sourceLinksHtml = source.links.map(link => `
                    <div style="display: flex; align-items: center; gap: 8px; margin-bottom: 4px;">
                        <a href="${this.resolveSourceHref(link.sourceContentUrl, source.title)}" target="_blank" rel="noopener noreferrer"
                           style="color: #0073aa; text-decoration: none; font-size: 12px; flex-grow: 1;">
                            ${this.escapeHtml(source.title)}
                        </a>
                        <button class="button button-small aysa-delete-source-link" 
                                data-link-id="${link.id || ''}" 
                                data-keyword="${this.escapeHtml(keyword)}"
                                style="padding: 2px 6px; font-size: 10px; line-height: 1; background: #dc3545; color: white; border: none; border-radius: 3px;"
                                title="Delete this specific link">
                            🗑️
                        </button>
                    </div>
                `).join('');

                return `
                    <div style="border: 1px solid #ddd; border-radius: 4px; padding: 8px; margin-bottom: 6px; background: #f9f9f9;">
                        <div style="font-weight: bold; font-size: 11px; color: #666; margin-bottom: 4px;">
                            ${this.escapeHtml(source.type.toUpperCase())} #${source.id}
                        </div>
                        ${sourceLinksHtml}
                    </div>
                `;
            }).join('');

            $element.html(sourcesHtml);

            // Bind delete events for individual source links
            $element.find('.aysa-delete-source-link').on('click', async (e) => {
                e.preventDefault();
                e.stopPropagation();
                
                const linkId = $(e.currentTarget).data('link-id');
                const keyword = $(e.currentTarget).data('keyword');
                
                if (!linkId || !keyword) return;
                
                if (!confirm(`Delete this specific link for keyword "${keyword}"?`)) return;
                
                try {
                    const sourceUrl = $(e.currentTarget).closest('div').find('a').attr('href') || '';
                    await this.deleteSourceLink(linkId, keyword, sourceUrl);
                    
                    // Reload sources for this keyword
                    const sourceData = await this.loadSourcesForKeyword(keyword);
                    this.displaySourcesInColumn($element, sourceData);
                    
                    // Update the stats after deletion
                    this.updateStatsAfterDeletion();
                    
                    this.showNotification('Link deleted successfully', 'success');
                } catch (error) {
                    console.error('❌ Failed to delete source link:', error);
                    this.showNotification('Failed to delete link: ' + error.message, 'error');
                }
            });
        }

        /**
         * Delete a specific source link
         */
        async deleteSourceLink(linkId, keyword, sourceUrl = '') {
            try {
                const url = `${this.apiBaseUrl}/link/${encodeURIComponent(linkId)}?projectId=${this.projectId}`;
                console.log(`🗑️ Deleting link ${linkId} from:`, url);
                
                const response = await fetch(url, {
                    method: 'DELETE',
                    headers: {
                        'Content-Type': 'application/json',
                        'Accept': 'application/json'
                    }
                });

                if (!response.ok) {
                    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
                }

                const result = await response.json();
                
                if (!result.success) {
                    throw new Error(result.message || 'Delete failed');
                }

                // Remove the link from content as well
                try {
                    const unlinkResponse = await $.post(window.aysaInternalLinking?.ajaxUrl || window.aysaAjax?.ajaxUrl || ajaxurl, {
                        action: 'aysa_internal_linking_remove_links',
                        nonce: this.getNonce(),
                        keyword: keyword,
                        source_url: sourceUrl
                    });
                    
                    if (unlinkResponse.success) {
                        console.log('🧹 Successfully removed link from content');
                    } else {
                        console.warn('⚠️ Unlink failed:', unlinkResponse.data?.message || 'Unknown error');
                    }
                } catch (e2) {
                    console.error('❌ Error removing link from content:', e2);
                }
                
                return result;
            } catch (error) {
                console.error(`❌ Error deleting link ${linkId}:`, error);
                throw error;
            }
        }

        async showKeywordDetailsAsync(keyword) {
            console.log('📊 Showing details for keyword:', keyword);
            
            try {
                // ✨ NEW: Use search-links endpoint to get only relevant links for this keyword
                const url = `${this.apiBaseUrl}/search-links?keyword=${encodeURIComponent(keyword)}&projectId=${this.projectId}`;
                console.log('🔗 Searching keyword links via:', url);
                
                const response = await fetch(url, {
                    method: 'GET',
                    headers: {
                        'Content-Type': 'application/json',
                        'Accept': 'application/json'
                    }
                });
                
                if (!response.ok) {
                    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
                }
                
                const result = await response.json();
                console.log('🔗 Search links response:', result);
                
                if (!result.success) {
                    throw new Error(result.message || 'Failed to search links');
                }
                
                const keywordLinks = result.data || [];
                console.log(`📊 Found ${keywordLinks.length} links for keyword "${keyword}"`);
                
                if (keywordLinks.length === 0) {
                    this.showNotification(`No links found for keyword "${keyword}"`, 'warning');
                    return;
                }
                
                // Process the search results into display format
                const keywordDetails = {
                    keyword: keyword,
                    totalLinks: keywordLinks.length,
                    placements: [],
                    targetPages: new Set(),
                    firstSeen: null,
                    lastSeen: null
                };
                
                keywordLinks.forEach(link => {
                    console.log('🔍 Processing search result:', link);
                    
                    const resolvedDate = link.createdAt || link.created_at || link.runDate || link.timestamp || null;
                    const placement = {
                        id: link.id, // CRITICAL: Include the ID for delete operations
                        runDate: resolvedDate || 'Unknown',
                        createdAt: resolvedDate || 'Unknown',
                        runId: link.runId || 'Unknown',
                        sourceTitle: link.sourceContentTitle || link.sourceTitle || link.source || 'Unknown',
                        sourceUrl: link.sourceContentUrl || link.sourceUrl || link.source_page_url || '#',
                        targetTitle: link.targetPageTitle || link.targetTitle || link.targetPage || link.target || 'Unknown',
                        targetUrl: link.targetPageUrl || link.targetUrl || link.target_page_url || '#',
                        targetType: link.targetPageType || link.targetType || link.target_type || ((link.targetUrl || link.targetPageUrl || '').includes('/product/') ? 'product' : 'page')
                    };
                    
                    keywordDetails.placements.push(placement);
                    keywordDetails.targetPages.add(placement.targetTitle);
                    
                    // Update date range
                    const currentDate = new Date(placement.runDate);
                    if (!keywordDetails.firstSeen || currentDate < new Date(keywordDetails.firstSeen)) {
                        keywordDetails.firstSeen = placement.runDate;
                    }
                    if (!keywordDetails.lastSeen || currentDate > new Date(keywordDetails.lastSeen)) {
                        keywordDetails.lastSeen = placement.runDate;
                    }
                });
                
                console.log('✅ Keyword search details processed:', keywordDetails);
                // Modal functionality has been replaced with inline Source column
                
            } catch (error) {
                console.error('❌ Error loading keyword search details:', error);
                console.log('🔄 Falling back to aggregation method...');
                
                // Fallback to old aggregation method if search endpoint fails
                this.showKeywordDetailsAsyncFallback(keyword);
            }
        }

        /**
         * Fallback method for keyword details using run aggregation
         */
        async showKeywordDetailsAsyncFallback(keyword) {
            try {
                console.log('📊 Loading keyword details via fallback method:', keyword);
                
                // Find all link mappings for this keyword from all runs
                const historyResults = await this.loadHistoryFromDatabase(1, 50); // Load more runs for complete history
                const keywordDetails = {
                    keyword: keyword,
                    totalLinks: 0,
                    placements: [],
                    targetPages: new Set(),
                    firstSeen: null,
                    lastSeen: null
                };
                
                // Process each run to find this keyword
                for (const result of historyResults) {
                    let workingResult = result;
                    
                    // Load detailed data if needed
                    if ((!result.linkMappings || result.linkMappings.length === 0) && 
                        (!result.link_mappings || result.link_mappings.length === 0)) {
                        try {
                            const detailedResult = await this.loadRunDetails(result.id);
                            if (detailedResult) {
                                workingResult = {
                                    ...result,
                                    ...detailedResult,
                                    linkMappings: detailedResult.links || detailedResult.linkMappings || detailedResult.link_mappings || [],
                                    links: detailedResult.links || detailedResult.linkMappings || detailedResult.link_mappings || []
                                };
                            }
                        } catch (error) {
                            console.warn('⚠️ Could not load detailed data for run:', result.id);
                        }
                    }
                    
                    // Find this keyword in the mappings
                    const linkMappings = workingResult.linkMappings || workingResult.links || workingResult.link_mappings || [];
                    const keywordMappings = linkMappings.filter(mapping => mapping.keyword === keyword);
                    
                    if (keywordMappings.length > 0) {
                        keywordDetails.totalLinks += keywordMappings.length;
                        const runDate = workingResult.runDate || workingResult.timestamp || 'Unknown';
                        
                        keywordMappings.forEach(mapping => {
                            keywordDetails.placements.push({
                                runDate: runDate,
                                runId: result.id,
                                sourceTitle: mapping.sourceContentTitle || mapping.sourceTitle || mapping.source_title || `Content #${mapping.sourceContentId || 'Unknown'}`,
                                sourceUrl: mapping.sourceContentUrl || mapping.sourceUrl || mapping.source_url || '#',
                                targetTitle: mapping.targetTitle || mapping.target_title || mapping.targetPageTitle || `Target #${mapping.targetContentId || 'Unknown'}`,
                                targetUrl: mapping.targetUrl || mapping.target_url || mapping.targetPageUrl || '#',
                                targetType: mapping.targetType || mapping.target_type || mapping.targetPageType || 'page'
                            });
                            
                            keywordDetails.targetPages.add(mapping.targetTitle || mapping.target_title || 'Unknown');
                        });
                        
                        if (!keywordDetails.firstSeen || runDate < keywordDetails.firstSeen) {
                            keywordDetails.firstSeen = runDate;
                        }
                        if (!keywordDetails.lastSeen || runDate > keywordDetails.lastSeen) {
                            keywordDetails.lastSeen = runDate;
                        }
                    }
                }
                
                // Modal functionality has been replaced with inline Source column
                
            } catch (error) {
                console.error('❌ Failed to load keyword details (fallback):', error);
                this.showNotification('Failed to load keyword details: ' + error.message, 'error');
            }
        }

        displayKeywordDetailsModal(details) {
            // Modal functionality has been removed and replaced with inline Source column
            console.log('📊 Modal display bypassed - using inline Source column instead');
            return;
            const modalHtml = `
                <div class="aysa-keyword-details-modal" style="
                    position: fixed;
                    top: 0;
                    left: 0;
                    width: 100%;
                    height: 100%;
                    background: rgba(0,0,0,0.75);
                    z-index: 10000;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    animation: fadeIn 0.3s ease-out;
                ">
                    <div style="
                        background: white;
                        border-radius: 16px;
                        padding: 0;
                        width: 95%;
                        max-width: 900px;
                        max-height: 85vh;
                        overflow: hidden;
                        box-shadow: 0 25px 70px rgba(0,0,0,0.4);
                        transform: scale(1);
                        animation: slideIn 0.3s ease-out;
                    ">
                        <div style="
                            background: linear-gradient(135deg, #2271b1 0%, #135e96 100%);
                            color: white;
                            padding: 24px 30px;
                            display: flex;
                            justify-content: space-between;
                            align-items: center;
                            border-radius: 16px 16px 0 0;
                        ">
                            <div>
                                <h3 style="margin: 0 0 4px 0; font-size: 20px; font-weight: 600;">
                                    📊 Keyword Details
                                </h3>
                                <div style="font-size: 16px; opacity: 0.9; font-weight: 500;">
                                    "${this.escapeHtml(details.keyword)}"
                                </div>
                            </div>
                            <button class="aysa-modal-close" style="
                                background: rgba(255,255,255,0.2);
                                border: none;
                                color: white;
                                font-size: 18px;
                                cursor: pointer;
                                padding: 8px 10px;
                                border-radius: 50%;
                                width: 36px;
                                height: 36px;
                                display: flex;
                                align-items: center;
                                justify-content: center;
                                transition: all 0.2s ease;
                            " onmouseover="this.style.background='rgba(255,255,255,0.3)'" onmouseout="this.style.background='rgba(255,255,255,0.2)'">✕</button>
                        </div>
                        
                        <div style="padding: 30px; max-height: 70vh; overflow-y: auto;">
                            <!-- Statistics Grid -->
                            <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 16px; margin-bottom: 30px;">
                                <div style="
                                    background: linear-gradient(135deg, #2271b1 0%, #135e96 100%);
                                    color: white;
                                    padding: 20px;
                                    border-radius: 12px;
                                    text-align: center;
                                    box-shadow: 0 4px 15px rgba(34, 113, 177, 0.3);
                                ">
                                    <div style="font-size: 28px; font-weight: bold; margin-bottom: 4px;">${details.totalLinks}</div>
                                    <div style="font-size: 13px; opacity: 0.9; font-weight: 500;">Total Links Created</div>
                                </div>
                                <div style="
                                    background: linear-gradient(135deg, #00a32a 0%, #00811f 100%);
                                    color: white;
                                    padding: 20px;
                                    border-radius: 12px;
                                    text-align: center;
                                    box-shadow: 0 4px 15px rgba(0, 163, 42, 0.3);
                                ">
                                    <div style="font-size: 28px; font-weight: bold; margin-bottom: 4px;">${details.targetPages.size}</div>
                                    <div style="font-size: 13px; opacity: 0.9; font-weight: 500;">Unique Target Pages</div>
                                </div>
                                <div style="
                                    background: linear-gradient(135deg, #8e44ad 0%, #732d91 100%);
                                    color: white;
                                    padding: 20px;
                                    border-radius: 12px;
                                    text-align: center;
                                    box-shadow: 0 4px 15px rgba(142, 68, 173, 0.3);
                                ">
                                    <div style="font-size: 15px; font-weight: bold; margin-bottom: 4px;">
                                        ${details.firstSeen ? this.formatDate(details.firstSeen) : 'N/A'}
                                    </div>
                                    <div style="font-size: 13px; opacity: 0.9; font-weight: 500;">First Placement</div>
                                </div>
                                <div style="
                                    background: linear-gradient(135deg, #e67e22 0%, #d35400 100%);
                                    color: white;
                                    padding: 20px;
                                    border-radius: 12px;
                                    text-align: center;
                                    box-shadow: 0 4px 15px rgba(230, 126, 34, 0.3);
                                ">
                                    <div style="font-size: 15px; font-weight: bold; margin-bottom: 4px;">
                                        ${details.lastSeen ? this.formatDate(details.lastSeen) : 'N/A'}
                                    </div>
                                    <div style="font-size: 13px; opacity: 0.9; font-weight: 500;">Latest Placement</div>
                                </div>
                            </div>
                            
                            <!-- Section Header -->
                            <div style="
                                display: flex;
                                align-items: center;
                                margin-bottom: 20px;
                                padding-bottom: 15px;
                                border-bottom: 2px solid #f1f3f4;
                            ">
                                <h4 style="color: #2271b1; margin: 0; font-size: 18px; font-weight: 600;">
                                    📋 All Link Placements
                                </h4>
                                <span style="
                                    background: #2271b1;
                                    color: white;
                                    padding: 4px 12px;
                                    border-radius: 20px;
                                    font-size: 12px;
                                    margin-left: 12px;
                                    font-weight: 500;
                                ">
                                    ${details.placements.length} total
                                </span>
                                <div style="margin-left:auto; display:flex; gap:8px;">
                                    <button id="aysa-delete-by-keyword" class="button button-secondary" data-keyword="${this.escapeHtml(details.keyword)}">🗑️ Delete keyword</button>
                                    <button id="aysa-delete-by-keyword-target" class="button button-secondary" data-keyword="${this.escapeHtml(details.keyword)}" data-target="${this.escapeHtml(Array.from(details.targetPages)[0] || '')}">🗑️ Delete keyword + target</button>
                                </div>
                            </div>
                            
                            <!-- Placements List -->
                            <div style="max-height: 450px; overflow-y: auto; margin-right: -15px; padding-right: 15px;">
                                ${details.placements.length > 0 ? details.placements.map((placement, index) => {
                                    const isProduct = ((placement && placement.targetType) ? String(placement.targetType).toLowerCase() : '') === 'product';
                                    const typeColor = isProduct ? '#e74c3c' : '#2271b1';
                                    const typeIcon = isProduct ? '🛍️' : '📄';
                                    
                                    return `
                                        <div style="
                                            background: white;
                                            padding: 20px;
                                            margin-bottom: 12px;
                                            border-radius: 12px;
                                            border: 1px solid #e1e5e9;
                                            box-shadow: 0 2px 8px rgba(0,0,0,0.04);
                                            transition: all 0.2s ease;
                                            position: relative;
                                            overflow: hidden;
                                        " onmouseover="this.style.boxShadow='0 4px 15px rgba(0,0,0,0.1)'" onmouseout="this.style.boxShadow='0 2px 8px rgba(0,0,0,0.04)'"><!-- Type Indicator -->
                                            <div style="
                                                position: absolute;
                                                top: 0;
                                                left: 0;
                                                width: 4px;
                                                height: 100%;
                                                background: ${typeColor};
                                            "></div>
                                            <!-- Content -->
                                            <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px;">
                                                <div>
                                                    <div style="font-size: 12px; color: #888;">Source</div>
                                                    <div style="font-size: 16px; font-weight: 600; margin-bottom: 6px;">
                                                        <a href="${placement.sourceUrl || '#'}" target="_blank" style="color: #2c3e50; text-decoration: none;">${this.escapeHtml(placement.sourceTitle || 'Unknown source')}</a>
                                                    </div>
                                                    <div style="font-size: 12px; color: #888;">
                                                        ${placement.sourceType ? placement.sourceType.toUpperCase() : 'PAGE'} • Position ${index + 1}
                                                    </div>
                                                </div>
                                                <div>
                                                    <div style="font-size: 12px; color: #888;">Target</div>
                                                    <div style="font-size: 16px; font-weight: 600; margin-bottom: 6px;">
                                                        <a href="${placement.targetUrl || '#'}" target="_blank" style="color: #2c3e50; text-decoration: none;">${this.escapeHtml(placement.targetTitle || 'Unknown target')}</a>
                                                    </div>
                                                    <div style="font-size: 12px; color: #888;">
                                                        ${placement.targetType ? `${String(placement.targetType).toUpperCase()} • ${placement.targetId ? ('ID ' + placement.targetId) : ''}` : ''}
                                                    </div>
                                                    <div style="margin-top:8px;">
                                                        <button class="button button-small aysa-delete-placement" 
                                                            data-link-id="${placement.id || ''}" 
                                                            data-keyword="${this.escapeHtml(details.keyword)}" 
                                                            data-target="${this.escapeHtml(placement.targetTitle || '')}"
                                                            data-source-title="${this.escapeHtml(placement.sourceTitle || '')}"
                                                            data-source-url="${this.escapeHtml(placement.sourceUrl || '')}"
                                                            data-position="${index + 1}">Delete Link ${index + 1}</button>
                                                    </div>
                                                </div>
                                            </div>
                                            <div style="margin-top: 10px; font-size: 12px; color: #999;">
                                                Placed on ${this.formatDate(placement.createdAt || placement.timestamp)}
                                            </div>
                                        </div>
                                    `;
                                }).join('') : `
                                    <div style="text-align:center; color:#666; padding:20px;">No placements found for this keyword.</div>
                                `}
                            </div>
                        </div>
                    </div>
                </div>
            `;
            
            // Add CSS animations
            const animationCSS = `
                <style>
                    @keyframes fadeIn {
                        from { opacity: 0; }
                        to { opacity: 1; }
                    }
                    @keyframes slideIn {
                        from { 
                            transform: scale(0.9) translateY(-20px);
                            opacity: 0;
                        }
                        to { 
                            transform: scale(1) translateY(0);
                            opacity: 1;
                        }
                    }
                    .aysa-keyword-details-modal * {
                        box-sizing: border-box;
                    }
                    .aysa-keyword-details-modal::-webkit-scrollbar {
                        width: 8px;
                    }
                    .aysa-keyword-details-modal::-webkit-scrollbar-track {
                        background: #f1f1f1;
                        border-radius: 4px;
                    }
                    .aysa-keyword-details-modal::-webkit-scrollbar-thumb {
                        background: #c1c1c1;
                        border-radius: 4px;
                    }
                    .aysa-keyword-details-modal::-webkit-scrollbar-thumb:hover {
                        background: #a8a8a8;
                    }
                </style>
            `;
            
            // Remove any existing modal and styles
            $('.aysa-keyword-details-modal, #aysa-modal-styles').remove();
            
            // Add styles to head
            $('head').append(`<style id="aysa-modal-styles">${animationCSS}</style>`);
            
            // Add modal to page
            $('body').append(modalHtml);
            // Bind delete actions inside modal
            const apiBaseUrl = this.apiBaseUrl;
            const projectId = this.projectId;
            const reload = () => this.loadReport();
            $('#aysa-delete-by-keyword').on('click', async (e) => {
                const keyword = $(e.currentTarget).data('keyword');
                if (!keyword) return;
                if (!confirm(`Delete all links for keyword "${keyword}"?`)) return;
                try {
                    const base = apiBaseUrl;
                    const res = await fetch(`${base}/links/by-keyword?keyword=${encodeURIComponent(keyword)}&projectId=${projectId}`, { method: 'DELETE' });
                    const json = await res.json();
                    if (json.success) {
                        const count = (json.data && json.data.deletedCount) || json.deletedCount || 0;
                        this.showNotification(`Deleted ${count} links for "${keyword}"`, 'success');
                        try {
                            console.log('🔧 Removing links from content for keyword:', keyword);
                            const unlinkResponse = await $.post(window.aysaInternalLinking?.ajaxUrl || window.aysaAjax?.ajaxUrl || ajaxurl, {
                                action: 'aysa_internal_linking_remove_links',
                                nonce: this.getNonce(),
                                keyword: keyword
                            });
                            console.log('✅ Unlink response:', unlinkResponse);
                            if (unlinkResponse.success) {
                                console.log('🧹 Successfully removed links from', unlinkResponse.data?.removedFrom || 0, 'content items');
                                console.log('🧹 Auto-clearing cache and refreshing data...');
                                
                                // Clear internal linking cache automatically (silent)
                                this.clearCacheSilent();
                                
                                // Reload the report data to reflect changes
                                setTimeout(() => {
                                    this.loadReport();
                                }, 500);
                            } else {
                                console.warn('⚠️ Unlink failed:', unlinkResponse.data?.message || 'Unknown error');
                            }
                        } catch (e2) {
                            console.error('❌ Error removing links from content:', e2);
                        }
                        $('.aysa-keyword-details-modal').remove();
                        reload();
                    } else { throw new Error(json.message || 'Delete failed'); }
                } catch (err) { this.showNotification('Delete failed: ' + err.message, 'error'); }
            });
            $('#aysa-delete-by-keyword-target').on('click', async (e) => {
                const keyword = $(e.currentTarget).data('keyword');
                const target = $(e.currentTarget).data('target');
                if (!keyword || !target) return;
                if (!confirm(`Delete all links for "${keyword}" targeting "${target}"?`)) return;
                try {
                    const base = apiBaseUrl;
                    const res = await fetch(`${base}/links/by-keyword-and-target-page?keyword=${encodeURIComponent(keyword)}&targetPage=${encodeURIComponent(target)}&projectId=${projectId}`, { method: 'DELETE' });
                    const json = await res.json();
                    if (json.success) {
                        const count = (json.data && json.data.deletedCount) || json.deletedCount || 0;
                        this.showNotification(`Deleted ${count} links for "${keyword}" -> "${target}"`, 'success');
                        try {
                            console.log('🔧 Removing links from content for keyword:', keyword, 'target:', target);
                            const unlinkResponse = await $.post(window.aysaInternalLinking?.ajaxUrl || window.aysaAjax?.ajaxUrl || ajaxurl, {
                                action: 'aysa_internal_linking_remove_links',
                                nonce: this.getNonce(),
                                keyword: keyword,
                                target_url: target
                            });
                            console.log('✅ Unlink response:', unlinkResponse);
                            if (unlinkResponse.success) {
                                console.log('🧹 Successfully removed links from', unlinkResponse.data?.removedFrom || 0, 'content items');
                                console.log('🧹 Auto-clearing cache and refreshing data...');
                                
                                // Clear internal linking cache automatically (silent)
                                this.clearCacheSilent();
                                
                                // Reload the report data to reflect changes
                                setTimeout(() => {
                                    this.loadReport();
                                }, 500);
                            } else {
                                console.warn('⚠️ Unlink failed:', unlinkResponse.data?.message || 'Unknown error');
                            }
                        } catch (e2) {
                            console.error('❌ Error removing links from content:', e2);
                        }
                        $('.aysa-keyword-details-modal').remove();
                        reload();
                    } else { throw new Error(json.message || 'Delete failed'); }
                } catch (err) { this.showNotification('Delete failed: ' + err.message, 'error'); }
            });
            
            // Bind close events
            $('.aysa-modal-close').on('click', function() {
                $('.aysa-keyword-details-modal').fadeOut(200, function() {
                    $(this).remove();
                    $('#aysa-modal-styles').remove();
                });
            });
            
            $('.aysa-keyword-details-modal').on('click', function(e) {
                if (e.target === this) {
                    $(this).fadeOut(200, function() {
                        $(this).remove();
                        $('#aysa-modal-styles').remove();
                    });
                }
            });
            
            // Prevent modal content clicks from closing modal
            $('.aysa-keyword-details-modal > div').on('click', function(e) {
                e.stopPropagation();
            });

            // Delete individual placement buttons
            $('.aysa-delete-placement').on('click', async (e) => {
                const linkId = $(e.currentTarget).data('link-id');
                const keyword = $(e.currentTarget).data('keyword');
                const target = $(e.currentTarget).data('target');
                const sourceTitle = $(e.currentTarget).data('source-title');
                const sourceUrl = $(e.currentTarget).data('source-url');
                const position = $(e.currentTarget).data('position') || 1;
                if (!linkId) { this.showNotification('Missing link id for this placement', 'warning'); return; }
                if (!confirm(`Delete link ${position} for "${keyword}" from "${sourceTitle}"?`)) return;
                try {
                    const base = this.apiBaseUrl;
                    const res = await fetch(`${base}/link/${encodeURIComponent(linkId)}?projectId=${this.projectId}`, { method: 'DELETE' });
                    const json = await res.json();
                    if (json.success) {
                        this.showNotification('Link deleted', 'success');
                        try {
                            console.log('🔧 Removing specific link from content:', {keyword, sourceTitle, sourceUrl, target, position});
                            const unlinkResponse = await $.post(window.aysaInternalLinking?.ajaxUrl || window.aysaAjax?.ajaxUrl || ajaxurl, {
                                action: 'aysa_internal_linking_remove_links',
                                nonce: this.getNonce(),
                                keyword: keyword,
                                target_url: target,
                                source_url: sourceUrl,  // Only unlink from this specific page
                                link_position: position  // Remove the Nth occurrence in the page
                            });
                            console.log('✅ Unlink response:', unlinkResponse);
                            if (unlinkResponse.success) {
                                console.log('🧹 Successfully removed links from', unlinkResponse.data?.removedFrom || 0, 'content items');
                                console.log('🧹 Auto-clearing cache and refreshing data...');
                                
                                // Clear internal linking cache automatically (silent)
                                this.clearCacheSilent();
                                
                                // Close modal and reload the report data to reflect changes
                                $('.aysa-keyword-details-modal').remove();
                                setTimeout(() => {
                                    this.loadReport();
                                }, 500);
                            } else {
                                console.warn('⚠️ Unlink failed:', unlinkResponse.data?.message || 'Unknown error');
                            }
                        } catch (e2) {
                            console.error('❌ Error removing links from content:', e2);
                        }
                        $('.aysa-keyword-details-modal').remove();
                        this.loadReport();
                    } else {
                        throw new Error(json.message || 'Delete failed');
                    }
                } catch (err) {
                    this.showNotification('Delete failed: ' + err.message, 'error');
                }
            });
        }

        displayBasicReport() {
            // Basic report when no data available
            $('#aysa-total-keywords').text('0');
            $('#aysa-total-links').text('0');
            
            const statusElement = $('#aysa-linking-status');
            if (this.settings?.enabled) {
                statusElement.text('Active').addClass('active').removeClass('inactive');
            } else {
                statusElement.text('Disabled').addClass('inactive').removeClass('active');
            }

            const tableBody = $('#aysa-keyword-stats-table tbody');
            tableBody.empty();
            $('.aysa-group-container').remove();
            $('#aysa-keyword-stats-table').show();
            tableBody.append('<tr><td colspan="6" style="text-align:center; color:#666; padding:20px;">No internal links have been created yet. Enable internal linking and process content to see statistics.</td></tr>');
        }

        displayReport(data) {
            // Update stats
            $('#aysa-total-keywords').text(data.total_keywords || 0);
            $('#aysa-total-links').text(data.total_links || 0);
            
            const statusElement = $('#aysa-linking-status');
            if (data.settings?.enabled) {
                statusElement.text('Active').addClass('active').removeClass('inactive');
            } else {
                statusElement.text('Disabled').addClass('inactive').removeClass('active');
            }

            // Update table
            const tableBody = $('#aysa-keyword-stats-table tbody');
            tableBody.empty();

            if (data.keyword_stats && data.keyword_stats.length > 0) {
                $('.aysa-group-container').remove();
                $('#aysa-keyword-stats-table').show();
                tableBody.html(this.renderReportRows(data.keyword_stats));
            } else {
                $('.aysa-group-container').remove();
                $('#aysa-keyword-stats-table').show();
                tableBody.html(`
                    <tr>
                        <td colspan="6" class="aysa-no-data">
                            No internal links have been created yet. Enable internal linking and process content to see statistics.
                        </td>
                    </tr>
                `);
            }
        }

        renderReportRows(keywordStats) {
            return keywordStats.map((stat) => {
                const keyword = this.escapeHtml(stat.keyword || '');
                const targetUrl = stat.targetUrl || stat.target_page_url || stat.target_url || '#';
                const targetTitle = this.escapeHtml(stat.targetTitle || stat.target_title || 'Target');
                const totalLinks = stat.totalLinks || stat.total_links || 0;
                const lastPlacement = this.formatDate(
                    stat.lastPlacement || (Array.isArray(stat.placements) && stat.placements.length > 0 ? stat.placements[stat.placements.length - 1].timestamp : null)
                );
                const sourceHtml = this.renderSourceFallback(stat);

                return `
                    <tr>
                        <td><strong style="color:#2271b1;">${keyword}</strong></td>
                        <td>
                            <a href="${targetUrl}" target="_blank" rel="noopener noreferrer">${targetTitle}</a>
                        </td>
                        <td>
                            <div class="aysa-source-links" data-keyword="${keyword}">
                                ${sourceHtml}
                            </div>
                        </td>
                        <td style="text-align:center;">
                            <span style="background:#00a32a;color:#fff;padding:4px 8px;border-radius:4px;font-weight:700;display:inline-block;">${totalLinks}</span>
                        </td>
                        <td>${lastPlacement}</td>
                        <td style="text-align:center;">
                            <button class="button button-small aysa-keyword-delete" data-keyword="${keyword}">Delete</button>
                        </td>
                    </tr>
                `;
            }).join('');
        }

        /**
         * Update stats after link deletion
         */
        updateStatsAfterDeletion() {
            // Simple refresh of the main stats without full reload
            setTimeout(() => {
                this.loadReport();
            }, 500);
        }

        /**
         * Group keywords by target type for organized display
         */
        groupKeywordsByTargetType(keywordArray) {
            const groups = new Map();
            
            keywordArray.forEach((stat, index) => {
                let targetType = (stat.targetType || stat.target_type || 'unknown').toLowerCase();
                
                // Map various type variations to standard types
                if (targetType === 'term' || targetType === 'category') {
                    targetType = 'category';
                } else if (targetType === 'post' || targetType === 'blog') {
                    targetType = 'post';
                } else if (targetType === 'page') {
                    targetType = 'page';
                } else if (targetType === 'product') {
                    targetType = 'product';
                } else {
                    targetType = 'unknown';
                }
                
                if (!groups.has(targetType)) {
                    groups.set(targetType, {
                        type: targetType,
                        displayName: this.getTypeDisplayName(targetType),
                        color: this.getTypeColor(targetType),
                        icon: this.getTypeIcon(targetType),
                        keywords: [],
                        totalKeywords: 0,
                        totalLinks: 0
                    });
                }
                
                const group = groups.get(targetType);
                group.keywords.push(stat);
                group.totalKeywords++;
                group.totalLinks += (stat.totalLinks || stat.total_links || 0);
            });
            
            // Sort groups by type priority (Products, Pages, Posts, Categories, Terms, Other)
            const sortedGroups = Array.from(groups.values()).sort((a, b) => {
                const order = ['product', 'page', 'post', 'category', 'term', 'unknown'];
                return order.indexOf(a.type) - order.indexOf(b.type);
            });
            
            return sortedGroups;
        }

        /**
         * Get display name for entity type
         */
        getTypeDisplayName(type) {
            const names = {
                'product': 'Products',
                'page': 'Pages', 
                'post': 'Posts',
                'category': 'Categories',
                'term': 'Terms',
                'unknown': 'Other'
            };
            return names[type] || type.charAt(0).toUpperCase() + type.slice(1);
        }

        /**
         * Get color for entity type
         */
        getTypeColor(type) {
            const colors = {
                'product': '#e74c3c',
                'page': '#3498db',
                'post': '#2ecc71', 
                'category': '#f39c12',
                'term': '#9b59b6',
                'unknown': '#95a5a6'
            };
            return colors[type] || '#95a5a6';
        }

        /**
         * Get icon for entity type
         */
        getTypeIcon(type) {
            const icons = {
                'product': '🛍️',
                'page': '📄',
                'post': '📝',
                'category': '📂',
                'term': '🏷️',
                'unknown': '❓'
            };
            return icons[type] || '📄';
        }

        /**
         * Render grouped table with collapse/expand functionality using separate sections
         */
        renderGroupedTable(tableBody, groupedData) {
            // Clear the existing table body
            tableBody.empty();
            
            // Get the parent container to add groups outside the table
            const tableContainer = tableBody.closest('.aysa-reports-table');
            
            // Remove any existing group containers
            tableContainer.find('.aysa-group-container').remove();
            
            // Hide the original table
            tableContainer.find('table').hide();
            
            // Create groups as separate sections
            groupedData.forEach((group, index) => {
                const groupContainer = $(`
                    <div class="aysa-group-container" data-group="${group.type}" style="margin-bottom: 20px;">
                        <!-- Group Header -->
                        <div class="aysa-group-header" data-group="${group.type}" style="
                            background: linear-gradient(135deg, ${group.color}15, ${group.color}05);
                            border: 2px solid ${group.color}30;
                            border-radius: 8px 8px 0 0;
                            cursor: pointer;
                            user-select: none;
                            padding: 15px 20px;
                            margin-bottom: 0;
                        ">
                            <div style="display: flex; align-items: center; gap: 15px;">
                                <span class="aysa-group-toggle" style="
                                    display: inline-block;
                                    width: 22px;
                                    height: 22px;
                                    background: ${group.color};
                                    color: white;
                                    border-radius: 50%;
                                    text-align: center;
                                    line-height: 22px;
                                    font-size: 12px;
                                    transition: transform 0.3s ease;
                                    cursor: pointer;
                                ">▼</span>
                                <span style="font-size: 20px;">${group.icon}</span>
                                <span style="font-size: 18px; font-weight: 600; color: ${group.color};">${group.displayName}</span>
                                <span style="
                                    background: ${group.color};
                                    color: white;
                                    padding: 5px 12px;
                                    border-radius: 15px;
                                    font-size: 13px;
                                    margin-left: auto;
                                    font-weight: 500;
                                ">${group.totalKeywords} keywords • ${group.totalLinks} links</span>
                            </div>
                        </div>
                        
                        <!-- Group Content -->
                        <div class="aysa-group-content" data-group="${group.type}" style="
                            border: 2px solid ${group.color}30;
                            border-top: none;
                            border-radius: 0 0 8px 8px;
                            overflow: hidden;
                        ">
                            <table class="aysa-table" style="margin: 0; border: none;">
                                <thead style="background: ${group.color}10;">
                                    <tr>
                                        <th style="padding: 12px; border: none; color: ${group.color};">Keyword</th>
                                        <th style="padding: 12px; border: none; color: ${group.color};">Target Page</th>
                                        <th style="padding: 12px; border: none; color: ${group.color};">Source</th>
                                        <th style="padding: 12px; border: none; color: ${group.color};">Links Added</th>
                                        <th style="padding: 12px; border: none; color: ${group.color};">Last Placement</th>
                                        <th style="padding: 12px; border: none; color: ${group.color};">Actions</th>
                                    </tr>
                                </thead>
                                <tbody class="aysa-group-table-body">
                                    ${this.renderGroupKeywords(group)}
                                </tbody>
                            </table>
                        </div>
                    </div>
                `);
                
                tableContainer.append(groupContainer);
            });
            
            // Bind collapse/expand functionality
            this.bindGroupToggleEvents();
        }

        /**
         * Render keywords for a specific group
         */
        renderGroupKeywords(group) {
            return group.keywords.map(stat => {
                const lastPlacement = this.formatDate(stat.lastPlacement || (stat.placements && stat.placements.length > 0 ? stat.placements[stat.placements.length - 1].timestamp : null));
                const typeColor = this.getTypeColor(group.type);
                const sourceHtml = this.renderSourceFallback(stat);
                
                return `
                    <tr style="border-bottom: 1px solid #f0f0f0;">
                        <td style="padding: 12px;">
                            <strong style="color: #2271b1;">${this.escapeHtml(stat.keyword)}</strong>
                        </td>
                        <td style="padding: 12px;">
                            <a href="${stat.targetUrl || stat.target_page_url || stat.target_url || '#'}" target="_blank" style="text-decoration: none; color: #0073aa; font-weight: 500;">
                                ${this.escapeHtml(stat.targetTitle || stat.target_title || 'Target')}
                            </a>
                            <div style="margin-top: 4px;">
                                <span style="background: ${typeColor}; color: white; padding: 2px 6px; border-radius: 3px; font-size: 11px;">
                                    ${group.type.toUpperCase()}
                                </span>
                            </div>
                        </td>
                        <td style="padding: 12px;">
                            <div class="aysa-source-links" data-keyword="${this.escapeHtml(stat.keyword)}">
                                ${sourceHtml}
                            </div>
                        </td>
                        <td style="padding: 12px; text-align: center;">
                            <span style="background: #00a32a; color: white; padding: 4px 8px; border-radius: 4px; font-weight: bold; display: inline-block;">
                                ${stat.totalLinks || stat.total_links || 0}
                            </span>
                        </td>
                        <td style="padding: 12px; color: #666; font-size: 12px;">
                            ${lastPlacement}
                        </td>
                        <td style="padding: 12px; text-align: center;">
                            <button class="button button-small aysa-keyword-delete" data-keyword="${this.escapeHtml(stat.keyword)}">
                                🗑️ Delete
                            </button>
                        </td>
                    </tr>
                `;
            }).join('');
        }

        renderSourceFallback(stat) {
            const placements = Array.isArray(stat.placements) ? stat.placements : [];
            if (!placements.length) {
                return '<span style="color: #666; font-style: italic; font-size: 12px;">No source data</span>';
            }

            const uniqueSources = new Map();
            placements.forEach((placement) => {
                const title = placement.source_title || placement.sourceTitle || 'Source';
                const url = placement.source_url || placement.sourceUrl || placement.source_permalink || placement.sourcePermalink || placement.source_link || placement.sourceLink || placement.url || '';
                const key = `${title}__${url}`;
                if (!uniqueSources.has(key)) {
                    uniqueSources.set(key, { title, url, count: 0 });
                }
                uniqueSources.get(key).count += 1;
            });

            const lines = Array.from(uniqueSources.values()).map((item) => {
                const safeTitle = this.escapeHtml(item.title);
                const safeCount = item.count > 1 ? ` <span style="color:#7b8799;">(${item.count}x)</span>` : '';
                const href = this.resolveSourceHref(item.url, item.title);
                const safeUrl = this.escapeHtml(href);
                return `<div style="font-size:12px;line-height:1.45;margin:0 0 4px;"><a href="${safeUrl}" target="_blank" rel="noopener noreferrer">${safeTitle}</a>${safeCount}</div>`;
            });

            if (!lines.length) {
                return '<span style="color: #666; font-style: italic; font-size: 12px;">No source data</span>';
            }

            return lines.join('');
        }

        resolveSourceHref(url, title = '') {
            const raw = String(url || '').trim();
            if (raw && raw !== '#') {
                return raw;
            }
            const base = this.getFrontendBaseUrl();
            const q = encodeURIComponent(String(title || '').trim());
            if (!q) {
                return base || '#';
            }
            return `${base.replace(/\/+$/, '')}/?s=${q}`;
        }

        getFrontendBaseUrl() {
            const configured = String(window.aysaInternalLinking?.frontendBaseUrl || window.aysaInternalLinking?.siteUrl || '').trim();
            if (configured) {
                return configured.replace(/\/+$/, '');
            }
            try {
                const loc = window.location;
                if (!loc || !loc.origin) {
                    return '';
                }
                return String(loc.origin).replace(/\/+$/, '');
            } catch (e) {
                return '';
            }
        }

        /**
         * Bind events for group collapse/expand functionality
         */
        bindGroupToggleEvents() {
            $(document).off('click', '.aysa-group-header').on('click', '.aysa-group-header', (e) => {
                const $header = $(e.currentTarget);
                const groupType = $header.data('group');
                const $content = $header.siblings('.aysa-group-content');
                const $toggle = $header.find('.aysa-group-toggle');
                
                if ($content.is(':visible')) {
                    // Collapse
                    $content.slideUp(300);
                    $toggle.css('transform', 'rotate(-90deg)').text('▶');
                    $header.css('opacity', '0.7');
                    this.saveGroupState(groupType, false);
                } else {
                    // Expand
                    $content.slideDown(300);
                    $toggle.css('transform', 'rotate(0deg)').text('▼');
                    $header.css('opacity', '1');
                    this.saveGroupState(groupType, true);
                }
            });
            
            // Restore saved states
            this.restoreGroupStates();
        }

        /**
         * Save group expand/collapse state to localStorage
         */
        saveGroupState(groupType, isExpanded) {
            try {
                const states = JSON.parse(localStorage.getItem('aysa_group_states') || '{}');
                states[groupType] = isExpanded;
                localStorage.setItem('aysa_group_states', JSON.stringify(states));
            } catch (e) {
                console.warn('Failed to save group state:', e);
            }
        }

        /**
         * Restore group states from localStorage
         */
        restoreGroupStates() {
            try {
                const states = JSON.parse(localStorage.getItem('aysa_group_states') || '{}');
                
                // Wait a bit for DOM to be ready
                setTimeout(() => {
                    Object.entries(states).forEach(([groupType, isExpanded]) => {
                        const $header = $(`.aysa-group-header[data-group="${groupType}"]`);
                        const $content = $header.siblings('.aysa-group-content');
                        const $toggle = $header.find('.aysa-group-toggle');
                        
                        if (!isExpanded) {
                            $content.hide();
                            $toggle.css('transform', 'rotate(-90deg)').text('▶');
                            $header.css('opacity', '0.7');
                        }
                    });
                }, 100);
            } catch (e) {
                console.warn('Failed to restore group states:', e);
            }
        }

        showKeywordDetails(keyword, keywordStats) {
            // Modal functionality has been removed and replaced with inline Source column
            console.log('📊 showKeywordDetails bypassed - using inline Source column instead');
            return;
        }

        toggleFunctionality() {
            const enabled = $('#aysa-internal-linking-enabled').is(':checked');
            
            // Enable/disable other controls
            $('.aysa-internal-linking-settings input, .aysa-internal-linking-settings select')
                .not('#aysa-internal-linking-enabled')
                .prop('disabled', !enabled);

            this.updateUI();
        }

        updateUI() {
            const enabled = $('#aysa-internal-linking-enabled').is(':checked');
            
            // Update status indicator
            const statusElement = $('#aysa-linking-status');
            if (enabled) {
                statusElement.text('Active').removeClass('inactive').addClass('active');
            } else {
                statusElement.text('Disabled').removeClass('active').addClass('inactive');
            }

            // Enable/disable processing buttons
            $('#aysa-process-all-internal-links, #aysa-process-all-content')
                .prop('disabled', !enabled || this.isProcessing);

            if (this.isProcessing) {
                $('#aysa-process-all-internal-links, #aysa-process-all-content')
                    .text('Processing...');
            } else {
                $('#aysa-process-all-internal-links').text('Process All Content Now');
                $('#aysa-process-all-content').text('Process All Content');
            }
        }

        collectFormData() {
            console.log('🔍 Collecting form data...');
            
            // Check element existence
            const elements = {
                enabled: $('#aysa-internal-linking-enabled'),
                maxLinksKeyword: $('#aysa-max-links-per-keyword'),
                maxLinksEntity: $('#aysa-max-links-per-entity'),
                matchingType: $('#aysa-matching-type'),
                processPosts: $('#aysa-process-posts'),
                processPages: $('#aysa-process-pages'),
                processCategories: $('#aysa-process-categories'),
                processProducts: $('#aysa-process-products'),
                caseSensitive: $('#aysa-case-sensitive'),
                ignoreExisting: $('#aysa-ignore-existing-links'),
                priorityAuthority: $('#aysa-priority-by-authority'),
                excludedIds: $('#aysa-excluded-post-ids'),
                excludedUrlPatterns: $('#aysa-excluded-url-patterns')
            };
            
            // Log element existence
            Object.keys(elements).forEach(key => {
                const element = elements[key];
                console.log(`Element ${key}:`, element.length > 0 ? '✅ Found' : '❌ Missing', element.length > 0 ? `Value: ${element.is('[type="checkbox"]') ? element.is(':checked') : element.val()}` : '');
            });
            
            return {
                enabled: elements.enabled.is(':checked'),
                max_links_per_keyword: parseInt(elements.maxLinksKeyword.val()) || 1,
                max_links_per_entity: parseInt(elements.maxLinksEntity.val()) || 3,
                matching_type: elements.matchingType.val() || 'both',
                process_posts: elements.processPosts.is(':checked'),
                process_pages: elements.processPages.is(':checked'),
                process_categories: elements.processCategories.is(':checked'),
                process_products: elements.processProducts.is(':checked'),
                case_sensitive: elements.caseSensitive.is(':checked'),
                ignore_existing_links: elements.ignoreExisting.is(':checked'),
                priority_by_authority: elements.priorityAuthority.is(':checked'),
                excluded_post_ids: elements.excludedIds.val() || '',
                excluded_url_patterns: elements.excludedUrlPatterns.val() || ''
            };
        }

        closeModal() {
            $('.aysa-modal').hide();
        }

        showLoading(message = 'Loading...') {
            // Create or update loading overlay
            let overlay = $('.aysa-loading-overlay');
            if (overlay.length === 0) {
                overlay = $(`
                    <div class="aysa-loading-overlay" style="
                        position: fixed;
                        top: 0;
                        left: 0;
                        width: 100%;
                        height: 100%;
                        background: rgba(255,255,255,0.8);
                        display: flex;
                        align-items: center;
                        justify-content: center;
                        z-index: 9999;
                        flex-direction: column;
                    ">
                        <div class="aysa-spinner" style="
                            border: 4px solid #f3f3f3;
                            border-top: 4px solid #3498db;
                            border-radius: 50%;
                            width: 40px;
                            height: 40px;
                            animation: spin 2s linear infinite;
                            margin-bottom: 15px;
                        "></div>
                        <div class="aysa-loading-text" style="
                            font-size: 16px;
                            color: #333;
                        ">${message}</div>
                    </div>
                `);
                $('body').append(overlay);
                
                // Add spinner animation
                if (!$('#aysa-spinner-style').length) {
                    $('head').append(`
                        <style id="aysa-spinner-style">
                            @keyframes spin {
                                0% { transform: rotate(0deg); }
                                100% { transform: rotate(360deg); }
                            }
                        </style>
                    `);
                }
            } else {
                overlay.find('.aysa-loading-text').text(message);
                overlay.show();
            }
        }

        hideLoading() {
            $('.aysa-loading-overlay').hide();
        }

        showNotification(message, type = 'info') {
            const notification = $(`
                <div class="aysa-notification aysa-notification-${type}" style="
                    position: fixed;
                    top: 32px;
                    right: 20px;
                    background: ${type === 'success' ? '#4caf50' : type === 'error' ? '#f44336' : type === 'warning' ? '#ff9800' : '#2196F3'};
                    color: white;
                    padding: 15px 20px;
                    border-radius: 4px;
                    box-shadow: 0 2px 5px rgba(0,0,0,0.2);
                    z-index: 10000;
                    max-width: 300px;
                    word-wrap: break-word;
                ">
                    ${this.escapeHtml(message)}
                </div>
            `);

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

            // Auto-hide after 5 seconds
            setTimeout(() => {
                notification.fadeOut(() => notification.remove());
            }, 5000);

            // Allow manual close
            notification.on('click', () => {
                notification.fadeOut(() => notification.remove());
            });
        }

        escapeHtml(text) {
            const div = document.createElement('div');
            div.textContent = text;
            return div.innerHTML;
        }

        formatDate(dateString) {
            try {
                const date = new Date(dateString);
                return date.toLocaleDateString() + ' ' + date.toLocaleTimeString();
            } catch (e) {
                return dateString;
            }
        }

        getNonce() {
            // Try multiple sources for the nonce
            let nonce = '';
            
            // First try the specific internal linking nonce
            if (window.aysaInternalLinking && window.aysaInternalLinking.nonce) {
                nonce = window.aysaInternalLinking.nonce;
                console.log('[Internal Linking] Using aysaInternalLinking.nonce:', nonce);
            }
            // Fallback to general AYSA nonce
            else if (window.aysaAjax && window.aysaAjax.nonce) {
                nonce = window.aysaAjax.nonce;
                console.log('[Internal Linking] Using aysaAjax.nonce:', nonce);
            }
            // Try to find internal linking specific nonce
            else if ($('#aysa-internal-linking-nonce').length > 0) {
                nonce = $('#aysa-internal-linking-nonce').val();
                console.log('[Internal Linking] Using #aysa-internal-linking-nonce:', nonce);
            }
            // Try to find general aysa nonce in page
            else if ($('#aysa-nonce').length > 0) {
                nonce = $('#aysa-nonce').val();
                console.log('[Internal Linking] Using #aysa-nonce:', nonce);
            }
            // Last resort - try any WordPress nonce on page
            else if ($('input[name*="nonce"]').length > 0) {
                nonce = $('input[name*="nonce"]').first().val();
                console.log('[Internal Linking] Using fallback nonce:', nonce);
            }
            
            if (!nonce) {
                console.error('[Internal Linking] No nonce found! Available objects:', {
                    aysaInternalLinking: window.aysaInternalLinking,
                    aysaAjax: window.aysaAjax
                });
            }
            
            return nonce;
        }
    }

    // Initialize when DOM is ready
    $(document).ready(() => {
        console.log('[Internal Linking] DOM ready, checking for elements...');
        console.log('[Internal Linking] Found internal-linking-content:', $('#internal-linking-content').length);
        console.log('[Internal Linking] Found save button:', $('#aysa-save-internal-linking-settings').length);
        console.log('[Internal Linking] Available objects:', {
            aysaInternalLinking: window.aysaInternalLinking,
            aysaAjax: window.aysaAjax,
            ajaxurl: typeof ajaxurl !== 'undefined' ? ajaxurl : 'undefined'
        });
        
        // Wait a bit more to ensure all tabs are loaded
        setTimeout(() => {
            console.log('[Internal Linking] Post-timeout check - save button:', $('#aysa-save-internal-linking-settings').length);
            
            // Initialize if we're on a page with the internal linking content OR on the technical optimization page
            if ($('#internal-linking-content').length > 0 || 
                window.location.href.indexOf('aysa-technical-optimization') !== -1 ||
                $('#aysa-save-internal-linking-settings').length > 0) {
                console.log('[Internal Linking] Initializing...');
                window.aysaInternalLinkingInstance = new AysaInternalLinking();
            } else {
                console.log('[Internal Linking] Not initializing - not on correct page');
            }
        }, 500);
    });

})(jQuery);
