<?php
/**
 * HVAC Background Jobs System
 * 
 * Provides background processing capabilities for long-running operations
 * using WordPress cron system
 * 
 * @package HVAC_Community_Events
 * @since 1.0.7
 */

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

/**
 * HVAC_Background_Jobs class
 */
class HVAC_Background_Jobs {
    
    /**
     * Job queue option name
     */
    const QUEUE_OPTION = 'hvac_job_queue';
    
    /**
     * Job status option prefix
     */
    const STATUS_PREFIX = 'hvac_job_status_';
    
    /**
     * Maximum jobs to process per batch
     */
    const BATCH_SIZE = 5;
    
    /**
     * Job types
     */
    const JOB_TYPES = [
        'geocoding_batch' => 'Batch Geocoding',
        'csv_import' => 'CSV Import',
        'profile_migration' => 'Profile Migration',
        'cache_warming' => 'Cache Warming'
    ];
    
    /**
     * Initialize hooks
     */
    public static function init() {
        // Register cron hook
        add_action('hvac_process_background_jobs', [__CLASS__, 'process_jobs']);
        
        // Schedule recurring job processing if not already scheduled
        if (!wp_next_scheduled('hvac_process_background_jobs')) {
            wp_schedule_event(time(), 'every_minute', 'hvac_process_background_jobs');
        }
        
        // Add custom cron interval
        add_filter('cron_schedules', [__CLASS__, 'add_cron_intervals']);
        
        // AJAX handlers for job management
        add_action('wp_ajax_hvac_get_job_status', [__CLASS__, 'ajax_get_job_status']);
        add_action('wp_ajax_hvac_cancel_job', [__CLASS__, 'ajax_cancel_job']);
    }
    
    /**
     * Add custom cron intervals
     * 
     * @param array $schedules Existing cron schedules
     * @return array Modified schedules
     */
    public static function add_cron_intervals($schedules) {
        $schedules['every_minute'] = [
            'interval' => 60,
            'display' => 'Every Minute'
        ];
        
        $schedules['every_five_minutes'] = [
            'interval' => 300,
            'display' => 'Every 5 Minutes'
        ];
        
        return $schedules;
    }
    
    /**
     * Queue a background job
     * 
     * @param string $type Job type
     * @param array $data Job data
     * @param int $priority Job priority (lower = higher priority)
     * @return string Job ID
     */
    public static function queue_job($type, $data = [], $priority = 10) {
        if (!isset(self::JOB_TYPES[$type])) {
            throw new InvalidArgumentException("Invalid job type: $type");
        }
        
        $job_id = uniqid('job_');
        $job = [
            'id' => $job_id,
            'type' => $type,
            'data' => $data,
            'priority' => $priority,
            'status' => 'queued',
            'created_at' => time(),
            'attempts' => 0,
            'max_attempts' => 3
        ];
        
        // Get current queue
        $queue = get_option(self::QUEUE_OPTION, []);
        
        // Add job to queue
        $queue[] = $job;
        
        // Sort by priority
        usort($queue, function($a, $b) {
            return $a['priority'] <=> $b['priority'];
        });
        
        // Save queue
        update_option(self::QUEUE_OPTION, $queue);
        
        // Store job status
        self::update_job_status($job_id, 'queued', 'Job queued for processing');
        
        HVAC_Logger::info("Background job queued: {$type} (ID: {$job_id})", 'Background Jobs');
        
        return $job_id;
    }
    
