<?php
/**
 * Ability: wp-agent/update-reusable-block
 *
 * Partielles Update eines bestehenden wiederverwendbaren Blocks (Post-Type
 * wp_block): nur die übergebenen Felder werden geändert. block_id muss auf
 * einen tatsächlich existierenden wp_block-Post zeigen; zeigt sie auf einen
 * Post eines anderen Post-Types, wird das wie "nicht gefunden" behandelt (404),
 * statt versehentlich einen fremden Post-Type über diese Ability zu ändern.
 *
 * Kein status-Feld: anders als bei normalen Beiträgen hat ein wiederverwendbarer
 * Block im Editor keine Status-Steuerung, und ein Statuswechsel weg von
 * "publish" würde core/block-Referenzen auf allen Seiten, die den Block
 * einbinden, still leer laufen lassen (siehe create-reusable-block.php für die
 * ausführliche Begründung). Wer den Status ändern will, kann das bewusst über
 * wp-agent/set-post-status tun, das genau dafür da ist.
 *
 * Nach dem Schreiben liest die Ability jedes geänderte Feld zurück und meldet
 * pro Feld verified:true/false (String-Vergleich), analog zu update-post.php.
 *
 * @package WPAgentCompanion
 */

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

function wpagent_ability_update_reusable_block(): array {
	return array(
		'label'               => __( 'Wiederverwendbaren Block aktualisieren', 'wp-agent-companion' ),
		'description'         => __( 'Aktualisiert Titel und/oder Inhalt eines bestehenden wiederverwendbaren Blocks (wp_block). Nur übergebene Felder werden geändert; jedes geänderte Feld wird per Re-Read verifiziert.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array(
			'type'       => 'object',
			'properties' => array(
				'block_id'         => array( 'type' => 'integer' ),
				'title'            => array( 'type' => 'string' ),
				'content_markdown' => array(
					'type'        => 'string',
					'description' => __( 'Wird wie bei create-reusable-block serverseitig zu erlaubten Gutenberg-Core-Blöcken konvertiert.', 'wp-agent-companion' ),
				),
			),
			'required'   => array( 'block_id' ),
		),
		'output_schema'       => array(
			'type'       => 'object',
			'properties' => array(
				'block_id'       => array( 'type' => 'integer' ),
				'written'        => array( 'type' => 'object' ),
				'verified'       => array( 'type' => 'boolean' ),
				'block_count'    => array( 'type' => 'integer' ),
				'freeform_count' => array( 'type' => 'integer' ),
				'block_types'    => array(
					'type'  => 'array',
					'items' => array( 'type' => 'string' ),
				),
				'has_freeform'   => array( 'type' => 'boolean' ),
			),
		),
		'execute_callback'    => 'wpagent_exec_update_reusable_block',
		'permission_callback' => 'wpagent_perm_edit_posts',
		'meta'                => array(
			'show_in_rest' => true,
			'annotations'  => array(
				'readonly'    => false,
				'destructive' => false,
				'idempotent'  => true,
			),
		),
	);
}

/**
 * @param mixed $input
 * @return array|WP_Error
 */
function wpagent_exec_update_reusable_block( $input ) {
	$input    = is_array( $input ) ? $input : array();
	$block_id = (int) ( $input['block_id'] ?? 0 );
	$post     = get_post( $block_id );

	if ( ! $post || 'wp_block' !== $post->post_type ) {
		return new WP_Error( 'wpagent_no_block', __( 'Wiederverwendbarer Block nicht gefunden.', 'wp-agent-companion' ), array( 'status' => 404 ) );
	}
	// current_user_can( 'edit_post', ... ) löst über WordPress' eigene
	// Meta-Capability-Zuordnung für wp_block korrekt auf edit_posts /
	// edit_published_posts / edit_others_posts auf (siehe map_meta_cap()-Zweig
	// 'edit_post' im Kern), abhängig davon, ob der Aufrufer der Autor ist und ob
	// der Block bereits veröffentlicht ist.
	if ( ! current_user_can( 'edit_post', $block_id ) ) {
		return new WP_Error( 'wpagent_forbidden', __( 'Keine Berechtigung.', 'wp-agent-companion' ), array( 'status' => 403 ) );
	}

	$postarr = array( 'ID' => $block_id );
	$expect  = array(); // Feld => Erwartungswert für die Re-Read-Verifikation.

	if ( array_key_exists( 'title', $input ) ) {
		$postarr['post_title'] = (string) $input['title'];
		$expect['title']       = $postarr['post_title'];
	}

	if ( array_key_exists( 'content', $input ) ) {
		return new WP_Error( 'wpagent_raw_block_markup_not_allowed', __( 'Rohes Block-Markup und HTML sind nicht erlaubt. Verwende content_markdown.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}

	$has_markdown = array_key_exists( 'content_markdown', $input ) && '' !== trim( (string) $input['content_markdown'] );

	$content_report = null;
	if ( $has_markdown ) {
		$converter = new WPAgent_Markdown_To_Blocks();
		$content   = $converter->convert( (string) $input['content_markdown'] );

		$content_report          = wpagent_block_report( $content );
		$validated               = wpagent_validate_generated_core_blocks( $content );
		if ( is_wp_error( $validated ) ) {
			return $validated;
		}
		$postarr['post_content'] = $content;
		$expect['content']       = $content;
	}

	if ( array() === $expect ) {
		return new WP_Error( 'wpagent_no_fields', __( 'Kein zu aktualisierendes Feld übergeben.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}

	$res = wp_update_post( $postarr, true );
	if ( is_wp_error( $res ) ) {
		return $res;
	}

	$fresh = get_post( $block_id );

	$written  = array();
	$verified = true;
	foreach ( $expect as $field => $value ) {
		$actual = match ( $field ) {
			'title'   => $fresh->post_title,
			'content' => $fresh->post_content,
			default   => null,
		};
		$ok                = ( (string) $actual === (string) $value );
		$written[ $field ] = $ok;
		if ( ! $ok ) {
			$verified = false;
		}
	}

	$result = array(
		'block_id' => $block_id,
		'written'  => $written,
		'verified' => $verified,
	);
	if ( null !== $content_report ) {
		$result['block_count']    = $content_report['block_count'];
		$result['freeform_count'] = $content_report['freeform_count'];
		$result['block_types']    = $content_report['block_types'];
		$result['has_freeform']   = $content_report['freeform_count'] > 0;
	}

	return $result;
}
