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

namespace Hafenstudios\Wellenbrecher\Support;

use Hafenstudios\Core\Settings\Settings;

defined( 'ABSPATH' ) || exit;

/**
 * Rehabilitations-Gedaechtnis (Bauplan Kap. 5): Settings-basierte Allowlist
 * aus E-Mail-HMACs mit TTL 90 Tage, gepflegt durch unspam-Aktionen
 * (transition_comment_status spam -> approved). Kein Klartext.
 *
 * HMAC bewusst mit wp_salt('auth') OHNE Rotation (WB11): mit dem
 * rotierenden Wochen-Salt des IpHasher wuerde jeder Eintrag nach einer
 * Woche unauffindbar und die 90-Tage-TTL waere wirkungslos.
 */
class Allowlist {

	public const TTL_DAYS = 90;

	protected Settings $settings;

	/**
	 * @param Settings $settings Wellenbrecher-Settings.
	 */
	public function __construct( Settings $settings ) {
		$this->settings = $settings;
	}

	/**
	 * Traegt eine E-Mail-Adresse ein (verlaengert bei erneutem Eintrag die
	 * TTL) und raeumt abgelaufene Eintraege im selben Schreibvorgang ab.
	 *
	 * @param string   $email E-Mail-Adresse (Klartext, wird sofort gehasht).
	 * @param int|null $now   Bezugszeit (Default: jetzt, fuer Tests).
	 * @return void
	 */
	public function add( string $email, ?int $now = null ): void {
		$hmac = $this->hash( $email );
		if ( '' === $hmac ) {
			return;
		}
		$now     = $now ?? time();
		$entries = $this->prune( $this->entries(), $now );

		$entries[ $hmac ] = $now + ( self::TTL_DAYS * DAY_IN_SECONDS );
		$this->settings->set( 'allowlist', $entries );
	}

	/**
	 * Entfernt eine E-Mail-Adresse (z.B. bei approved -> spam).
	 *
	 * @param string $email E-Mail-Adresse.
	 * @return void
	 */
	public function remove( string $email ): void {
		$hmac    = $this->hash( $email );
		$entries = $this->entries();
		if ( '' === $hmac || ! isset( $entries[ $hmac ] ) ) {
			return;
		}
		unset( $entries[ $hmac ] );
		$this->settings->set( 'allowlist', $entries );
	}

	/**
	 * Ist die Adresse aktuell allowgelistet (Eintrag vorhanden und TTL nicht
	 * abgelaufen)?
	 *
	 * @param string   $email E-Mail-Adresse.
	 * @param int|null $now   Bezugszeit (Default: jetzt).
	 * @return bool
	 */
	public function contains( string $email, ?int $now = null ): bool {
		$hmac = $this->hash( $email );
		if ( '' === $hmac ) {
			return false;
		}
		$expires = (int) ( $this->entries()[ $hmac ] ?? 0 );
		return $expires > ( $now ?? time() );
	}

	/**
	 * HMAC einer E-Mail-Adresse (lowercase, getrimmt).
	 *
	 * @param string $email E-Mail-Adresse.
	 * @return string Leer bei leerer Adresse.
	 */
	protected function hash( string $email ): string {
		$email = strtolower( trim( $email ) );
		if ( '' === $email ) {
			return '';
		}
		return hash_hmac( 'sha256', $email, 'wellenbrecher_allowlist|' . (string) wp_salt( 'auth' ) );
	}

	/**
	 * Gespeicherte Eintraege (hmac => Ablauf-Unix-Zeit).
	 *
	 * @return array<string, int>
	 */
	protected function entries(): array {
		$entries = $this->settings->get( 'allowlist', array() );
		return is_array( $entries ) ? $entries : array();
	}

	/**
	 * Entfernt abgelaufene Eintraege.
	 *
	 * @param array<string, int> $entries Eintraege.
	 * @param int                $now     Bezugszeit.
	 * @return array<string, int>
	 */
	protected function prune( array $entries, int $now ): array {
		return array_filter(
			$entries,
			static function ( $expires ) use ( $now ) {
				return (int) $expires > $now;
			}
		);
	}
}