    /**
     * Process background jobs
     */
    public static function process_jobs() {
        $queue = get_option(self::QUEUE_OPTION, []);
        
        if (empty($queue)) {
            return;
        }
        
        $processed = 0;
        $remaining_jobs = [];
        
        foreach ($queue as $job) {
            if ($processed >= self::BATCH_SIZE) {
                $remaining_jobs[] = $job;
                continue;
            }
            
            // Skip jobs that have exceeded max attempts
            if ($job['attempts'] >= $job['max_attempts']) {
                self::update_job_status($job['id'], 'failed', 'Maximum attempts exceeded');
                continue;
            }
            
            // Process job
            $result = self::process_job($job);
            
            if ($result['success']) {
                self::update_job_status($job['id'], 'completed', $result['message']);
                $processed++;
            } else {
                // Increment attempts and re-queue if not at max attempts
                $job['attempts']++;
                if ($job['attempts'] < $job['max_attempts']) {
                    $remaining_jobs[] = $job;
                    self::update_job_status($job['id'], 'retrying', "Attempt {$job['attempts']}/{$job['max_attempts']}: {$result['message']}");
                } else {
                    self::update_job_status($job['id'], 'failed', "Final attempt failed: {$result['message']}");
                }
            }
        }
        
        // Update queue with remaining jobs
        update_option(self::QUEUE_OPTION, $remaining_jobs);
        
        if ($processed > 0) {
            HVAC_Logger::info("Processed {$processed} background jobs", 'Background Jobs');
        }
    }
    
    /**
     * Process a single job
     * 
     * @param array $job Job data
     * @return array Result with success boolean and message
     */
    private static function process_job($job) {
        try {
            self::update_job_status($job['id'], 'processing', 'Job started');
            
            switch ($job['type']) {
                case 'geocoding_batch':
                    return self::process_geocoding_batch($job);
                    
                case 'csv_import':
                    return self::process_csv_import($job);
                    
                case 'profile_migration':
                    return self::process_profile_migration($job);
                    
                case 'cache_warming':
                    return self::process_cache_warming($job);
                    
                default:
                    return [
                        'success' => false,
                        'message' => "Unknown job type: {$job['type']}"
                    ];
            }
            
        } catch (Exception $e) {
            HVAC_Logger::error("Background job error (ID: {$job['id']}): " . $e->getMessage(), 'Background Jobs');
            
            return [
                'success' => false,
                'message' => $e->getMessage()
            ];
        }
    }
    
    /**
     * Process geocoding batch job
     * 
     * @param array $job Job data
     * @return array Result
     */
    private static function process_geocoding_batch($job) {
        if (!class_exists('HVAC_Geocoding_Service')) {
            return [
                'success' => false,
                'message' => 'Geocoding service not available'
            ];
        }
        
        $user_ids = $job['data']['user_ids'] ?? [];
        $processed = 0;
        
        foreach (array_slice($user_ids, 0, 10) as $user_id) { // Process 10 at a time
            $result = HVAC_Geocoding_Service::geocode_user($user_id);
            if ($result) {
                $processed++;
            }
        }
        
        return [
            'success' => true,
            'message' => "Processed geocoding for {$processed} users"
        ];
    }
    
    /**
     * Process CSV import job
     * 
     * @param array $job Job data
     * @return array Result
     */
    private static function process_csv_import($job) {
        $file_path = $job['data']['file_path'] ?? '';
        $import_type = $job['data']['import_type'] ?? '';
        
        if (!file_exists($file_path)) {
            return [
                'success' => false,
                'message' => 'Import file not found'
            ];
        }
        
        // Process CSV in chunks
        $processed = 0;
        $handle = fopen($file_path, 'r');
        
        if ($handle === false) {
            return [
                'success' => false,
                'message' => 'Could not open import file'
            ];
        }
        
        // Skip header row
        fgetcsv($handle);
        
        // Process up to 50 rows
        while (($data = fgetcsv($handle)) !== false && $processed < 50) {
            // Process row based on import type
            if ($import_type === 'trainers') {
                // Process trainer import
                $processed++;
            }
        }
        
        fclose($handle);
        
        return [
            'success' => true,
            'message' => "Processed {$processed} CSV rows"
        ];
    }
    
