<?php
/**
 * VMPFence AJAX Background Processor
 * 
 * Handles differential caching of plugin checksums via AJAX
 * to avoid blocking and provide better UX with progress updates.
 * 
 * @package VMPFence
 * @since 2.0.0
 */

if (!defined('ABSPATH')) {
    exit;
}

class VMPFence_AJAX_Background_Processor {
    
    /**
     * Singleton instance
     */
    private static $instance = null;
    
    /**
     * Metadata option name for tracking cached plugins
     */
    const METADATA_KEY = 'vmpfence_cached_plugins_list';
    
    /**
     * Batch size for parallel processing
     */
    const BATCH_SIZE = 5;
    
    /**
     * Integrity checker instance
     */
    private $integrity_checker;
    
    /**
     * Get singleton instance
     */
    public static function get_instance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    /**
     * Constructor
     */
    private function __construct() {
        // Load integrity checker
        if (!class_exists('VMPFence_WP_Integrity_Checker')) {
            require_once VMPFENCE_PLUGIN_DIR . 'includes/class-wp-integrity-checker.php';
        }
        $this->integrity_checker = new VMPFence_WP_Integrity_Checker();
    }
    
    /**
     * Detect missing or updated plugins that need checksum caching
     * 
     * @return array Array of plugins needing cache: [{slug, version, name}]
     */
    public function detect_missing_plugins() {
        // Get all installed plugins
        if (!function_exists('get_plugins')) {
            require_once ABSPATH . 'wp-admin/includes/plugin.php';
        }
        
        $all_plugins = get_plugins();
        $cached_plugins = $this->get_cache_metadata();
        $missing_plugins = array();
        
        foreach ($all_plugins as $plugin_path => $plugin_data) {
            // Extract plugin slug
            $plugin_slug = dirname($plugin_path);
            if ($plugin_slug === '.') {
                $plugin_slug = basename($plugin_path, '.php');
            }
            
            $plugin_version = $plugin_data['Version'] ?? '';
            $plugin_name = $plugin_data['Name'] ?? $plugin_slug;
            
            if (empty($plugin_version)) {
                continue;
            }
            
            // Check if plugin is cached with correct version
            $is_missing = false;
            
            if (!isset($cached_plugins[$plugin_slug])) {
                // Plugin not in cache at all
                $is_missing = true;
            } elseif ($cached_plugins[$plugin_slug] !== $plugin_version) {
                // Plugin version changed (update detected)
                $is_missing = true;
            }
            
            if ($is_missing) {
                $missing_plugins[] = array(
                    'slug' => $plugin_slug,
                    'version' => $plugin_version,
                    'name' => $plugin_name,
                    'path' => $plugin_path
                );
            }
        }
        
        return $missing_plugins;
    }
    
    /**
     * Download and cache checksums for a single plugin
     * 
     * @param string $plugin_slug Plugin slug
     * @param string $plugin_version Plugin version
     * @return array Result: {success, message, files_count, cache_key}
     */
    public function download_single_plugin_checksums($plugin_slug, $plugin_version) {
        try {
            // Validate inputs
            if (empty($plugin_slug) || empty($plugin_version)) {
                return array(
                    'success' => false,
                    'message' => 'Invalid plugin slug or version',
                    'files_count' => 0
                );
            }
            
            // Check if already cached with correct version
            $cache_key = 'vmpfence_plugin_checksums_' . $plugin_slug . '_' . $plugin_version;
            $existing_cache = get_transient($cache_key);
            
            if ($existing_cache !== false && is_array($existing_cache) && count($existing_cache) > 0) {
                // Already cached - just update metadata
                $this->update_cache_metadata($plugin_slug, $plugin_version);
                
                return array(
                    'success' => true,
                    'message' => 'Already cached',
                    'files_count' => count($existing_cache),
                    'cache_key' => $cache_key,
                    'from_cache' => true
                );
            }
            
            // Call integrity checker to download and generate checksums
            // This uses the existing get_official_checksums method
            $checksums = $this->integrity_checker->get_official_checksums('plugin', $plugin_slug, $plugin_version);
            
            if (empty($checksums) || !is_array($checksums)) {
                // Plugin not found in WordPress.org or download failed
                return array(
                    'success' => false,
                    'message' => 'Plugin not found in WordPress.org repository or checksums unavailable',
                    'files_count' => 0,
                    'cache_key' => $cache_key
                );
            }
            
            // Cache was set by integrity_checker, now update metadata
            $this->update_cache_metadata($plugin_slug, $plugin_version);
            
            return array(
                'success' => true,
                'message' => 'Checksums downloaded and cached successfully',
                'files_count' => count($checksums),
                'cache_key' => $cache_key,
                'from_cache' => false
            );
            
        } catch (Exception $e) {
            return array(
                'success' => false,
                'message' => 'Error: ' . $e->getMessage(),
                'files_count' => 0
            );
        }
    }
    
