<?php
/**
 * @package Hafenstudios\Wellenbrecher
 */

namespace Hafenstudios\Wellenbrecher\Support;

defined( 'ABSPATH' ) || exit;

/**
 * Context-Fabrik fuer den Server-Snapshot (WB10, Context-Doku).
 *
 * Verbindliche Normalisierung: HTTP_*-Header werden zu Kleinbuchstaben-
 * Schluesseln OHNE http_-Praefix (HTTP_ACCEPT_LANGUAGE -> accept_language,
 * HTTP_USER_AGENT -> user_agent, HTTP_SEC_FETCH_SITE -> sec_fetch_site),
 * SERVER_PROTOCOL -> protocol, dazu request_time (Unix-Sekunden).
 *
 * 'remote_addr' ist die via IpHasher::client_ip() mit dem Setting
 * proxy.trusted_header AUFGELOESTE Client-IP. Die Regeln lesen nur das
 * Ergebnis und versuchen die Proxy-Aufloesung nie selbst (sonst waere das
 * Proxy-Setting tot und Rate-Limit/Wiederholungstaeter wuerden hinter
 * Proxies die Proxy-IP hashen).
 */
class RequestSnapshot {

	protected IpHasher $hasher;

	/**
	 * @param IpHasher $hasher IP-Helfer fuer die Client-IP-Aufloesung.
	 */
	public function __construct( IpHasher $hasher ) {
		$this->hasher = $hasher;
	}

	/**
	 * Baut den normalisierten Server-Snapshot aus $_SERVER.
	 *
	 * @param array<string, mixed> $server         Roher $_SERVER-Inhalt.
	 * @param string               $trusted_header Setting proxy.trusted_header (leer = REMOTE_ADDR).
	 * @return array<string, mixed> Snapshot mit Kleinbuchstaben-Schluesseln.
	 */
	public function build( array $server, string $trusted_header = '' ): array {
		$out = array();

		foreach ( $server as $key => $value ) {
			if ( ! is_scalar( $value ) || ! is_string( $key ) ) {
				continue;
			}
			if ( 0 === strpos( $key, 'HTTP_' ) ) {
				$out[ strtolower( substr( $key, 5 ) ) ] = (string) $value;
			}
		}

		$out['protocol'] = isset( $server['SERVER_PROTOCOL'] ) && is_scalar( $server['SERVER_PROTOCOL'] )
			? (string) $server['SERVER_PROTOCOL']
			: '';

		$request_time        = $server['REQUEST_TIME'] ?? 0;
		$out['request_time'] = is_numeric( $request_time ) && (int) $request_time > 0 ? (int) $request_time : time();

		// Rohwert fuer die Aufloesung bereitstellen, dann durch das Ergebnis ersetzen.
		$out['remote_addr'] = isset( $server['REMOTE_ADDR'] ) && is_scalar( $server['REMOTE_ADDR'] )
			? trim( (string) $server['REMOTE_ADDR'] )
			: '';
		$out['remote_addr'] = $this->hasher->client_ip( $out, $trusted_header );

		return $out;
	}
}
