/**
 * AYSA SEO History Manager
 * 
 * Handles client-side SEO generation history logging and management.
 * Integrates with the WordPress backend to store and retrieve SEO generation data.
 * 
 * @package AYSA
 * @since 1.0.0
 */

class AysaSeoHistory {
    
    /**
     * Initialize the SEO history manager
     * @param {Object} options - Configuration options
     */
    constructor(options = {}) {
        this.options = {
            debug: false,
            ajaxUrl: window.ajaxurl || '/wp-admin/admin-ajax.php',
            nonce: '',
            autoLog: true,
            batchSize: 10,
            retryAttempts: 3,
            retryDelay: 1000,
            ...options
        };
        
        this.pendingLogs = [];
        this.isProcessing = false;
        this.retryQueue = [];
        
        this._init();
    }
    
    /**
     * Initialize the history manager
     * @private
     */
    _init() {
        // Set up global reference
        window.aysaSeoHistory = this;
        
        // Set up periodic batch processing
        if (this.options.autoLog) {
            setInterval(() => this._processPendingLogs(), 5000);
        }
        
        // Set up page unload handler to flush pending logs
        window.addEventListener('beforeunload', () => {
            this._flushPendingLogs();
        });
        
        if (this.options.debug) {
            console.log('[AysaSeoHistory] Initialized with options:', this.options);
        }
    }
    
    /**
     * Log a new SEO generation
     * @param {Object} data - The SEO generation data
     * @returns {Promise}
     */
    async logGeneration(data) {
        try {
            // Validate required fields
            if (!data.entity_id || !data.entity_type || !data.keyword) {
                throw new Error('Missing required fields: entity_id, entity_type, keyword');
            }
            
            // Prepare the log entry
            const logEntry = {
                ...data,
                timestamp: new Date().toISOString(),
                session_id: this._getSessionId(),
                user_id: this._getCurrentUserId(),
                ip_address: this._getClientIP(),
                user_agent: navigator.userAgent,
                page_url: window.location.href,
                referrer: document.referrer
            };
            
            if (this.options.autoLog) {
                // Add to pending queue for batch processing
                this.pendingLogs.push(logEntry);
                
                if (this.options.debug) {
                    console.log('[AysaSeoHistory] Added to pending logs:', logEntry);
                }
                
                return Promise.resolve({ queued: true, entry: logEntry });
            } else {
                // Send immediately
                return await this._sendLogEntry(logEntry);
            }
            
        } catch (error) {
            console.error('[AysaSeoHistory] Failed to log generation:', error);
            throw error;
        }
    }
    
    /**
     * Mark an entry as applied
     * @param {number} entryId - The history entry ID
     * @returns {Promise}
     */
    async markAsApplied(entryId) {
        return await this._updateEntryStatus(entryId, 'applied');
    }
    
    /**
     * Mark an entry as reverted
     * @param {number} entryId - The history entry ID
     * @returns {Promise}
     */
    async markAsReverted(entryId) {
        return await this._updateEntryStatus(entryId, 'reverted');
    }
    
    /**
     * Get history for a specific entity
     * @param {string} entityType - The entity type
     * @param {number} entityId - The entity ID
     * @param {Object} options - Query options
     * @returns {Promise}
     */
    async getEntityHistory(entityType, entityId, options = {}) {
        try {
            const response = await this._makeAjaxRequest('aysa_get_entity_history', {
                entity_type: entityType,
                entity_id: entityId,
                limit: options.limit || 50,
                offset: options.offset || 0
            });
            
            return response.data;
            
        } catch (error) {
            console.error('[AysaSeoHistory] Failed to get entity history:', error);
            throw error;
        }
    }
    
    /**
     * Get recent history
     * @param {Object} options - Query options
     * @returns {Promise}
     */
    async getRecentHistory(options = {}) {
        try {
            const response = await this._makeAjaxRequest('aysa_get_recent_history', {
                limit: options.limit || 50,
                offset: options.offset || 0,
                entity_type: options.entityType || '',
                user_id: options.userId || 0
            });
            
            return response.data;
            
        } catch (error) {
            console.error('[AysaSeoHistory] Failed to get recent history:', error);
            throw error;
        }
    }
    
    /**
     * Search history
     * @param {string} query - Search query
     * @param {Object} options - Search options
     * @returns {Promise}
     */
    async searchHistory(query, options = {}) {
        try {
            const response = await this._makeAjaxRequest('aysa_search_history', {
                query: query,
                limit: options.limit || 50,
                offset: options.offset || 0,
                entity_type: options.entityType || '',
                user_id: options.userId || 0
            });
            
            return response.data;
            
        } catch (error) {
            console.error('[AysaSeoHistory] Failed to search history:', error);
            throw error;
        }
    }
    
    /**
     * Get statistics
     * @returns {Promise}
     */
    async getStatistics() {
        try {
            const response = await this._makeAjaxRequest('aysa_get_history_statistics');
            return response.data;
            
        } catch (error) {
            console.error('[AysaSeoHistory] Failed to get statistics:', error);
            throw error;
        }
    }
    
    /**
     * Flush all pending logs immediately
     * @returns {Promise}
     */
    async flushPendingLogs() {
        return await this._flushPendingLogs();
    }
    
    /**
     * Process pending logs in batches
     * @private
     */
    async _processPendingLogs() {
        if (this.isProcessing || this.pendingLogs.length === 0) {
            return;
        }
        
        this.isProcessing = true;
        
        try {
            const batch = this.pendingLogs.splice(0, this.options.batchSize);
            
            if (this.options.debug) {
                console.log(`[AysaSeoHistory] Processing batch of ${batch.length} logs`);
            }
            
            await this._sendLogBatch(batch);
            
        } catch (error) {
            console.error('[AysaSeoHistory] Failed to process pending logs:', error);
            
            // Add failed logs to retry queue
            this.retryQueue.push(...batch);
            
        } finally {
            this.isProcessing = false;
        }
    }
    
