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

namespace Hafenstudios\Wellenbrecher\Admin;

use Hafenstudios\Wellenbrecher\Db\SpamLogRepository;

defined( 'ABSPATH' ) || exit;

/**
 * Block-Log-Seite (Bauplan Kap. 8): Liste aller Ereignisse aus hs_spam_log
 * mit Filtern nach Kanal/Verdict, Pagination und Bulk-Loeschen. Zweck laut
 * Bauplan: unsichtbare False Positives sichtbar machen ("0 fragwuerdig von
 * 42" schafft Vertrauen).
 */
class LogPage {

	public const SLUG          = 'wellenbrecher-log';
	public const ACTION_DELETE = 'wellenbrecher_delete_logs';

	public const PER_PAGE = 20;

	public const CHANNELS = array( 'comment', 'trackback', 'registration', 'leadlotse', 'woo_review' );
	public const VERDICTS = array( 'blocked', 'quarantined', 'flagged' );

	protected SpamLogRepository $log;

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

	/**
	 * Registriert den admin-post-Handler.
	 *
	 * @return void
	 */
	public function register(): void {
		add_action( 'admin_post_' . self::ACTION_DELETE, array( $this, 'handle_delete' ) );
	}

	/**
	 * Rendert die Seite.
	 *
	 * @return void
	 */
	public function render(): void {
		if ( ! current_user_can( 'hs_manage_spam' ) ) {
			wp_die( esc_html__( 'Sie haben keine Berechtigung, das Block-Log einzusehen.', 'wellenbrecher' ) );
		}

		// phpcs:disable WordPress.Security.NonceVerification.Recommended -- Nur Filter/Pagination der Anzeige.
		$channel = isset( $_GET['channel'] ) ? sanitize_key( wp_unslash( $_GET['channel'] ) ) : '';
		$verdict = isset( $_GET['verdict'] ) ? sanitize_key( wp_unslash( $_GET['verdict'] ) ) : '';
		$page    = isset( $_GET['paged'] ) ? max( 1, absint( wp_unslash( $_GET['paged'] ) ) ) : 1;
		$notice  = isset( $_GET['msg'] ) ? sanitize_key( wp_unslash( $_GET['msg'] ) ) : '';
		// phpcs:enable

		$channel = in_array( $channel, self::CHANNELS, true ) ? $channel : '';
		$verdict = in_array( $verdict, self::VERDICTS, true ) ? $verdict : '';

		$result = $this->log->query(
			array(
				'channel'  => $channel,
				'verdict'  => $verdict,
				'page'     => $page,
				'per_page' => self::PER_PAGE,
			)
		);

		echo '<div class="wrap">';
		echo '<h1 class="wp-heading-inline">' . esc_html__( 'Wellenbrecher: Block-Log', 'wellenbrecher' ) . '</h1>';
		echo '<hr class="wp-header-end" />';

		if ( 'deleted' === $notice ) {
			echo '<div class="notice notice-success is-dismissible"><p>' . esc_html__( 'Die ausgewaehlten Eintraege wurden geloescht.', 'wellenbrecher' ) . '</p></div>';
		}

		echo '<p>' . esc_html__( 'Hier sehen Sie jede Wellenbrecher-Entscheidung mit Begruendung: blockiert (403 vor der Datenbank), Quarantaene (Spam-Ordner) und markiert (Beobachtungsmodus). So bleibt kein False Positive unsichtbar. Eintraege werden nach den Aufbewahrungsfristen automatisch geloescht.', 'wellenbrecher' ) . '</p>';

		$this->render_filters( $channel, $verdict );
		$this->render_table( $result, $channel, $verdict, $page );

		echo '</div>';
	}

