<?php
defined('ABSPATH') || exit;

/**
 * Specialized diagnostic scan for test files
 * 
 * @param string $file_path Full path to the test file
 * @return array Detailed diagnosis results
 */
function wpsec_diagnose_test_file($file_path) {
    $results = [];
    $start_time = microtime(true);
    $results['file'] = basename($file_path);
    $results['full_path'] = $file_path;
    $results['file_exists'] = file_exists($file_path);
    $results['file_readable'] = is_readable($file_path);
    
    if (!$results['file_exists'] || !$results['file_readable']) {
        $results['status'] = 'error';
        $results['message'] = 'File does not exist or is not readable';
        return $results;
    }
    
    // Basic file info
    $results['file_size'] = filesize($file_path);
    $results['file_type'] = mime_content_type($file_path);
    $results['file_extension'] = pathinfo($file_path, PATHINFO_EXTENSION);
    $results['file_modified'] = filemtime($file_path);
    
    // Get file content
    $results['file_content_sample'] = substr(file_get_contents($file_path), 0, 500) . '... (truncated)';
    
    // Force scan using all engines
    $results['scan_steps'] = [];
    
    // 1. Check file signatures
    if (function_exists('wpsec_check_file_signatures')) {
        $file_content = file_get_contents($file_path);
        $signature_results = wpsec_check_file_signatures($file_path, $file_content);
        $results['scan_steps']['signatures'] = [
            'ran' => true,
            'detection_count' => count($signature_results),
            'raw_results' => $signature_results
        ];
    } else {
        $results['scan_steps']['signatures'] = ['ran' => false, 'error' => 'Function not found'];
    }
    
    // 2. Check file patterns
    if (function_exists('wpsec_check_file_patterns')) {
        $file_content = file_get_contents($file_path);
        $pattern_results = wpsec_check_file_patterns($file_path, $file_content);
        $results['scan_steps']['patterns'] = [
            'ran' => true,
            'detection_count' => count($pattern_results),
            'raw_results' => $pattern_results
        ];
    } else {
        $results['scan_steps']['patterns'] = ['ran' => false, 'error' => 'Function not found'];
    }
    
    // 3. Check advanced patterns
    if (function_exists('wpsec_get_advanced_definitions') && function_exists('wpsec_scan_file_with_advanced_patterns')) {
        $definitions = wpsec_get_advanced_definitions();
        $advanced_results = [];
        
        if (!empty($definitions['known'])) {
            $known_results = wpsec_scan_file_with_advanced_patterns($file_path, $definitions['known']);
            $results['scan_steps']['advanced_known'] = [
                'ran' => true,
                'detection_count' => count($known_results),
                'raw_results' => $known_results
            ];
            $advanced_results = array_merge($advanced_results, $known_results);
        } else {
            $results['scan_steps']['advanced_known'] = ['ran' => false, 'error' => 'No definitions'];
        }
        
        if (!empty($definitions['potential'])) {
            $potential_results = wpsec_scan_file_with_advanced_patterns($file_path, $definitions['potential']);
            $results['scan_steps']['advanced_potential'] = [
                'ran' => true,
                'detection_count' => count($potential_results),
                'raw_results' => $potential_results
            ];
            $advanced_results = array_merge($advanced_results, $potential_results);
        } else {
            $results['scan_steps']['advanced_potential'] = ['ran' => false, 'error' => 'No definitions'];
        }
    } else {
        $results['scan_steps']['advanced'] = ['ran' => false, 'error' => 'Functions not found'];
    }
    
    // 4. Test the entire pipeline
    if (function_exists('wpsec_scan_single_file')) {
        try {
            // Force skip whitelist check
            $single_file_result = wpsec_scan_single_file($file_path, '', true, true);
            $results['scan_steps']['full_pipeline'] = [
                'ran' => true,
                'detection_count' => is_array($single_file_result) ? count($single_file_result) : 0,
                'raw_results' => $single_file_result
            ];
        } catch (Exception $e) {
            $results['scan_steps']['full_pipeline'] = [
                'ran' => false,
                'error' => $e->getMessage()
            ];
        }
    } else {
        $results['scan_steps']['full_pipeline'] = ['ran' => false, 'error' => 'Function not found'];
    }
    
    // Calculate detection summary
    $all_detections = [];
    foreach ($results['scan_steps'] as $step => $step_results) {
        if (isset($step_results['raw_results']) && is_array($step_results['raw_results']) && !empty($step_results['raw_results'])) {
            foreach ($step_results['raw_results'] as $result) {
                $detection = [
                    'engine' => $step,
                    'details' => $result
                ];
                $all_detections[] = $detection;
            }
        }
    }
    
    // Finalize results
    $results['total_detections'] = count($all_detections);
    $results['all_detections'] = $all_detections;
    $results['duration_ms'] = round((microtime(true) - $start_time) * 1000, 2);
    $results['timestamp'] = time();
    
    return $results;
}

