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

namespace Hafenstudios\Wellenbrecher\Pro\Bayes;

defined( 'ABSPATH' ) || exit;

/**
 * Tokenisierung fuer den Bayes-Filter (Technik A6, b8-Muster). Rein, ohne
 * WordPress-Abhaengigkeiten und damit mit einem Zweizeiler-Fixture testbar.
 *
 * Regeln:
 * - E-Mail-Adressen werden VOR der Tokenisierung auf ihre Domain reduziert
 *   (`emaildom:mail.ru`) und dann aus dem Text entfernt: es gelangt niemals
 *   eine ganze Adresse (PII) in die Token-Tabelle.
 * - URLs werden auf den Host reduziert (`url:bit.ly`), fuehrendes www. entfernt;
 *   die restliche URL wird verworfen (kein PII aus Pfaden/Query).
 * - Der Resttext wird lowercase zerlegt, Tokens unter 3 Zeichen fallen weg.
 * - Rueckgabe sind eindeutige Tokens (die Menge der im Dokument vorkommenden
 *   Merkmale, wie es der Graham-/b8-Ansatz erwartet).
 */
class Tokenizer {

	/**
	 * Zerlegt Text in eindeutige Bayes-Tokens.
	 *
	 * @param string $text Roh-Text (Inhalt, Autor-Name, URL, E-Mail zusammengefuehrt).
	 * @return array<int, string> Eindeutige Tokens.
	 */
	public function tokenize( string $text ): array {
		$tokens = array();

		// 1. E-Mails zuerst: nur die Domain als Merkmal, dann aus dem Text tilgen.
		if ( preg_match_all( '/[a-z0-9._%+\-]+@([a-z0-9.\-]+\.[a-z]{2,})/iu', $text, $m ) ) {
			foreach ( $m[1] as $domain ) {
				$tokens[] = 'emaildom:' . strtolower( $domain );
			}
			$text = (string) preg_replace( '/[a-z0-9._%+\-]+@[a-z0-9.\-]+\.[a-z]{2,}/iu', ' ', $text );
		}

		// 2. URLs: nur der Host als Merkmal, dann aus dem Text tilgen. Delimiter ~
		// (nicht #), weil # im Host-Zeichen-Ausschluss [^/\s?#] vorkommt.
		if ( preg_match_all( '~https?://([^/\s?#]+)~iu', $text, $m ) ) {
			foreach ( $m[1] as $host ) {
				$host = strtolower( (string) preg_replace( '/^www\./', '', $host ) );
				if ( '' !== $host ) {
					$tokens[] = 'url:' . $host;
				}
			}
			$text = (string) preg_replace( '~https?://\S+~iu', ' ', $text );
		}

		// 3. Restliche Woerter: lowercase, mindestens 3 Zeichen.
		$lower = function_exists( 'mb_strtolower' ) ? mb_strtolower( $text ) : strtolower( $text );
		if ( preg_match_all( '/[\p{L}\p{N}]{3,}/u', $lower, $m ) ) {
			foreach ( $m[0] as $word ) {
				$tokens[] = $word;
			}
		}

		return array_values( array_unique( $tokens ) );
	}
}
