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

namespace Hafenstudios\Wellenbrecher\Signals;

defined( 'ABSPATH' ) || exit;

/**
 * Rotierender Honeypot-/Feldname (Bauplan Kap. 4.4, Lehre aus der
 * ASB-Schwaeche: ein statischer Feldname ist nach einmaligem Rendern
 * dauerhaft bekannt). Der Name wird pro UTC-Tag aus einem HMAC abgeleitet;
 * gueltig sind heute UND gestern (Page-Cache-Fenster wie beim TokenService).
 *
 * Zwecke ('honeypot', 'field') erzeugen unabhaengige Namensraeume: der
 * Honeypot-Name und der Tarnname des echten Feldes (Feld-Tausch) rotieren
 * getrennt.
 */
class FieldRotation {

	public const PURPOSE_HONEYPOT = 'honeypot';
	public const PURPOSE_FIELD    = 'field';

	/**
	 * Aktueller Feldname fuer einen Zweck.
	 *
	 * @param string   $purpose Zweck (honeypot|field).
	 * @param int|null $time    Unix-Zeit (Default: jetzt).
	 * @return string
	 */
	public function name( string $purpose = self::PURPOSE_HONEYPOT, ?int $time = null ): string {
		return $this->for_day( $purpose, 0, $time );
	}

	/**
	 * Ist ein eingereichter Feldname eine gueltige Generation (heute/gestern)?
	 *
	 * @param string   $purpose Zweck (honeypot|field).
	 * @param string   $name    Eingereichter Feldname.
	 * @param int|null $time    Unix-Zeit (Default: jetzt).
	 * @return bool
	 */
	public function is_known( string $purpose, string $name, ?int $time = null ): bool {
		if ( '' === $name ) {
			return false;
		}
		return hash_equals( $this->for_day( $purpose, 0, $time ), $name )
			|| hash_equals( $this->for_day( $purpose, 1, $time ), $name );
	}

	/**
	 * Feldname fuer ein bestimmtes UTC-Tagesfenster. Praefix "wb_" plus
	 * 10 Hex-Zeichen: unauffaellig, aber eindeutig dem Plugin zuordenbar.
	 *
	 * @param string   $purpose  Zweck.
	 * @param int      $days_ago Tage zurueck (0 = heute).
	 * @param int|null $time     Bezugszeit (Default: jetzt).
	 * @return string
	 */
	protected function for_day( string $purpose, int $days_ago, ?int $time = null ): string {
		$time = ( $time ?? time() ) - ( $days_ago * DAY_IN_SECONDS );
		$day  = gmdate( 'Y-m-d', $time );
		$hash = hash_hmac( 'sha256', 'wellenbrecher_field|' . $purpose . '|' . $day, (string) wp_salt( 'nonce' ) );
		return 'wb_' . substr( $hash, 0, 10 );
	}
}
