<?php
/**
 * Server Protection Detector
 *
 * Detects server-level security protections (Cloudflare, fail2ban) and provides
 * recommendations for optimal security configuration.
 *
 * @package     WPUltimateSecurity\UltimateSecurity\Modules\Monitoring
 * @since       2.1.0
 */

declare(strict_types=1);

namespace WPUltimateSecurity\UltimateSecurity\Modules\Monitoring;

/**
 * Detects server-level security protections.
 *
 * This class checks for common server-level security measures like Cloudflare
 * and fail2ban, providing recommendations for optimal plugin configuration.
 *
 * @since 2.1.0
 */
class ServerProtectionDetector
{
    /**
     * Detect all server-level protections.
     *
     * @since 2.1.0
     *
     * @return array{cloudflare: bool, fail2ban: bool} Detection results.
     */
    public static function detect(): array
    {
        return [
            'cloudflare' => self::detect_cloudflare(),
            'fail2ban'   => self::detect_fail2ban(),
        ];
    }

    /**
     * Check if site is behind Cloudflare.
     *
     * Detects Cloudflare by checking for the CF-Ray or CF-Connecting-IP headers
     * that Cloudflare adds to all requests passing through their network.
     *
     * @since 2.1.0
     *
     * @return bool True if Cloudflare headers are detected.
     */
    public static function detect_cloudflare(): bool
    {
        // phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Read-only check for header existence
        return isset($_SERVER['HTTP_CF_RAY'])
            || isset($_SERVER['HTTP_CF_CONNECTING_IP']);
        // phpcs:enable
    }

    /**
     * Check if fail2ban is running on the server.
     *
     * Attempts to detect the fail2ban-server process using pgrep.
     * Fails gracefully if shell_exec is disabled or unavailable.
     *
     * @since 2.1.0
     *
     * @return bool True if fail2ban process is detected.
     */
    public static function detect_fail2ban(): bool
    {
        // Skip if shell_exec function doesn't exist
        if (!function_exists('shell_exec')) {
            return false;
        }

        // Check if shell_exec is in disabled_functions
        $disabled_functions = ini_get('disable_functions');
        if ($disabled_functions !== false) {
            $disabled = explode(',', $disabled_functions);
            $disabled = array_map('trim', $disabled);
            if (in_array('shell_exec', $disabled, true)) {
                return false;
            }
        }

        // Try to detect fail2ban process
        // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.system_calls_shell_exec -- Required for process detection
        $result = @shell_exec('pgrep -x fail2ban-server 2>/dev/null');

        return !empty(trim($result ?? ''));
    }

    /**
     * Get recommendations based on detected protections.
     *
     * Returns an array of recommendation objects that can be displayed
     * to users to help them understand their security posture.
     *
     * @since 2.1.0
     *
     * @return array Array of recommendation objects with type, title, message, and icon.
     */
    public static function get_recommendations(): array
    {
        $detected        = self::detect();
        $recommendations = [];

        if ($detected['cloudflare']) {
            $recommendations[] = [
                'type'    => 'cloudflare',
                'title'   => __('Cloudflare Protection Detected', 'ultimate-security'),
                'message' => __('Your site is behind Cloudflare. Rate limiting and bot protection are handled at the edge before requests reach WordPress.', 'ultimate-security'),
                'icon'    => 'cloud',
            ];
        }

        if ($detected['fail2ban']) {
            $recommendations[] = [
                'type'    => 'fail2ban',
                'title'   => __('fail2ban Protection Detected', 'ultimate-security'),
                'message' => __('Server-level brute force protection is active. Login Limit provides additional user-aware protection but is optional.', 'ultimate-security'),
                'icon'    => 'server',
            ];
        }

        return $recommendations;
    }

    /**
     * Get full status for REST API response.
     *
     * Combines detection results with recommendations for a complete
     * server protection status report.
     *
     * @since 2.1.0
     *
     * @return array{detected: array, has_protection: bool, recommendations: array} Full status data.
     */
    public static function get_status(): array
    {
        $detected = self::detect();

        return [
            'detected'        => $detected,
            'has_protection'  => $detected['cloudflare'] || $detected['fail2ban'],
            'recommendations' => self::get_recommendations(),
        ];
    }
}
