<?php
/**
 * CVE Sync Class - Sync CVE Vulnerabilities from API
 *
 * @package VMPFence
 * @since 1.0.0
 */

// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

/**
 * CVE Sync Class (matches Signature_Sync pattern)
 *
 * @since 1.0.0
 */
class VMPFence_CVE_Sync {

    /**
     * Get JSON file path
     *
     * @since 1.0.0
     * @return string
     */
    public static function get_json_file_path() {
        return VMPFENCE_PLUGIN_DIR . 'data/cve-vulnerabilities.json';
    }

    /**
     * Sync CVE vulnerabilities from API server (PRIMARY METHOD)
     *
     * @since 1.0.0
     * @return array Result with 'success', 'imported', 'errors', 'license_tier', 'version' keys
     */
    public static function sync_from_api() {
        // Get API key
        $api_key = VMPFence_Config::get('central_api_key');
        
        if (empty($api_key)) {
            return array(
                'success' => false,
                'imported' => 0,
                'errors' => array('API key not configured'),
                'license_tier' => 'unknown',
                'version' => 'unknown'
            );
        }
        
        // Initialize API client
        require_once VMPFENCE_PLUGIN_DIR . 'lib/class-api-client.php';
        $api_client = new VMPFence_API_Client();
        
        // Fetch CVE vulnerabilities from API
        $response = $api_client->get_cve_vulnerabilities($api_key);
        
        if (is_wp_error($response)) {
            return array(
                'success' => false,
                'imported' => 0,
                'errors' => array('API error: ' . $response->get_error_message()),
                'license_tier' => 'unknown',
                'version' => 'unknown'
            );
        }
        
        // Extract vulnerabilities and metadata
        // API returns 'cves' key, not 'vulnerabilities'
        $vulnerabilities = isset($response['cves']) ? $response['cves'] : array();
        $version = isset($response['version']) ? $response['version'] : 'unknown';
        // CVE endpoint doesn't return tier info - use current license instead of defaulting to 'free'
        $license_tier = VMPFence_License::get_license_type();
        $last_updated = isset($response['last_updated']) ? $response['last_updated'] : current_time('mysql');
        
        if (empty($vulnerabilities)) {
            return array(
                'success' => true,
                'imported' => 0,
                'errors' => array(),
                'license_tier' => $license_tier,
                'version' => $version
            );
        }
        
        // Save vulnerabilities to JSON file
        $result = self::save_vulnerabilities_to_file($vulnerabilities, $version, $license_tier, $last_updated);
        
        if ($result['success']) {
            // Update WordPress options metadata
            update_option('vmpfence_cve_last_sync', current_time('mysql'));
            update_option('vmpfence_cve_count', count($vulnerabilities));
            update_option('vmpfence_cve_version', $version);
            
            // DON'T update license from CVE sync - CVE endpoint doesn't return tier information
            // Only firewall/rules endpoint returns license_tier and should update it
            
            VMPFence_Secure_Logger::log('info', 'CVE: Synced vulnerabilities', ['count' => count($vulnerabilities), 'version' => $version, 'license_tier' => $license_tier]);
        }
        
        return array(
            'success' => $result['success'],
            'imported' => count($vulnerabilities),
            'errors' => $result['errors'],
            'license_tier' => $license_tier,
            'version' => $version,
            'total_available' => count($vulnerabilities)
        );
    }
    