    /**
     * Get cache metadata (list of cached plugins with versions)
     * 
     * @return array Associative array: {plugin_slug => version}
     */
    public function get_cache_metadata() {
        $metadata = get_option(self::METADATA_KEY, array());
        
        // Ensure it's an array
        if (!is_array($metadata)) {
            $metadata = array();
            update_option(self::METADATA_KEY, $metadata, false);
        }
        
        return $metadata;
    }
    
    /**
     * Update cache metadata after successful download
     * 
     * @param string $plugin_slug Plugin slug
     * @param string $plugin_version Plugin version
     * @return bool Success status
     */
    public function update_cache_metadata($plugin_slug, $plugin_version) {
        $metadata = $this->get_cache_metadata();
        $metadata[$plugin_slug] = $plugin_version;
        
        return update_option(self::METADATA_KEY, $metadata, false);
    }
    
    /**
     * Remove plugin from cache metadata
     * 
     * @param string $plugin_slug Plugin slug
     * @return bool Success status
     */
    public function remove_from_metadata($plugin_slug) {
        $metadata = $this->get_cache_metadata();
        
        if (isset($metadata[$plugin_slug])) {
            unset($metadata[$plugin_slug]);
            return update_option(self::METADATA_KEY, $metadata, false);
        }
        
        return true;
    }
    
    /**
     * Clear all cache metadata
     * 
     * @return bool Success status
     */
    public function clear_all_metadata() {
        return delete_option(self::METADATA_KEY);
    }
    
    /**
     * Get cache statistics
     * 
     * @return array Statistics: {total_plugins, cached_plugins, missing_plugins, cache_percentage}
     */
    public function get_cache_statistics() {
        if (!function_exists('get_plugins')) {
            require_once ABSPATH . 'wp-admin/includes/plugin.php';
        }
        
        $all_plugins = get_plugins();
        $missing_plugins = $this->detect_missing_plugins();
        
        $total_count = count($all_plugins);
        $missing_count = count($missing_plugins);
        
        // Calculate cached count as total - missing (more accurate than metadata count)
        // This accounts for expired transients and ensures accuracy
        $cached_count = $total_count - $missing_count;
        
        $cache_percentage = $total_count > 0 ? (($cached_count / $total_count) * 100) : 0;
        
        return array(
            'total_plugins' => $total_count,
            'cached_plugins' => $cached_count,
            'missing_plugins' => $missing_count,
            'cache_percentage' => round($cache_percentage, 2),
            'last_updated' => get_option('vmpfence_cache_last_updated', 'Never')
        );
    }
    
    /**
     * Update last cache update timestamp
     */
    public function update_timestamp() {
        update_option('vmpfence_cache_last_updated', current_time('mysql'), false);
    }
    
    /**
     * Batch download multiple plugins (for manual trigger)
     * 
     * @param array $plugins Array of plugin objects with slug and version
     * @param int $batch_size Number of plugins to process
     * @return array Results for each plugin
     */
    public function batch_download_plugins($plugins, $batch_size = self::BATCH_SIZE) {
        $results = array();
        $processed = 0;
        
        foreach ($plugins as $plugin) {
            if ($processed >= $batch_size) {
                break;
            }
            
            $result = $this->download_single_plugin_checksums(
                $plugin['slug'],
                $plugin['version']
            );
            
            $results[] = array_merge($result, array(
                'slug' => $plugin['slug'],
                'name' => $plugin['name'] ?? $plugin['slug']
            ));
            
            $processed++;
        }
        
        // Update timestamp after batch
        if ($processed > 0) {
            $this->update_timestamp();
        }
        
        return $results;
    }
}