/**
 * Direct scan of a specific file with detailed tracing of each step
 * Bypasses all caches and whitelists
 * 
 * @param string $file_path Full path to file
 * @return array Detailed scan results
 */
/**
 * Direct scan of a specific file with detailed tracing of each step
 * This version is simplified to avoid compatibility issues
 */
function wpsec_scan_file_with_tracing($file_path) {
    $trace = [];
    $trace['start_time'] = microtime(true);
    $trace['file'] = basename($file_path);
    $trace['path'] = $file_path;
    
    // Track if file exists and is readable
    $trace['file_exists'] = file_exists($file_path);
    $trace['is_readable'] = is_readable($file_path);
    
    if (!$trace['file_exists'] || !$trace['is_readable']) {
        $trace['status'] = 'error';
        $trace['message'] = 'File not found or not readable';
        return $trace;
    }
    
    // Get file content
    $trace['step_get_content'] = ['started_at' => microtime(true)];
    try {
        $file_content = file_get_contents($file_path);
        $trace['step_get_content']['status'] = 'success';
        $trace['step_get_content']['size'] = strlen($file_content);
        $trace['step_get_content']['sample'] = substr($file_content, 0, 100) . '... (truncated)';
    } catch (Exception $e) {
        $trace['step_get_content']['status'] = 'error';
        $trace['step_get_content']['error'] = $e->getMessage();
        return $trace;
    }
    $trace['step_get_content']['completed_at'] = microtime(true);
    
    // Run signature engine
    $trace['step_signatures'] = ['started_at' => microtime(true)];
    if (function_exists('wpsec_check_file_signatures')) {
        try {
            $signatures = wpsec_check_file_signatures($file_path, $file_content);
            $trace['step_signatures']['status'] = 'success';
            $trace['step_signatures']['detections'] = is_array($signatures) ? count($signatures) : 0;
            $trace['step_signatures']['results'] = $signatures;
        } catch (Exception $e) {
            $trace['step_signatures']['status'] = 'error';
            $trace['step_signatures']['error'] = $e->getMessage();
        }
    } else {
        $trace['step_signatures']['status'] = 'skipped';
        $trace['step_signatures']['reason'] = 'Function not available';
    }
    $trace['step_signatures']['completed_at'] = microtime(true);
    
    // Run pattern engine
    $trace['step_patterns'] = ['started_at' => microtime(true)];
    if (function_exists('wpsec_check_file_patterns')) {
        try {
            $patterns = wpsec_check_file_patterns($file_path, $file_content);
            $trace['step_patterns']['status'] = 'success';
            $trace['step_patterns']['detections'] = is_array($patterns) ? count($patterns) : 0;
            $trace['step_patterns']['results'] = $patterns;
        } catch (Exception $e) {
            $trace['step_patterns']['status'] = 'error';
            $trace['step_patterns']['error'] = $e->getMessage();
        }
    } else {
        $trace['step_patterns']['status'] = 'skipped';
        $trace['step_patterns']['reason'] = 'Function not available';
    }
    $trace['step_patterns']['completed_at'] = microtime(true);
    
    // Run heuristic engine if available
    $trace['step_heuristics'] = ['started_at' => microtime(true)];
    if (function_exists('wpsec_check_file_heuristics')) {
        try {
            $heuristics = wpsec_check_file_heuristics($file_path, $file_content);
            $trace['step_heuristics']['status'] = 'success';
            $trace['step_heuristics']['detections'] = is_array($heuristics) ? count($heuristics) : 0;
            $trace['step_heuristics']['results'] = $heuristics;
        } catch (Exception $e) {
            $trace['step_heuristics']['status'] = 'error';
            $trace['step_heuristics']['error'] = $e->getMessage();
        }
    } else {
        $trace['step_heuristics']['status'] = 'skipped';
        $trace['step_heuristics']['reason'] = 'Function not available';
    }
    $trace['step_heuristics']['completed_at'] = microtime(true);
    
    // Run anomaly engine if available
    $trace['step_anomalies'] = ['started_at' => microtime(true)];
    if (function_exists('wpsec_check_file_anomalies')) {
        try {
            $anomalies = wpsec_check_file_anomalies($file_path, $file_content);
            $trace['step_anomalies']['status'] = 'success';
            $trace['step_anomalies']['detections'] = is_array($anomalies) ? count($anomalies) : 0;
            $trace['step_anomalies']['results'] = $anomalies;
        } catch (Exception $e) {
            $trace['step_anomalies']['status'] = 'error';
            $trace['step_anomalies']['error'] = $e->getMessage();
        }
    } else {
        $trace['step_anomalies']['status'] = 'skipped';
        $trace['step_anomalies']['reason'] = 'Function not available';
    }
    $trace['step_anomalies']['completed_at'] = microtime(true);
    
    // Run advanced scan engine
    $trace['step_advanced'] = ['started_at' => microtime(true)];
    if (function_exists('wpsec_get_advanced_definitions') && function_exists('wpsec_scan_file_with_advanced_patterns')) {
        try {
            $definitions = wpsec_get_advanced_definitions();
            $trace['step_advanced']['definitions_loaded'] = !empty($definitions);
            
            $advanced_results = [];
            if (!empty($definitions['known']) && is_array($definitions['known'])) {
                $known_results = wpsec_scan_file_with_advanced_patterns($file_path, $definitions['known']);
                $trace['step_advanced']['known_detections'] = is_array($known_results) ? count($known_results) : 0;
                $trace['step_advanced']['known_results'] = $known_results;
                if (is_array($known_results)) {
                    $advanced_results = array_merge($advanced_results, $known_results);
                }
            }
            
            if (!empty($definitions['potential']) && is_array($definitions['potential'])) {
                $potential_results = wpsec_scan_file_with_advanced_patterns($file_path, $definitions['potential']);
                $trace['step_advanced']['potential_detections'] = is_array($potential_results) ? count($potential_results) : 0;
                $trace['step_advanced']['potential_results'] = $potential_results;
                if (is_array($potential_results)) {
                    $advanced_results = array_merge($advanced_results, $potential_results);
                }
            }
            
            $trace['step_advanced']['status'] = 'success';
            $trace['step_advanced']['total_detections'] = count($advanced_results);
        } catch (Exception $e) {
            $trace['step_advanced']['status'] = 'error';
            $trace['step_advanced']['error'] = $e->getMessage();
        }
    } else {
        $trace['step_advanced']['status'] = 'skipped';
        $trace['step_advanced']['reason'] = 'Functions not available';
    }
    $trace['step_advanced']['completed_at'] = microtime(true);
    
    // Calculate timing for each step
    foreach ($trace as $key => &$step) {
        if (is_array($step) && isset($step['started_at']) && isset($step['completed_at'])) {
            $step['duration_ms'] = round(($step['completed_at'] - $step['started_at']) * 1000, 2);
        }
    }
    unset($step); // Break the reference with the last element
    
    // Finalize the trace
    $trace['end_time'] = microtime(true);
    $trace['total_duration_ms'] = round(($trace['end_time'] - $trace['start_time']) * 1000, 2);
    
    return $trace;
}
