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

namespace Hafenstudios\Wellenbrecher\Privacy;

use Hafenstudios\Core\Events\EventBus;
use Hafenstudios\Wellenbrecher\Db\SpamLogRepository;

defined( 'ABSPATH' ) || exit;

/**
 * DSGVO-Anbindung (Bauplan Kap. 9): Datenschutz-Snippet, Datenexport und
 * Loeschung. Muster: Kurato/Leadlotse PrivacyBridge (Export/Loeschung laufen
 * ueber die Flotten-Filter privacy_export / privacy_erase des Core-
 * PrivacyManager; das Policy-Snippet ueber wp_add_privacy_policy_content).
 *
 * Der EINZIGE Klartext-Personenbezug im Plugin sind die Quarantaene-Payloads
 * (kompletter Leadlotse-Submit, bis zur 30-Tage-Frist bzw. bis Wiederherstellung
 * oder Loeschung). Alle uebrigen Log-Zeilen sind pseudonymisiert (IP nur als
 * HMAC unter rotierendem Wochen-Salt, E-Mail nur als Domain) und werden
 * ausschliesslich per Fristenlauf geloescht - der Eraser weist sie ehrlich als
 * "retained, Loeschung erfolgt fristgebunden" aus (WP-konform).
 */
final class PrivacyBridge {

	private SpamLogRepository $log;

	/**
	 * @param SpamLogRepository $log Spam-Log-Repository.
	 */
	public function __construct( SpamLogRepository $log ) {
		$this->log = $log;
	}

	/**
	 * Registriert Policy-Snippet, Exporter und Eraser.
	 *
	 * @return void
	 */
	public function register(): void {
		add_action( 'admin_init', array( $this, 'add_policy_content' ) );
		EventBus::add_filter( 'privacy_export', array( $this, 'export' ), 10, 2 );
		EventBus::add_filter( 'privacy_erase', array( $this, 'erase' ), 10, 2 );
	}

	/**
	 * Datenschutz-Vorschlag fuer den WordPress-Datenschutz-Assistenten (Sie-Form,
	 * keine Em-Dashes). Beschreibt, was Wellenbrecher verarbeitet, die Fristen und
	 * den Update-Check als EINZIGEN externen Request (Empfaenger, Frequenz, Daten).
	 *
	 * @return void
	 */
	public function add_policy_content(): void {
		if ( ! function_exists( 'wp_add_privacy_policy_content' ) ) {
			return;
		}

		$content =
			'<p>' . esc_html__( 'Wellenbrecher schuetzt diese Website lokal vor Spam. Die Bewertung eingehender Kommentare, Formulare und Registrierungen findet ausschliesslich auf diesem Server statt. Es wird zur Laufzeit ein Punktwert gebildet und sofort verworfen; gespeichert wird nur das Ergebnis.', 'wellenbrecher' ) . '</p>'
			. '<p>' . esc_html__( 'Zur Nachvollziehbarkeit fuehrt Wellenbrecher ein internes Ereignis-Protokoll. Darin wird die IP-Adresse niemals im Klartext abgelegt, sondern nur als nicht umkehrbarer Pruefwert (HMAC) unter einem woechentlich wechselnden Schluessel; von E-Mail-Adressen wird ausschliesslich die Domain gespeichert. Abgefangene Formular-Einsendungen (Quarantaene) werden bis zu ihrer Wiederherstellung oder Loeschung vollstaendig im Klartext vorgehalten, damit Sie faelschlich abgefangene Anfragen zurueckholen koennen.', 'wellenbrecher' ) . '</p>'
			. '<p>' . esc_html__( 'Aufbewahrungsfristen: Protokolleintraege zu blockierten oder markierten Vorgaengen werden nach 7 Tagen automatisch geloescht, quarantinierte Formular-Einsendungen nach 30 Tagen. Eine anonyme Tagesstatistik ohne Personenbezug bleibt darueber hinaus erhalten.', 'wellenbrecher' ) . '</p>'
			. '<p>' . esc_html__( 'Wellenbrecher sendet im Normalbetrieb keine Daten an Dritte. Der einzige ausgehende Aufruf ist die Pruefung auf Programm-Aktualisierungen: Hoechstens alle 12 Stunden ruft WordPress dazu die Datei https://hafenstudios.com/updates/wellenbrecher.json ab. Dabei uebermittelt WordPress standardmaessig die Adresse dieser Website und die WordPress-Version (uebliches Vorgehen bei Aktualisierungen). Es werden keine Inhalte und keine personenbezogenen Daten Ihrer Besucher uebertragen.', 'wellenbrecher' ) . '</p>';

		wp_add_privacy_policy_content( 'Wellenbrecher', $content );
	}

