<?php

/**
 * VMPFence Scan Metrics Tracker
 * 
 * Tracks scan performance, timing, and provides comprehensive metrics
 * 
 * @package VMPFence
 * @subpackage Security
 * @since 1.0.0
 */

if (!defined('ABSPATH')) {
    exit; // Exit if accessed directly
}

class VMPFence_Scan_Metrics {
    
    private $start_time;
    private $end_time;
    private $scan_stats = [];
    private $performance_data = [];
    private $memory_usage = [];
    private $file_processing_times = [];
    
    public function __construct() {
        $this->init_metrics();
    }
    
    /**
     * Initialize metrics tracking
     * Required by roadmap for performance monitoring
     */
    private function init_metrics() {
        $this->scan_stats = [
            'files_scanned' => 0,
            'directories_processed' => 0,
            'threats_detected' => 0,
            'false_positives_avoided' => 0,
            'exclusions_applied' => 0,
            'integrity_checks' => 0,
            'cache_hits' => 0,
            'cache_misses' => 0,
            'scan_errors' => 0,
            'files_skipped' => 0
        ];
        
        $this->performance_data = [
            'total_duration' => 0,
            'avg_file_processing_time' => 0,
            'memory_peak' => 0,
            'memory_avg' => 0,
            'files_per_second' => 0,
            'cpu_usage_samples' => [],
            'io_operations' => 0
        ];
        
        $this->memory_usage = [];
        $this->file_processing_times = [];
    }
    
    /**
     * Start tracking scan progress
     * Required by roadmap: track_scan_progress() method
     */
    public function track_scan_progress($total_files = 0) {
        $this->start_time = microtime(true);
        $this->scan_stats['total_files'] = $total_files;
        $this->scan_stats['scan_started'] = current_time('mysql');
        
        // Initialize memory tracking
        $this->memory_usage[] = [
            'time' => microtime(true),
            'memory' => memory_get_usage(true),
            'peak' => memory_get_peak_usage(true)
        ];
        
        // $this->log_metric('INFO', 'Scan progress tracking started', [
        //     'total_files' => $total_files,
        //     'start_time' => $this->start_time,
        //     'initial_memory' => memory_get_usage(true)
        // ]);
    }
    
    /**
     * Update scan progress with file processing
     * Required by roadmap for real-time progress updates
     */
    public function update_file_progress($file_path, $processing_time, $result) {
        $this->scan_stats['files_scanned']++;
        $this->file_processing_times[] = $processing_time;
        
        // Track memory usage
        $current_memory = memory_get_usage(true);
        $this->memory_usage[] = [
            'time' => microtime(true),
            'memory' => $current_memory,
            'peak' => memory_get_peak_usage(true),
            'file' => basename($file_path)
        ];
        
        // Update performance metrics
        if ($result === 'threat_detected') {
            $this->scan_stats['threats_detected']++;
        } elseif ($result === 'excluded') {
            $this->scan_stats['exclusions_applied']++;
            $this->scan_stats['false_positives_avoided']++;
        } elseif ($result === 'skipped') {
            $this->scan_stats['files_skipped']++;
        } elseif ($result === 'integrity_verified') {
            $this->scan_stats['integrity_checks']++;
        } elseif ($result === 'error') {
            $this->scan_stats['scan_errors']++;
        }
        
        // Log progress every 100 files
        if ($this->scan_stats['files_scanned'] % 100 === 0) {
            $this->log_progress_update();
        }
    }
    
    /**
     * Update directory processing metrics
     * Required for comprehensive scan tracking
     */
    public function update_directory_progress($directory_path, $file_count) {
        $this->scan_stats['directories_processed']++;
        
        // $this->log_metric('DEBUG', 'Directory processed', [
        //     'directory' => $directory_path,
        //     'files_found' => $file_count,
        //     'total_dirs' => $this->scan_stats['directories_processed']
        // ]);
    }
    
    /**
     * Track cache performance
     * Required for integrity checker performance monitoring
     */
    public function track_cache_performance($cache_type, $hit = true) {
        if ($hit) {
            $this->scan_stats['cache_hits']++;
        } else {
            $this->scan_stats['cache_misses']++;
        }
        
        // Calculate cache hit rate
        $total_cache_ops = $this->scan_stats['cache_hits'] + $this->scan_stats['cache_misses'];
        $hit_rate = $total_cache_ops > 0 ? ($this->scan_stats['cache_hits'] / $total_cache_ops) * 100 : 0;
        
        $this->performance_data['cache_hit_rate'] = round($hit_rate, 2);
    }
    
