<?php
/**
 * Ability: wp-agent/create-reusable-block
 *
 * Legt einen wiederverwendbaren Block (Post-Type wp_block) aus Markdown an.
 * Der post_type ist fest auf
 * wp_block verdrahtet, deshalb kommt hier bewusst NICHT wpagent_validate_post_type()
 * zum Einsatz: wp_block wird im WordPress-Kern mit 'public' => false registriert
 * (siehe wp-includes/post.php), und dieser generische Whitelist-Check würde jeden
 * Aufruf fälschlich mit "Post-Type nicht öffentlich" ablehnen.
 *
 * Zwei WordPress-Kern-Fallstricke, die diese Ability gezielt umschifft:
 *
 * 1. Erstell-Capability: Der WordPress-Kern mappt create_posts für wp_block NICHT
 *    auf edit_posts, sondern explizit auf die echte Capability publish_posts
 *    (Kern-Kommentar dort: "You need to be able to publish posts, in order to
 *    create blocks."). wpagent_post_type_create_cap( 'wp_block' ) löst das
 *    korrekt auf. Ein Mitwirkender (Contributor) mit edit_posts, aber ohne
 *    publish_posts, darf also KEINEN wiederverwendbaren Block anlegen, obwohl er
 *    eigene Beiträge bearbeiten kann.
 *
 * 2. post_status ist deshalb bewusst fest auf 'publish' verdrahtet und KEIN
 *    Eingabefeld: core/block referenziert einen wiederverwendbaren Block über
 *    dessen ID, und render_block_core_block() im Kern liefert für normale
 *    Besucher nur dann Inhalt, wenn der referenzierte Block den Status
 *    "publish" hat. Ein als draft angelegter Block würde auf jeder Seite, die
 *    ihn einbindet, still leer bleiben, ganz ohne Fehlermeldung. Aus demselben
 *    Grund wird hier AUCH NICHT wpagent_check_post_status_cap() aufgerufen: die
 *    darin genutzte publish-Capability für einen Post-Type wird über dessen
 *    NICHT überschriebenen Standard-Wert publish_posts -> "publish_blocks"
 *    aufgelöst, eine synthetische Capability, die im Kern an keine Rolle
 *    vergeben wird und JEDEN Aufruf ablehnen würde, selbst durch Administratoren.
 *    Die bereits oben durchgeführte create_posts-Prüfung deckt die
 *    Veröffentlichungs-Berechtigung hier vollständig ab.
 *
 * @package WPAgentCompanion
 */

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

function wpagent_ability_create_reusable_block(): array {
	return array(
		'label'               => __( 'Wiederverwendbaren Block erstellen', 'wp-agent-companion' ),
		'description'         => __( 'Legt einen wiederverwendbaren Block (wp_block) aus Markdown an. Der Server erzeugt daraus erlaubte Core-Blöcke. Wird immer veröffentlicht angelegt, damit core/block ihn sofort einbinden kann. Meldet block_count/freeform_count und verifiziert Titel und Inhalt per Re-Read.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array(
			'type'       => 'object',
			'properties' => array(
				'title'            => array(
					'type'        => 'string',
					'description' => __( 'Name des wiederverwendbaren Blocks.', 'wp-agent-companion' ),
				),
				'content_markdown' => array(
					'type'        => 'string',
					'description' => __( 'Inhalt in Markdown, wird serverseitig über WPAgent_Markdown_To_Blocks zu erlaubten Gutenberg-Core-Blöcken konvertiert.', 'wp-agent-companion' ),
				),
			),
			'required'   => array( 'title', 'content_markdown' ),
		),
		'output_schema'       => array(
			'type'       => 'object',
			'properties' => array(
				'block_id'       => array( 'type' => 'integer' ),
				'status'         => array( 'type' => 'string' ),
				'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_create_reusable_block',
		'permission_callback' => 'wpagent_perm_edit_posts',
		'meta'                => array(
			'show_in_rest' => true,
			'annotations'  => array(
				'readonly'    => false,
				'destructive' => false,
				// Jeder Aufruf legt per wp_insert_post() einen neuen wp_block an.
				// Es gibt keinen post_id-/slug-Schlüssel, der einen Retry auf
				// denselben Datensatz abbildet.
				'idempotent'  => false,
			),
		),
	);
}

/**
 * @param mixed $input
 * @return array|WP_Error
 */
function wpagent_exec_create_reusable_block( $input ) {
	$input = is_array( $input ) ? $input : array();
	$title = trim( (string) ( $input['title'] ?? '' ) );

	if ( '' === $title ) {
		return new WP_Error( 'wpagent_missing_title', __( 'Titel fehlt.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}

	// Grobe Schranke oben ist edit_posts; hier zusätzlich die für wp_block
	// tatsächlich zuständige Erstell-Capability prüfen (publish_posts, siehe
	// Datei-Kommentar oben), nicht einfach edit_posts erneut.
	if ( ! current_user_can( wpagent_post_type_create_cap( 'wp_block' ) ) ) {
		return new WP_Error( 'wpagent_forbidden', __( 'Keine Berechtigung, wiederverwendbare Blöcke zu erstellen.', 'wp-agent-companion' ), array( 'status' => 403 ) );
	}

	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 ) );
	}

	if ( ! array_key_exists( 'content_markdown', $input ) || '' === trim( (string) $input['content_markdown'] ) ) {
		return new WP_Error( 'wpagent_missing_content', __( 'content_markdown ist erforderlich.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}

	$converter = new WPAgent_Markdown_To_Blocks();
	$content   = $converter->convert( (string) $input['content_markdown'] );

	$report    = wpagent_block_report( $content );
	$validated = wpagent_validate_generated_core_blocks( $content );
	if ( is_wp_error( $validated ) ) {
		return $validated;
	}

	$postarr = array(
		'post_title'   => $title,
		'post_content' => $content,
		'post_status'  => 'publish',
		'post_type'    => 'wp_block',
	);

	$res = wp_insert_post( $postarr, true );
	if ( is_wp_error( $res ) ) {
		return $res;
	}
	$block_id = (int) $res;

	$fresh = get_post( $block_id );

	$written = array(
		'title'   => ( $fresh instanceof WP_Post && (string) $fresh->post_title === $title ),
		'content' => ( $fresh instanceof WP_Post && (string) $fresh->post_content === $content ),
	);
	$verified = ! in_array( false, $written, true );

	return array(
		'block_id'       => $block_id,
		'status'         => $fresh ? $fresh->post_status : '',
		'written'        => $written,
		'verified'       => $verified,
		'block_count'    => $report['block_count'],
		'freeform_count' => $report['freeform_count'],
		'block_types'    => $report['block_types'],
		'has_freeform'   => $report['freeform_count'] > 0,
	);
}
