<?php
/**
 * Ability: wp-agent/moderate-comment
 *
 * Setzt den Status eines bestehenden Kommentars direkt (approve, hold, spam,
 * trash) über wp_set_comment_status() und verifiziert per Re-Read über
 * wp_get_comment_status().
 *
 * Fallstrick, den diese Ability explizit ausgleicht: wp_set_comment_status()
 * nimmt als Eingabe-Vokabular 'approve'/'hold'/'spam'/'trash' entgegen,
 * wp_get_comment_status() liefert beim Zurücklesen aber ein ANDERES
 * Vokabular ('approved'/'unapproved'/'spam'/'trash'; 'hold' wird zu
 * 'unapproved'). Ein naiver String-Vergleich der beiden Werte würde also
 * ausgerechnet für approve/hold IMMER fehlschlagen, obwohl der Status
 * korrekt gesetzt wurde. Die Verifikation bildet deshalb explizit auf das
 * Rückgabe-Vokabular ab, bevor sie vergleicht.
 *
 * @package WPAgentCompanion
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( ! function_exists( 'wpagent_perm_moderate_comments' ) ) {
	/**
	 * Permission callback: der Aufrufer muss Kommentare moderieren dürfen.
	 *
	 * Siehe die ausführliche Begründung in list-comments.php (identische,
	 * function_exists()-geschützte Definition in allen vier neuen
	 * Kommentare-Ability-Dateien, damit keine Ladereihenfolge zwischen ihnen
	 * vorausgesetzt werden muss).
	 *
	 * @param mixed $input Ungenutzter Ability-Input.
	 * @return bool
	 */
	function wpagent_perm_moderate_comments( $input = null ): bool {
		return current_user_can( 'moderate_comments' );
	}
}

function wpagent_ability_moderate_comment(): array {
	return array(
		'label'               => __( 'Kommentar moderieren', 'wp-agent-companion' ),
		'description'         => __( 'Setzt den Status eines Kommentars direkt (approve, hold, spam, trash) und verifiziert per Re-Read, dass der neue Status tatsächlich persistiert wurde.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array(
			'type'       => 'object',
			'properties' => array(
				'comment_id' => array( 'type' => 'integer' ),
				'status'     => array(
					'type' => 'string',
					'enum' => array( 'approve', 'hold', 'spam', 'trash' ),
				),
			),
			'required'   => array( 'comment_id', 'status' ),
		),
		'output_schema'       => array(
			'type'       => 'object',
			'properties' => array(
				'comment_id' => array( 'type' => 'integer' ),
				'status'     => array( 'type' => 'string' ),
				'verified'   => array( 'type' => 'boolean' ),
			),
		),
		'execute_callback'    => 'wpagent_exec_moderate_comment',
		'permission_callback' => 'wpagent_perm_moderate_comments',
		'meta'                => array(
			'show_in_rest' => true,
			'annotations'  => array(
				'readonly'    => false,
				'destructive' => false,
				'idempotent'  => true,
			),
		),
	);
}

/**
 * @param mixed $input
 * @return array|WP_Error
 */
function wpagent_exec_moderate_comment( $input ) {
	$input      = is_array( $input ) ? $input : array();
	$comment_id = (int) ( $input['comment_id'] ?? 0 );
	$comment    = get_comment( $comment_id );

	if ( ! $comment ) {
		return new WP_Error( 'wpagent_no_comment', __( 'Kommentar nicht gefunden.', 'wp-agent-companion' ), array( 'status' => 404 ) );
	}
	// edit_comment statt moderate_comments: die grobe Schranke oben prüft nur,
	// ob überhaupt moderiert werden darf. Der Feincheck hier löst über
	// WordPress' eigene Meta-Capability-Zuordnung (map_meta_cap, Fall
	// 'edit_comment') die tatsächlich zuständige Capability für DIESEN
	// Kommentar auf: sie mappt intern auf edit_post des zugehörigen Beitrags
	// (oder edit_posts bei verwaisten Kommentaren ohne Beitrag).
	if ( ! current_user_can( 'edit_comment', $comment_id ) ) {
		return new WP_Error( 'wpagent_forbidden', __( 'Keine Berechtigung.', 'wp-agent-companion' ), array( 'status' => 403 ) );
	}

	$status  = (string) ( $input['status'] ?? '' );
	$allowed = array( 'approve', 'hold', 'spam', 'trash' );
	if ( ! in_array( $status, $allowed, true ) ) {
		/* translators: %s: submitted comment status. */
		return new WP_Error( 'wpagent_bad_status', sprintf( __( 'Ungültiger Status "%s".', 'wp-agent-companion' ), $status ), array( 'status' => 400 ) );
	}

	// Eingabe-Vokabular (wp_set_comment_status) -> Rückgabe-Vokabular
	// (wp_get_comment_status), siehe Datei-Kommentar oben.
	$expected_label = array(
		'approve' => 'approved',
		'hold'    => 'unapproved',
		'spam'    => 'spam',
		'trash'   => 'trash',
	);

	$current_status = wp_get_comment_status( $comment_id );
	if ( $expected_label[ $status ] === $current_status ) {
		return array(
			'comment_id' => $comment_id,
			'status'     => $current_status,
			'verified'   => true,
		);
	}

	$res = wp_set_comment_status( $comment_id, $status, true );
	if ( is_wp_error( $res ) ) {
		return $res;
	}

	$actual_status = wp_get_comment_status( $comment_id );
	$verified      = ( $expected_label[ $status ] === $actual_status );

	return array(
		'comment_id' => $comment_id,
		'status'     => false !== $actual_status ? $actual_status : '',
		'verified'   => $verified,
	);
}