    /**
     * Measure performance metrics
     * Required by roadmap: measure_performance() method
     */
    public function measure_performance() {
        if (!$this->start_time) {
            return false;
        }
        
        $current_time = microtime(true);
        $elapsed_time = $current_time - $this->start_time;
        
        // Calculate files per second
        if ($elapsed_time > 0 && $this->scan_stats['files_scanned'] > 0) {
            $this->performance_data['files_per_second'] = round($this->scan_stats['files_scanned'] / $elapsed_time, 2);
        }
        
        // Calculate average file processing time
        if (!empty($this->file_processing_times)) {
            $this->performance_data['avg_file_processing_time'] = round(array_sum($this->file_processing_times) / count($this->file_processing_times), 6);
        }
        
        // Memory analysis
        if (!empty($this->memory_usage)) {
            $memory_values = array_column($this->memory_usage, 'memory');
            $this->performance_data['memory_peak'] = max($memory_values);
            $this->performance_data['memory_avg'] = round(array_sum($memory_values) / count($memory_values));
            $this->performance_data['memory_current'] = end($memory_values);
        }
        
        // Update total duration
        $this->performance_data['total_duration'] = round($elapsed_time, 2);
        
        return $this->performance_data;
    }
    
    /**
     * Generate comprehensive metrics report
     * Required by roadmap: generate_metrics_report() method
     */
    public function generate_metrics_report() {
        $this->end_time = microtime(true);
        $final_performance = $this->measure_performance();
        
        $report = [
            'scan_summary' => [
                'scan_id' => uniqid('vmpfence_scan_'),
                'started' => $this->scan_stats['scan_started'],
                'completed' => current_time('mysql'),
                'duration_seconds' => $final_performance['total_duration'],
                'duration_formatted' => $this->format_duration($final_performance['total_duration'])
            ],
            'file_statistics' => [
                'total_files_scanned' => $this->scan_stats['files_scanned'],
                'directories_processed' => $this->scan_stats['directories_processed'],
                'files_per_second' => $final_performance['files_per_second'],
                'avg_processing_time_ms' => round($final_performance['avg_file_processing_time'] * 1000, 2),
                'files_skipped' => $this->scan_stats['files_skipped'],
                'scan_errors' => $this->scan_stats['scan_errors']
            ],
            'security_results' => [
                'threats_detected' => $this->scan_stats['threats_detected'],
                'false_positives_avoided' => $this->scan_stats['false_positives_avoided'],
                'exclusions_applied' => $this->scan_stats['exclusions_applied'],
                'integrity_checks_performed' => $this->scan_stats['integrity_checks']
            ],
            'performance_metrics' => [
                'memory_peak_mb' => round($final_performance['memory_peak'] / 1024 / 1024, 2),
                'memory_avg_mb' => round($final_performance['memory_avg'] / 1024 / 1024, 2),
                'memory_current_mb' => round($final_performance['memory_current'] / 1024 / 1024, 2),
                'cache_hit_rate' => $final_performance['cache_hit_rate'] ?? 0,
                'cache_hits' => $this->scan_stats['cache_hits'],
                'cache_misses' => $this->scan_stats['cache_misses']
            ],
            'efficiency_analysis' => [
                'exclusion_effectiveness' => $this->calculate_exclusion_effectiveness(),
                'scan_efficiency_score' => $this->calculate_efficiency_score(),
                'performance_grade' => $this->get_performance_grade()
            ]
        ];
        
        // Log comprehensive report
        // $this->log_metric('INFO', 'Scan metrics report generated', $report);
        
        return $report;
    }
    
    /**
     * Calculate exclusion system effectiveness
     * Measures how well Step 6 exclusions are working
     */
    private function calculate_exclusion_effectiveness() {
        $total_processed = $this->scan_stats['files_scanned'] + $this->scan_stats['files_skipped'];
        
        if ($total_processed === 0) {
            return 0;
        }
        
        $exclusion_rate = ($this->scan_stats['exclusions_applied'] / $total_processed) * 100;
        
        return [
            'exclusion_rate_percent' => round($exclusion_rate, 2),
            'false_positives_prevented' => $this->scan_stats['false_positives_avoided'],
            'effectiveness_rating' => $this->get_exclusion_rating($exclusion_rate)
        ];
    }
    