    /**
     * Save CVE vulnerabilities to JSON file
     *
     * @since 1.0.0
     * @param array $vulnerabilities Vulnerabilities array from API
     * @param string $version CVE database version
     * @param string $tier License tier
     * @param string $last_updated Last updated timestamp
     * @return array Result with 'success' and 'errors' keys
     */
    private static function save_vulnerabilities_to_file($vulnerabilities, $version, $tier, $last_updated) {
        $file_path = self::get_json_file_path();
        
        // Prepare data structure
        $data = array(
            'version' => $version,
            'last_updated' => $last_updated,
            'tier' => $tier,
            'total_cves' => count($vulnerabilities),
            'vulnerabilities' => $vulnerabilities
        );
        
        // Encode to JSON
        $json_content = wp_json_encode($data, JSON_PRETTY_PRINT);
        
        if ($json_content === false) {
            return array(
                'success' => false,
                'errors' => array('Failed to encode CVE vulnerabilities to JSON')
            );
        }
        
        // Write to file
        $bytes_written = file_put_contents($file_path, $json_content);
        
        if ($bytes_written === false) {
            return array(
                'success' => false,
                'errors' => array('Failed to write CVE vulnerabilities to file: ' . $file_path)
            );
        }
        
        return array(
            'success' => true,
            'errors' => array()
        );
    }
    
    /**
     * Get CVE count from JSON file
     *
     * @since 1.0.0
     * @return int Number of CVE vulnerabilities
     */
    public static function get_cve_count() {
        $file_path = self::get_json_file_path();
        
        if (!file_exists($file_path)) {
            return 0;
        }
        
        $json_content = file_get_contents($file_path);
        if ($json_content === false) {
            return 0;
        }
        
        $data = json_decode($json_content, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            return 0;
        }
        
        if (isset($data['total_cves'])) {
            return intval($data['total_cves']);
        }
        
        if (isset($data['vulnerabilities']) && is_array($data['vulnerabilities'])) {
            return count($data['vulnerabilities']);
        }
        
        return 0;
    }
    
    /**
     * Get CVE database version from JSON file
     *
     * @since 1.0.0
     * @return string Version string
     */
    public static function get_cve_version() {
        $file_path = self::get_json_file_path();
        
        if (!file_exists($file_path)) {
            return 'unknown';
        }
        
        $json_content = file_get_contents($file_path);
        if ($json_content === false) {
            return 'unknown';
        }
        
        $data = json_decode($json_content, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            return 'unknown';
        }
        
        return isset($data['version']) ? $data['version'] : 'unknown';
    }
    
    /**
     * Validate CVE file integrity
     *
     * @since 1.0.0
     * @return array Result with 'valid' and 'errors' keys
     */
    public static function validate_cve_file() {
        $file_path = self::get_json_file_path();
        $errors = array();
        
        // Check file exists
        if (!file_exists($file_path)) {
            $errors[] = 'CVE vulnerabilities file not found';
            return array('valid' => false, 'errors' => $errors);
        }
        
        // Check file is readable
        if (!is_readable($file_path)) {
            $errors[] = 'CVE vulnerabilities file is not readable';
            return array('valid' => false, 'errors' => $errors);
        }
        
        // Read and parse JSON
        $json_content = file_get_contents($file_path);
        if ($json_content === false) {
            $errors[] = 'Failed to read CVE vulnerabilities file';
            return array('valid' => false, 'errors' => $errors);
        }
        
        $data = json_decode($json_content, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            $errors[] = 'JSON parse error: ' . json_last_error_msg();
            return array('valid' => false, 'errors' => $errors);
        }
        
        // Validate structure
        if (!isset($data['version'])) {
            $errors[] = 'Missing version field';
        }
        
        if (!isset($data['vulnerabilities']) || !is_array($data['vulnerabilities'])) {
            $errors[] = 'Missing or invalid vulnerabilities array';
        }
        
        return array(
            'valid' => empty($errors),
            'errors' => $errors
        );
    }
    
    /**
     * Get vulnerabilities from JSON file
     *
     * @since 1.0.0
     * @return array Array of CVE vulnerabilities
     */
    public static function get_vulnerabilities() {
        $file_path = self::get_json_file_path();
        
        if (!file_exists($file_path)) {
            return array();
        }
        
        $json_content = file_get_contents($file_path);
        if ($json_content === false) {
            return array();
        }
        
        $data = json_decode($json_content, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            return array();
        }
        
        return isset($data['vulnerabilities']) ? $data['vulnerabilities'] : array();
    }
}
