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

namespace Hafenstudios\Wellenbrecher\Rules;

use Hafenstudios\Wellenbrecher\Engine\Context;
use Hafenstudios\Wellenbrecher\Engine\RuleInterface;
use Hafenstudios\Wellenbrecher\Engine\RuleResult;
use Hafenstudios\Wellenbrecher\Pro\GeoIp\GeoDatabase;

defined( 'ABSPATH' ) || exit;

/**
 * Herkunftsland-Regel (Pro, Stufe 3, W5b Technik A8). Gibt +10, wenn die
 * aufgeloeste Besucher-IP aus einem der konfigurierten Laender kommt.
 *
 * Bewusst schwach und NIE hart blockend (Bauplan/WB4): +10 allein erreicht die
 * Block-Schwelle nicht; das Land ist ein Zusatzsignal, kein Urteil. Die
 * Laenderliste ist Default LEER - dann ist die Regel inaktiv (applies() false),
 * niemand wird ungewollt nach Herkunft gefiltert. Fehlt/veraltet die Datenbank,
 * ist die Regel ebenfalls stumm (GeoDatabase::has_country()).
 */
class CountryRule implements RuleInterface {

	public const ID = 'geo_country';

	public const DEFAULT_POINTS = 10;

	protected GeoDatabase $geo;

	/**
	 * @var array<int, string> Konfigurierte Laendercodes (ISO-3166 Alpha-2, gross).
	 */
	protected array $countries;

	protected int $points;

	/**
	 * @param GeoDatabase       $geo       Geo-Datenbank-Huelle.
	 * @param array<int,string> $countries Laendercodes (werden gross normalisiert).
	 * @param int               $points    Punkte bei Treffer.
	 */
	public function __construct( GeoDatabase $geo, array $countries, int $points = self::DEFAULT_POINTS ) {
		$this->geo       = $geo;
		$this->countries = array_values( array_filter( array_map(
			static fn( $c ): string => strtoupper( trim( (string) $c ) ),
			$countries
		) ) );
		$this->points    = $points;
	}

	public function id(): string {
		return self::ID;
	}

	public function stage(): int {
		return 3;
	}

	/**
	 * Nur aktiv mit konfigurierter Laenderliste, vorhandener Datenbank und
	 * aufgeloester IP.
	 *
	 * @param Context $context Bewertungs-Kontext.
	 * @return bool
	 */
	public function applies( Context $context ): bool {
		return array() !== $this->countries
			&& $this->geo->has_country()
			&& '' !== $context->server( 'remote_addr' );
	}

	public function evaluate( Context $context ): RuleResult {
		$country = $this->geo->country( $context->server( 'remote_addr' ) );
		if ( '' === $country || ! in_array( $country, $this->countries, true ) ) {
			return RuleResult::none( self::ID );
		}
		return new RuleResult( $this->points, self::ID );
	}
}