    /**
     * Calculate overall scan efficiency score
     * Comprehensive performance evaluation
     */
    private function calculate_efficiency_score() {
        $score = 100;
        
        // Deduct points for slow performance
        if ($this->performance_data['files_per_second'] < 50) {
            $score -= 10;
        } elseif ($this->performance_data['files_per_second'] < 100) {
            $score -= 5;
        }
        
        // Deduct points for high memory usage
        $memory_mb = $this->performance_data['memory_peak'] / 1024 / 1024;
        if ($memory_mb > 256) {
            $score -= 15;
        } elseif ($memory_mb > 128) {
            $score -= 10;
        }
        
        // Deduct points for low cache hit rate
        $cache_hit_rate = $this->performance_data['cache_hit_rate'] ?? 0;
        if ($cache_hit_rate < 70) {
            $score -= 10;
        } elseif ($cache_hit_rate < 85) {
            $score -= 5;
        }
        
        // Deduct points for errors
        if ($this->scan_stats['scan_errors'] > 0) {
            $score -= min(20, $this->scan_stats['scan_errors'] * 2);
        }
        
        return max(0, min(100, $score));
    }
    
    /**
     * Get performance grade based on efficiency score
     */
    private function get_performance_grade() {
        $score = $this->calculate_efficiency_score();
        
        if ($score >= 90) return 'A+';
        if ($score >= 85) return 'A';
        if ($score >= 80) return 'B+';
        if ($score >= 75) return 'B';
        if ($score >= 70) return 'C+';
        if ($score >= 65) return 'C';
        if ($score >= 60) return 'D+';
        if ($score >= 55) return 'D';
        return 'F';
    }
    
    /**
     * Get exclusion system effectiveness rating
     */
    private function get_exclusion_rating($exclusion_rate) {
        if ($exclusion_rate >= 80) return 'Excellent';
        if ($exclusion_rate >= 70) return 'Very Good';
        if ($exclusion_rate >= 60) return 'Good';
        if ($exclusion_rate >= 50) return 'Fair';
        if ($exclusion_rate >= 30) return 'Poor';
        return 'Very Poor';
    }
    
    /**
     * Format duration for human readability
     * @since 1.0.0
     * @since 2.1.1 Improved formatting logic
     */
    private function format_duration($seconds) {
        if ($seconds < 60) {
            return round($seconds, 2) . ' seconds';
        } elseif ($seconds < 3600) {
            $minutes = floor($seconds / 60);
            $secs = $seconds % 60;
            return sprintf('%d minutes, %.2f seconds', (int)$minutes, $secs);
        } else {
            $hours = floor($seconds / 3600);
            $minutes = floor(($seconds % 3600) / 60);
            $secs = $seconds % 60;
            return sprintf('%d hours, %d minutes, %.2f seconds', (int)$hours, (int)$minutes, $secs);
        }
    }
    
    /**
     * Log progress update
     * Internal method for progress logging
     */
    private function log_progress_update() {
        $current_performance = $this->measure_performance();
        
        $progress_data = [
            'files_processed' => $this->scan_stats['files_scanned'],
            'current_speed' => $current_performance['files_per_second'] ?? 0,
            'memory_usage_mb' => round(memory_get_usage(true) / 1024 / 1024, 2),
            'threats_found' => $this->scan_stats['threats_detected'],
            'exclusions_applied' => $this->scan_stats['exclusions_applied']
        ];
        
        // $this->log_metric('INFO', 'Scan progress update', $progress_data);
    }
    
    /**
     * Log metric data
     * Centralized logging for all metrics
     */
    private function log_metric($level, $message, $data = []) {
        $timestamp = gmdate('Y-m-d H:i:s');
        $log_entry = sprintf(
            "[%s] [%s] [METRICS] %s: %s\n",
            $timestamp,
            $level,
            $message,
            !empty($data) ? json_encode($data, JSON_PRETTY_PRINT) : 'N/A'
        );
        
        // Write to metrics log file
        $log_file = plugin_dir_path(__FILE__) . 'vmpfence-metrics.log';
        file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
    }
    
    /**
     * Reset metrics for new scan
     * Allows reusing metrics instance
     */
    public function reset_metrics() {
        $this->start_time = null;
        $this->end_time = null;
        $this->init_metrics();
        $this->memory_usage = [];
        $this->file_processing_times = [];
        
        // $this->log_metric('INFO', 'Metrics reset for new scan');
    }
    
    /**
     * Export metrics data for analysis
     * Useful for performance analysis and optimization
     */
    public function export_metrics_data() {
        return [
            'scan_stats' => $this->scan_stats,
            'performance_data' => $this->performance_data,
            'memory_usage_timeline' => $this->memory_usage,
            'file_processing_times' => $this->file_processing_times,
            'metadata' => [
                'php_version' => PHP_VERSION,
                'wordpress_version' => get_bloginfo('version'),
                'vmpfence_version' => VMPFENCE_VERSION,
                'server_info' => php_uname(),
                'memory_limit' => ini_get('memory_limit'),
                'max_execution_time' => ini_get('max_execution_time')
            ]
        ];
    }
}
