<?php
/**
 * WAF Rule Importer - Import Rules from JSON
 *
 * @package VMPFence
 * @since 2.0.0
 */

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

/**
 * WAF Rule Importer Class
 *
 * @since 2.0.0
 */
class VMPFence_Rule_Importer {

    /**
     * Get JSON file path
     *
     * @since 2.0.0
     * @return string
     */
    public static function get_json_file_path() {
        return VMPFENCE_PLUGIN_DIR . 'firewall/rules/waf-rules.json';
    }

    /**
     * Get expected rule count from JSON metadata
     *
     * @since 2.0.0
     * @return int
     */
    public static function get_expected_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;
        }

        // Return total_rules if exists, otherwise count rules array
        if (isset($data['total_rules'])) {
            return intval($data['total_rules']);
        }

        if (isset($data['rules']) && is_array($data['rules'])) {
            return count($data['rules']);
        }

        return 0;
    }

    /**
     * Verify rules count matches expected
     *
     * @since 2.0.0
     * @param int|null $expected_count Expected count (null = auto-detect from JSON)
     * @return bool
     */
    public static function verify_rules_count($expected_count = null) {
        global $wpdb;
        $table_name = $wpdb->prefix . 'vmpfence_waf_rules';

        // Get expected count from JSON if not provided
        if ($expected_count === null) {
            $expected_count = self::get_expected_count();
        }

        if ($expected_count === 0) {
            return true; // No verification needed
        }

        $actual_count = $wpdb->get_var("SELECT COUNT(*) FROM $table_name");

        return intval($actual_count) >= $expected_count;
    }

    /**
     * Validate JSON structure
     *
     * @since 2.0.0
     * @param array $data Decoded JSON data
     * @return array Result array with 'valid' and 'errors' keys
     */
    public static function validate_json_structure($data) {
        $errors = array();

        // Check top-level fields
        if (!isset($data['version'])) {
            $errors[] = 'Missing version field';
        }

        if (!isset($data['rules']) || !is_array($data['rules'])) {
            $errors[] = 'Missing or invalid rules array';
            return array('valid' => false, 'errors' => $errors);
        }

        // Validate each rule
        $required_fields = array('rule_id', 'category', 'severity', 'pattern', 'description', 'score', 'action');
        
        foreach ($data['rules'] as $index => $rule) {
            if (!is_array($rule)) {
                $errors[] = "Rule at index $index is not an array";
                continue;
            }

            foreach ($required_fields as $field) {
                if (!isset($rule[$field])) {
                    $errors[] = "Rule at index $index missing required field: $field";
                }
            }

            // Validate pattern is valid regex
            if (isset($rule['pattern'])) {
                set_error_handler(function() {}, E_WARNING);
                $valid = @preg_match($rule['pattern'], '') !== false;
                restore_error_handler();

                if (!$valid) {
                    $errors[] = "Rule at index $index has invalid regex pattern: {$rule['rule_id']}";
                }
            }
        }

        return array(
            'valid' => empty($errors),
            'errors' => $errors
        );
    }

    /**
     * Import rules from array
     *
     * @since 2.0.0
     * @param array $rules Rules array
     * @return array Result with 'imported', 'failed', 'errors' keys
     */
    public static function import_rules($rules) {
        $imported = 0;
        $failed = 0;
        $errors = array();

        foreach ($rules as $rule) {
            // Add default values
            if (!isset($rule['enabled'])) {
                $rule['enabled'] = 1;
            }
            if (!isset($rule['version'])) {
                $rule['version'] = '1.0';
            }
            if (!isset($rule['whitelist'])) {
                $rule['whitelist'] = 0;
            }

            $result = VMPFence_WAF_Rule::add_rule($rule);

            if ($result) {
                $imported++;
            } else {
                $failed++;
                $errors[] = "Failed to import rule: {$rule['rule_id']}";
            }
        }

        return array(
            'imported' => $imported,
            'failed' => $failed,
            'errors' => $errors
        );
    }

    /**
     * Import rules from JSON file
     *
     * @since 2.0.0
     * @param string|null $file_path Optional file path (default: waf-rules.json)
     * @return array Result with 'success', 'imported', 'failed', 'errors' keys
     */
    public static function import_from_json($file_path = null) {
        if ($file_path === null) {
            $file_path = self::get_json_file_path();
        }

        // Check if file exists
        if (!file_exists($file_path)) {
            return array(
                'success' => false,
                'imported' => 0,
                'failed' => 0,
                'errors' => array('JSON file not found: ' . $file_path)
            );
        }

        // Read file
        $json_content = file_get_contents($file_path);
        if ($json_content === false) {
            return array(
                'success' => false,
                'imported' => 0,
                'failed' => 0,
                'errors' => array('Failed to read JSON file')
            );
        }

        // Parse JSON
        $data = json_decode($json_content, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            return array(
                'success' => false,
                'imported' => 0,
                'failed' => 0,
                'errors' => array('JSON parse error: ' . json_last_error_msg())
            );
        }

        // Validate structure
        $validation = self::validate_json_structure($data);
        if (!$validation['valid']) {
            return array(
                'success' => false,
                'imported' => 0,
                'failed' => 0,
                'errors' => $validation['errors']
            );
        }

        // Import rules
        $result = self::import_rules($data['rules']);

        return array(
            'success' => $result['imported'] > 0,
            'imported' => $result['imported'],
            'failed' => $result['failed'],
            'errors' => $result['errors']
        );
    }

    /**
     * Retry import with exponential backoff
     *
     * @since 2.0.0
     * @param int $max_retries Maximum retry attempts
     * @return array Final result array
     */
    public static function retry_import($max_retries = 3) {
        $attempt = 0;
        $last_result = null;

        while ($attempt < $max_retries) {
            $attempt++;

            // Clear existing rules before retry to prevent duplicates
            if (VMPFence_WAF_Rule::has_default_rules()) {
                VMPFence_WAF_Rule::delete_all_rules();
            }

            // Try import
            $result = self::import_from_json();

            if ($result['success']) {
                // Verify count
                if (self::verify_rules_count()) {
                    return $result;
                }
            }

            $last_result = $result;

            // Wait before retry (2 seconds)
            if ($attempt < $max_retries) {
                sleep(2);
            }
        }

        return $last_result ? $last_result : array(
            'success' => false,
            'imported' => 0,
            'failed' => 0,
            'errors' => array('Max retries exceeded')
        );
    }
}