    /**
     * Process profile migration job
     * 
     * @param array $job Job data
     * @return array Result
     */
    private static function process_profile_migration($job) {
        if (!class_exists('HVAC_Trainer_Profile_Migration')) {
            return [
                'success' => false,
                'message' => 'Migration class not available'
            ];
        }
        
        $batch_size = $job['data']['batch_size'] ?? 20;
        $offset = $job['data']['offset'] ?? 0;
        
        // Process batch of users
        $users = get_users([
            'role__in' => ['hvac_trainer', 'hvac_master_trainer'],
            'number' => $batch_size,
            'offset' => $offset
        ]);
        
        $processed = 0;
        foreach ($users as $user) {
            // Process user migration
            $processed++;
        }
        
        return [
            'success' => true,
            'message' => "Migrated {$processed} user profiles"
        ];
    }
    
    /**
     * Process cache warming job
     * 
     * @param array $job Job data
     * @return array Result
     */
    private static function process_cache_warming($job) {
        if (!class_exists('HVAC_Master_Dashboard_Data')) {
            return [
                'success' => false,
                'message' => 'Dashboard data class not available'
            ];
        }
        
        $dashboard_data = new HVAC_Master_Dashboard_Data();
        
        // Warm up key caches
        $dashboard_data->get_total_events_count();
        $dashboard_data->get_upcoming_events_count();
        $dashboard_data->get_past_events_count();
        $dashboard_data->get_total_tickets_sold();
        $dashboard_data->get_total_revenue();
        
        return [
            'success' => true,
            'message' => 'Cache warmed successfully'
        ];
    }
    
    /**
     * Update job status
     * 
     * @param string $job_id Job ID
     * @param string $status Status
     * @param string $message Status message
     */
    private static function update_job_status($job_id, $status, $message = '') {
        $status_data = [
            'status' => $status,
            'message' => $message,
            'updated_at' => time()
        ];
        
        update_option(self::STATUS_PREFIX . $job_id, $status_data);
    }
    
    /**
     * Get job status
     * 
     * @param string $job_id Job ID
     * @return array|false Job status or false if not found
     */
    public static function get_job_status($job_id) {
        return get_option(self::STATUS_PREFIX . $job_id, false);
    }
    
    /**
     * AJAX handler for getting job status
     */
    public static function ajax_get_job_status() {
        check_ajax_referer('hvac_ajax_nonce', 'nonce');
        
        if (!current_user_can('hvac_master_trainer')) {
            wp_send_json_error('Insufficient permissions');
        }
        
        $job_id = sanitize_text_field($_POST['job_id']);
        $status = self::get_job_status($job_id);
        
        if ($status === false) {
            wp_send_json_error('Job not found');
        }
        
        wp_send_json_success($status);
    }
    
    /**
     * AJAX handler for canceling jobs
     */
    public static function ajax_cancel_job() {
        check_ajax_referer('hvac_ajax_nonce', 'nonce');
        
        if (!current_user_can('hvac_master_trainer')) {
            wp_send_json_error('Insufficient permissions');
        }
        
        $job_id = sanitize_text_field($_POST['job_id']);
        
        // Remove from queue
        $queue = get_option(self::QUEUE_OPTION, []);
        $queue = array_filter($queue, function($job) use ($job_id) {
            return $job['id'] !== $job_id;
        });
        update_option(self::QUEUE_OPTION, array_values($queue));
        
        // Update status
        self::update_job_status($job_id, 'cancelled', 'Job cancelled by user');
        
        wp_send_json_success('Job cancelled');
    }
    
    /**
     * Get queue statistics
     * 
     * @return array Queue stats
     */
    public static function get_queue_stats() {
        $queue = get_option(self::QUEUE_OPTION, []);
        
        $stats = [
            'total' => count($queue),
            'by_status' => [],
            'by_type' => []
        ];
        
        foreach ($queue as $job) {
            $status = $job['status'] ?? 'unknown';
            $type = $job['type'] ?? 'unknown';
            
            $stats['by_status'][$status] = ($stats['by_status'][$status] ?? 0) + 1;
            $stats['by_type'][$type] = ($stats['by_type'][$type] ?? 0) + 1;
        }
        
        return $stats;
    }
}