<?php
/**
 * XML-RPC Guard
 *
 * Optionally disables XML-RPC entirely or rate-limits it.
 * Also removes system.multicall to prevent brute-force amplification.
 *
 * @package GuardianShield
 */

namespace GuardianShield;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class XmlRpcGuard {

	private Logger      $logger;
	private RateLimiter $rate_limiter;

	public function __construct( Logger $logger, RateLimiter $rate_limiter ) {
		$this->logger       = $logger;
		$this->rate_limiter = $rate_limiter;
	}

	public function register_hooks(): void {
		if ( (bool) gs_get_option( 'block_xmlrpc', false ) ) {
			add_filter( 'xmlrpc_enabled', '__return_false' );
			add_action( 'xmlrpc_call', [ $this, 'block_xmlrpc_call' ] );
		} else {
			add_action( 'xmlrpc_call', [ $this, 'rate_limit_xmlrpc' ] );
		}

		add_filter( 'xmlrpc_methods', [ $this, 'disable_multicall' ] );
	}

	public function block_xmlrpc_call( string $method ): void {
		$ip = gs_get_client_ip();
		$this->logger->log_attack( [
			'ip_address'  => $ip,
			'attack_type' => 'xmlrpc_blocked',
			'severity'    => 2,
			'description' => "XML-RPC call blocked: {$method}",
			'blocked'     => 1,
		] );

		wp_die(
			esc_html__( 'XML-RPC is disabled by Guardian Shield.', 'guardian-shield' ),
			esc_html__( '403 Forbidden', 'guardian-shield' ),
			[ 'response' => 403 ]
		);
	}

	public function rate_limit_xmlrpc( string $method ): void {
		$ip      = gs_get_client_ip();
		$allowed = $this->rate_limiter->check_and_record( $ip, 'xmlrpc' );
		if ( ! $allowed ) {
			$this->logger->log_attack( [
				'ip_address'  => $ip,
				'attack_type' => 'xmlrpc_rate_limit',
				'severity'    => 3,
				'description' => "XML-RPC rate limit exceeded: {$method}",
				'blocked'     => 1,
			] );
			http_response_code( 429 );
			exit( 'Too many XML-RPC requests.' );
		}
	}

	public function disable_multicall( array $methods ): array {
		unset( $methods['system.multicall'] );
		return $methods;
	}
}