    /**
     * Flush all pending logs immediately
     * @private
     */
    async _flushPendingLogs() {
        if (this.pendingLogs.length === 0) {
            return;
        }
        
        try {
            const allLogs = [...this.pendingLogs];
            this.pendingLogs = [];
            
            if (this.options.debug) {
                console.log(`[AysaSeoHistory] Flushing ${allLogs.length} pending logs`);
            }
            
            // Send in batches
            for (let i = 0; i < allLogs.length; i += this.options.batchSize) {
                const batch = allLogs.slice(i, i + this.options.batchSize);
                await this._sendLogBatch(batch);
            }
            
        } catch (error) {
            console.error('[AysaSeoHistory] Failed to flush pending logs:', error);
        }
    }
    
    /**
     * Send a single log entry
     * @param {Object} logEntry - The log entry
     * @returns {Promise}
     * @private
     */
    async _sendLogEntry(logEntry) {
        return await this._makeAjaxRequest('aysa_log_seo_generation', {
            log_data: logEntry
        });
    }
    
    /**
     * Send a batch of log entries
     * @param {Array} batch - Array of log entries
     * @returns {Promise}
     * @private
     */
    async _sendLogBatch(batch) {
        return await this._makeAjaxRequest('aysa_log_seo_generation_batch', {
            log_data: batch
        });
    }
    
    /**
     * Update entry status
     * @param {number} entryId - The entry ID
     * @param {string} status - The new status
     * @returns {Promise}
     * @private
     */
    async _updateEntryStatus(entryId, status) {
        try {
            const response = await this._makeAjaxRequest('aysa_update_history_status', {
                entry_id: entryId,
                status: status
            });
            
            if (this.options.debug) {
                console.log(`[AysaSeoHistory] Updated entry ${entryId} status to ${status}`);
            }
            
            return response.data;
            
        } catch (error) {
            console.error(`[AysaSeoHistory] Failed to update entry ${entryId} status:`, error);
            throw error;
        }
    }
    
    /**
     * Make an AJAX request with retry logic
     * @param {string} action - WordPress AJAX action
     * @param {Object} data - Request data
     * @returns {Promise}
     * @private
     */
    async _makeAjaxRequest(action, data = {}) {
        const requestData = {
            action: action,
            nonce: this.options.nonce,
            ...data
        };
        
        for (let attempt = 1; attempt <= this.options.retryAttempts; attempt++) {
            try {
                const response = await fetch(this.options.ajaxUrl, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/x-www-form-urlencoded',
                    },
                    body: new URLSearchParams(requestData)
                });
                
                if (!response.ok) {
                    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
                }
                
                const result = await response.json();
                
                if (!result.success) {
                    throw new Error(result.data || 'Unknown error');
                }
                
                return result;
                
            } catch (error) {
                if (attempt === this.options.retryAttempts) {
                    throw error;
                }
                
                if (this.options.debug) {
                    console.warn(`[AysaSeoHistory] Attempt ${attempt} failed, retrying in ${this.options.retryDelay}ms:`, error);
                }
                
                await new Promise(resolve => setTimeout(resolve, this.options.retryDelay * attempt));
            }
        }
    }
    
    /**
     * Get session ID
     * @returns {string}
     * @private
     */
    _getSessionId() {
        if (!this._sessionId) {
            this._sessionId = 'sess_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
        }
        return this._sessionId;
    }
    
    /**
     * Get current user ID
     * @returns {number}
     * @private
     */
    _getCurrentUserId() {
        // Try to get from WordPress global
        if (typeof window.userSettings !== 'undefined' && window.userSettings.uid) {
            return parseInt(window.userSettings.uid);
        }
        
        // Try to get from meta tag
        const userMeta = document.querySelector('meta[name="current-user-id"]');
        if (userMeta) {
            return parseInt(userMeta.content);
        }
        
        // Try to get from body class
        const bodyClasses = document.body.className;
        const userMatch = bodyClasses.match(/user-id-(\d+)/);
        if (userMatch) {
            return parseInt(userMatch[1]);
        }
        
        return 0;
    }
    
    /**
     * Get client IP address (best effort)
     * @returns {string}
     * @private
     */
    _getClientIP() {
        // This is a placeholder - actual IP detection would require server-side support
        return 'unknown';
    }
}

// Auto-initialize if WordPress AJAX URL is available
if (typeof window.ajaxurl !== 'undefined') {
    document.addEventListener('DOMContentLoaded', function() {
        // Get nonce from a meta tag or global variable
        let nonce = '';
        
        const nonceMeta = document.querySelector('meta[name="aysa-history-nonce"]');
        if (nonceMeta) {
            nonce = nonceMeta.content;
        } else if (typeof window.aysaHistoryNonce !== 'undefined') {
            nonce = window.aysaHistoryNonce;
        }
        
        // Initialize the history manager
        new AysaSeoHistory({
            nonce: nonce,
            debug: typeof window.aysaDebug !== 'undefined' ? window.aysaDebug : false
        });
    });
}

// Export for module systems
if (typeof module !== 'undefined' && module.exports) {
    module.exports = AysaSeoHistory;
}

// AMD support
if (typeof define === 'function' && define.amd) {
    define([], function() {
        return AysaSeoHistory;
    });
}