	/**
	 * Filter-Formular (GET).
	 *
	 * @param string $channel Aktiver Kanal-Filter.
	 * @param string $verdict Aktiver Verdict-Filter.
	 * @return void
	 */
	protected function render_filters( string $channel, string $verdict ): void {
		echo '<form method="get">';
		echo '<input type="hidden" name="page" value="' . esc_attr( self::SLUG ) . '" />';

		echo '<select name="channel" aria-label="' . esc_attr__( 'Nach Kanal filtern', 'wellenbrecher' ) . '">';
		echo '<option value="">' . esc_html__( 'Alle Kanaele', 'wellenbrecher' ) . '</option>';
		foreach ( self::CHANNELS as $key ) {
			echo '<option value="' . esc_attr( $key ) . '"' . selected( $channel, $key, false ) . '>' . esc_html( $this->channel_label( $key ) ) . '</option>';
		}
		echo '</select> ';

		echo '<select name="verdict" aria-label="' . esc_attr__( 'Nach Ergebnis filtern', 'wellenbrecher' ) . '">';
		echo '<option value="">' . esc_html__( 'Alle Ergebnisse', 'wellenbrecher' ) . '</option>';
		foreach ( self::VERDICTS as $key ) {
			echo '<option value="' . esc_attr( $key ) . '"' . selected( $verdict, $key, false ) . '>' . esc_html( $this->verdict_label( $key ) ) . '</option>';
		}
		echo '</select> ';

		echo '<button type="submit" class="button">' . esc_html__( 'Filtern', 'wellenbrecher' ) . '</button>';
		echo '</form>';
	}

	/**
	 * Die Log-Tabelle inkl. Bulk-Loeschen und Pagination.
	 *
	 * @param array<string, mixed> $result  Ergebnis von SpamLogRepository::query.
	 * @param string               $channel Aktiver Kanal-Filter.
	 * @param string               $verdict Aktiver Verdict-Filter.
	 * @param int                  $page    Aktuelle Seite.
	 * @return void
	 */
	protected function render_table( array $result, string $channel, string $verdict, int $page ): void {
		$items = (array) ( $result['items'] ?? array() );
		$total = (int) ( $result['total'] ?? 0 );

		if ( array() === $items ) {
			echo '<p>' . esc_html__( 'Keine Eintraege. Sobald Wellenbrecher etwas blockiert, in Quarantaene stellt oder markiert, erscheint es hier.', 'wellenbrecher' ) . '</p>';
			return;
		}

		echo '<form method="post" action="' . esc_url( admin_url( 'admin-post.php' ) ) . '">';
		echo '<input type="hidden" name="action" value="' . esc_attr( self::ACTION_DELETE ) . '" />';
		echo '<input type="hidden" name="channel" value="' . esc_attr( $channel ) . '" />';
		echo '<input type="hidden" name="verdict" value="' . esc_attr( $verdict ) . '" />';
		wp_nonce_field( self::ACTION_DELETE );

		echo '<table class="wp-list-table widefat fixed striped">';
		echo '<thead><tr>';
		echo '<td class="check-column"><input type="checkbox" onclick="this.closest(\'table\').querySelectorAll(\'tbody input[type=checkbox]\').forEach(function(c){c.checked=this.checked}, this)" aria-label="' . esc_attr__( 'Alle auswaehlen', 'wellenbrecher' ) . '" /></td>';
		echo '<th scope="col">' . esc_html__( 'Zeit (UTC)', 'wellenbrecher' ) . '</th>';
		echo '<th scope="col">' . esc_html__( 'Kanal', 'wellenbrecher' ) . '</th>';
		echo '<th scope="col">' . esc_html__( 'Ergebnis', 'wellenbrecher' ) . '</th>';
		echo '<th scope="col">' . esc_html__( 'Punkte', 'wellenbrecher' ) . '</th>';
		echo '<th scope="col">' . esc_html__( 'Gruende', 'wellenbrecher' ) . '</th>';
		echo '<th scope="col">' . esc_html__( 'Auszug', 'wellenbrecher' ) . '</th>';
		echo '</tr></thead><tbody>';

		foreach ( $items as $item ) {
			$item = (array) $item;
			echo '<tr>';
			echo '<th scope="row" class="check-column"><input type="checkbox" name="wb_ids[]" value="' . esc_attr( (string) (int) ( $item['id'] ?? 0 ) ) . '" /></th>';
			echo '<td>' . esc_html( (string) ( $item['created_at'] ?? '' ) ) . '</td>';
			echo '<td>' . esc_html( $this->channel_label( (string) ( $item['channel'] ?? '' ) ) ) . '</td>';
			echo '<td>' . esc_html( $this->verdict_label( (string) ( $item['verdict'] ?? '' ) ) ) . '</td>';
			echo '<td>' . esc_html( (string) (int) ( $item['score'] ?? 0 ) ) . '</td>';
			echo '<td>' . esc_html( $this->reasons_text( is_array( $item['reasons'] ?? null ) ? $item['reasons'] : array() ) ) . '</td>';
			echo '<td>' . esc_html( (string) ( $item['excerpt'] ?? '' ) ) . '</td>';
			echo '</tr>';
		}

		echo '</tbody></table>';

		echo '<p><button type="submit" class="button">' . esc_html__( 'Ausgewaehlte loeschen', 'wellenbrecher' ) . '</button></p>';
		echo '</form>';

		$this->render_pagination( $total, $page, $channel, $verdict );
	}

