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

namespace Hafenstudios\Wellenbrecher\Pro\AbuseIpdb;

defined( 'ABSPATH' ) || exit;

/**
 * Duenner AbuseIPDB-Client (W5b, Technik A9). Fragt den check-Endpoint mit dem
 * BYO-Key des Betreibers ab und liefert den abuseConfidenceScore 0-100 - oder
 * -1 bei jedem Fehler (fail-open). Timeout 5 s.
 *
 * Datenschutz-Hinweis (im UI ausgewiesen, Admin\ExternaPage): die abgefragte
 * IP-Adresse wird an AbuseIPDB (USA) uebertragen. Nur mit Opt-in und eigenem
 * Schluessel; ohne beides wird nie abgefragt.
 *
 * Nicht final, damit Tests confidence() ueberschreiben koennen.
 */
class AbuseIpdbClient {

	public const ENDPOINT = 'https://api.abuseipdb.com/api/v2/check';

	public const TIMEOUT = 5;

	public const MAX_AGE_DAYS = 90;

	protected string $key;

	/**
	 * @param string $key AbuseIPDB-API-Key (Klartext, bereits entschluesselt).
	 */
	public function __construct( string $key ) {
		$this->key = trim( $key );
	}

	/**
	 * Ist ein Schluessel hinterlegt?
	 *
	 * @return bool
	 */
	public function is_configured(): bool {
		return '' !== $this->key;
	}

	/**
	 * Fragt den Confidence-Score fuer eine IP ab. Liefert 0-100 oder -1 bei
	 * jedem Fehler (nicht konfiguriert, Netzfehler, Nicht-200, unparsbar).
	 *
	 * @param string $ip Klartext-IP.
	 * @return int
	 */
	public function confidence( string $ip ): int {
		$ip = trim( $ip );
		if ( ! $this->is_configured() || '' === $ip ) {
			return -1;
		}

		$url = add_query_arg(
			array(
				'ipAddress'    => $ip,
				'maxAgeInDays' => self::MAX_AGE_DAYS,
			),
			self::ENDPOINT
		);

		$response = wp_remote_get(
			$url,
			array(
				'timeout' => self::TIMEOUT,
				'headers' => array(
					'Key'    => $this->key,
					'Accept' => 'application/json',
				),
			)
		);

		if ( is_wp_error( $response ) ) {
			return -1;
		}
		if ( 200 !== (int) wp_remote_retrieve_response_code( $response ) ) {
			return -1;
		}

		$data  = json_decode( (string) wp_remote_retrieve_body( $response ), true );
		$score = is_array( $data ) ? ( $data['data']['abuseConfidenceScore'] ?? null ) : null;
		if ( ! is_numeric( $score ) ) {
			return -1;
		}
		return max( 0, min( 100, (int) $score ) );
	}
}