	/**
	 * Exporter: liefert zu einer E-Mail die noch vorhandenen Quarantaene-Payload-
	 * Treffer (dekodiert, wertweise; technische Signalfelder ausgeblendet).
	 *
	 * @param array<int, array<string, mixed>> $items Bisherige Export-Items.
	 * @param string                           $email E-Mail.
	 * @return array<int, array<string, mixed>>
	 */
	public function export( array $items, string $email ): array {
		foreach ( $this->log->find_payload_rows_by_email( $email ) as $row ) {
			$data = array(
				array( 'name' => __( 'Kanal', 'wellenbrecher' ), 'value' => (string) ( $row['channel'] ?? '' ) ),
				array( 'name' => __( 'Abgefangen am (UTC)', 'wellenbrecher' ), 'value' => (string) ( $row['created_at'] ?? '' ) ),
			);
			foreach ( $this->payload_values( $row ) as $label => $value ) {
				$data[] = array( 'name' => (string) $label, 'value' => (string) $value );
			}

			$items[] = array(
				'group_id'    => 'wellenbrecher_quarantine',
				'group_label' => __( 'Quarantaene (Wellenbrecher)', 'wellenbrecher' ),
				'item_id'     => 'wb-quarantine-' . (int) ( $row['id'] ?? 0 ),
				'data'        => $data,
			);
		}
		return $items;
	}

	/**
	 * Eraser: loescht die Quarantaene-Payload-Treffer (der einzige Klartext-PII).
	 * Die uebrigen, pseudonymisierten Log-Zeilen koennen nicht personenscharf
	 * gefunden werden (IP nur als HMAC, E-Mail nur als Domain); sie bleiben und
	 * werden per Fristenlauf geloescht. Das wird ehrlich als retained mit
	 * Begruendung ausgewiesen (WP-konform).
	 *
	 * @param array<string, mixed> $result Bisheriges Loeschergebnis.
	 * @param string               $email  E-Mail.
	 * @return array<string, mixed>
	 */
	public function erase( array $result, string $email ): array {
		$ids = array();
		foreach ( $this->log->find_payload_rows_by_email( $email ) as $row ) {
			$id = (int) ( $row['id'] ?? 0 );
			if ( $id > 0 ) {
				$ids[] = $id;
			}
		}
		if ( array() !== $ids ) {
			$this->log->delete( $ids );
			$result['items_removed'] = true;
		}

		// Pseudonymisierte Protokolle: nicht personenscharf loeschbar, aber
		// fristgebunden. Ehrlich als retained ausweisen.
		$result['items_retained'] = true;
		$messages                 = isset( $result['messages'] ) && is_array( $result['messages'] ) ? $result['messages'] : array();
		$messages[]               = __( 'Wellenbrecher: Die uebrigen Spam-Schutz-Protokolle enthalten keine Klartext-Daten (IP-Adressen nur als nicht umkehrbarer Pruefwert, E-Mail-Adressen nur als Domain) und lassen sich daher keiner Person eindeutig zuordnen. Sie werden automatisch nach Ablauf der Aufbewahrungsfrist geloescht (blockiert oder markiert nach 7 Tagen, Quarantaene nach 30 Tagen).', 'wellenbrecher' );
		$result['messages']       = $messages;

		return $result;
	}

	/**
	 * Dekodiert den Payload einer Zeile und liefert die fachlichen Felder
	 * wertweise (technische Signalfelder mit Praefix wb_ oder ll_ ausgeblendet).
	 *
	 * @param array<string, mixed> $row Log-Zeile.
	 * @return array<string, string>
	 */
	private function payload_values( array $row ): array {
		$decoded = json_decode( (string) ( $row['payload'] ?? '' ), true );
		if ( ! is_array( $decoded ) ) {
			return array();
		}
		$input  = is_array( $decoded['input'] ?? null ) ? $decoded['input'] : $decoded;
		$values = array();
		foreach ( $input as $key => $value ) {
			$key = (string) $key;
			if ( 0 === strpos( $key, 'wb_' ) || 0 === strpos( $key, 'll_' ) ) {
				continue; // Technische Signalfelder (Token/JS/Honeypot/Zeitfalle).
			}
			$values[ $key ] = is_array( $value ) ? implode( ', ', array_map( 'strval', $value ) ) : (string) $value;
		}
		return $values;
	}
}