	/**
	 * Einfache Zurueck/Weiter-Pagination.
	 *
	 * @param int    $total   Gesamtzahl.
	 * @param int    $page    Aktuelle Seite.
	 * @param string $channel Kanal-Filter.
	 * @param string $verdict Verdict-Filter.
	 * @return void
	 */
	protected function render_pagination( int $total, int $page, string $channel, string $verdict ): void {
		$pages = (int) ceil( $total / self::PER_PAGE );
		if ( $pages <= 1 ) {
			return;
		}

		$base = add_query_arg(
			array(
				'page'    => self::SLUG,
				'channel' => $channel,
				'verdict' => $verdict,
			),
			admin_url( 'admin.php' )
		);

		echo '<p class="tablenav-pages">';
		if ( $page > 1 ) {
			echo '<a class="button" href="' . esc_url( add_query_arg( 'paged', $page - 1, $base ) ) . '">' . esc_html__( 'Zurueck', 'wellenbrecher' ) . '</a> ';
		}
		/* translators: 1: aktuelle Seite, 2: Seitenzahl gesamt */
		echo esc_html( sprintf( __( 'Seite %1$d von %2$d', 'wellenbrecher' ), $page, $pages ) );
		if ( $page < $pages ) {
			echo ' <a class="button" href="' . esc_url( add_query_arg( 'paged', $page + 1, $base ) ) . '">' . esc_html__( 'Weiter', 'wellenbrecher' ) . '</a>';
		}
		echo '</p>';
	}

	/**
	 * Bulk-Loeschen (admin-post).
	 *
	 * @return void
	 */
	public function handle_delete(): void {
		if ( ! current_user_can( 'hs_manage_spam' ) ) {
			wp_die( esc_html__( 'Keine Berechtigung.', 'wellenbrecher' ) );
		}
		check_admin_referer( self::ACTION_DELETE );

		$ids = isset( $_POST['wb_ids'] ) && is_array( $_POST['wb_ids'] ) ? array_map( 'absint', wp_unslash( $_POST['wb_ids'] ) ) : array();
		if ( array() !== $ids ) {
			$this->log->delete( $ids );
		}

		$channel = isset( $_POST['channel'] ) ? sanitize_key( wp_unslash( $_POST['channel'] ) ) : '';
		$verdict = isset( $_POST['verdict'] ) ? sanitize_key( wp_unslash( $_POST['verdict'] ) ) : '';

		wp_safe_redirect(
			add_query_arg(
				array(
					'page'    => self::SLUG,
					'channel' => $channel,
					'verdict' => $verdict,
					'msg'     => 'deleted',
				),
				admin_url( 'admin.php' )
			)
		);
		exit;
	}

	/**
	 * Gruende lesbar aufgeloest: "Label (+Punkte)", kommagetrennt.
	 *
	 * @param array<string, mixed> $reasons Breakdown rule_id => Punkte.
	 * @return string
	 */
	protected function reasons_text( array $reasons ): string {
		$parts = array();
		foreach ( $reasons as $id => $points ) {
			$parts[] = RuleLabels::label( (string) $id ) . ' (' . sprintf( '%+d', (int) $points ) . ')';
		}
		return implode( ', ', $parts );
	}

	/**
	 * Kanal-Label (zentral in ChannelLabels, damit alle Seiten dieselben
	 * Bezeichnungen zeigen).
	 *
	 * @param string $channel Kanal-Key.
	 * @return string
	 */
	protected function channel_label( string $channel ): string {
		return ChannelLabels::label( $channel );
	}

	/**
	 * Verdict-Label.
	 *
	 * @param string $verdict Verdict-Key.
	 * @return string
	 */
	protected function verdict_label( string $verdict ): string {
		$labels = array(
			'blocked'     => __( 'Blockiert', 'wellenbrecher' ),
			'quarantined' => __( 'Quarantaene', 'wellenbrecher' ),
			'flagged'     => __( 'Markiert (Beobachtung)', 'wellenbrecher' ),
		);
		return $labels[ $verdict ] ?? $verdict;
	}
}
