<?php
/**
 * Ability: wp-agent/update-post
 *
 * @package WPAgentCompanion
 */

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

define( 'WPAGENT_UPDATE_POST_LOCK_TTL', 300 );

/**
 * Shared by the post/media mutations that can safely use a provider-specific
 * compare-and-set. update-post itself is deliberately not a remote writer.
 */
function wpagent_update_post_lock_name( int $post_id ): string {
	return 'wp_agent_update_post_lock_' . $post_id;
}

/** @return string|WP_Error */
function wpagent_update_post_acquire_lock( int $post_id ) {
	$name  = wpagent_update_post_lock_name( $post_id );
	$token = wpagent_companion_acquire_option_lock( $name, WPAGENT_UPDATE_POST_LOCK_TTL );
	if ( is_string( $token ) ) {
		return $token;
	}
	return new WP_Error( 'wpagent_post_busy', __( 'Dieser Beitrag wird gerade geändert. Versuche es gleich erneut.', 'wp-agent-companion' ), array( 'status' => 409 ) );
}

function wpagent_update_post_release_lock( int $post_id, string $token ): void {
	wpagent_companion_release_option_lock( wpagent_update_post_lock_name( $post_id ), $token );
}

/** Refreshes the post-scoped write lock before a mutation or rollback. */
function wpagent_update_post_refresh_lock( int $post_id, string $token ): bool {
	return wpagent_companion_refresh_option_lock( wpagent_update_post_lock_name( $post_id ), $token, WPAGENT_UPDATE_POST_LOCK_TTL );
}

/** Proves that a Core post writer still owns its scoped lock. */
function wpagent_update_post_lock_is_owned( int $post_id, string $token ): bool {
	return wpagent_companion_option_lock_is_owned( wpagent_update_post_lock_name( $post_id ), $token );
}

function wpagent_ability_update_post(): array {
	return array(
		'label'               => __( 'Beitrag aktualisieren', 'wp-agent-companion' ),
		'description'         => __( 'Das ferngesteuerte Ändern eines Beitrags ist nicht verfügbar. WordPress verarbeitet Beitragsänderungen über Prewrite-Filter und Seiteneffekte, die ohne eine atomare Core-Compare-and-Set-Operation nicht konfliktfrei mit dem state_hash verbunden werden können. Ändere Beiträge lokal in einer beaufsichtigten Administration.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array(
			'type'       => 'object',
			'properties' => array(
				'post_id'             => array( 'type' => 'integer' ),
				'expected_state_hash' => array(
					'type'        => 'string',
					'pattern'     => '^[a-f0-9]{64}$',
					'description' => __( 'Exakter state_hash aus get-post.', 'wp-agent-companion' ),
				),
				'title'            => array( 'type' => 'string' ),
				'content_markdown' => array( 'type' => 'string' ),
				'excerpt'          => array( 'type' => 'string' ),
				'slug'             => array( 'type' => 'string' ),
				'status'           => array(
					'type' => 'string',
					'enum' => array( 'draft', 'publish', 'pending', 'private', 'future' ),
				),
				'date'             => array( 'type' => 'string' ),
				'menu_order'       => array( 'type' => 'integer' ),
				'parent'           => array( 'type' => 'integer' ),
			),
			'required'   => array( 'post_id', 'expected_state_hash' ),
		),
		'output_schema'       => array(
			'type'       => 'object',
			'properties' => array(
				'post_id'             => array( 'type' => 'integer' ),
				'post_type'           => array( 'type' => 'string' ),
				'written'             => array(
					'type'                 => 'object',
					'properties'           => array(
						'title'      => array( 'type' => 'boolean' ),
						'content'    => array( 'type' => 'boolean' ),
						'excerpt'    => array( 'type' => 'boolean' ),
						'slug'       => array( 'type' => 'boolean' ),
						'status'     => array( 'type' => 'boolean' ),
						'date'       => array( 'type' => 'boolean' ),
						'menu_order' => array( 'type' => 'boolean' ),
						'parent'     => array( 'type' => 'boolean' ),
					),
					'additionalProperties' => false,
				),
				'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' ),
				'previous_state_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
				'state_hash'          => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
			),
		),
		'execute_callback'    => 'wpagent_exec_update_post',
		'permission_callback' => 'wpagent_perm_edit_posts',
		'meta'                => array(
			'show_in_rest' => true,
			'annotations'  => array(
				'readonly'    => false,
				'destructive' => false,
				'idempotent'  => false,
				'manual_only' => true,
			),
		),
	);
}

/** @return WP_Error */
function wpagent_post_update_manual_write_required(): WP_Error {
	return new WP_Error(
		'wpagent_post_update_manual_write_required',
		__( 'Das ferngesteuerte Ändern eines Beitrags ist nicht verfügbar. WordPress verarbeitet Beitragsänderungen über Prewrite-Filter und Seiteneffekte, die ohne eine atomare Core-Compare-and-Set-Operation nicht konfliktfrei mit dem state_hash verbunden werden können. Ändere den Beitrag lokal in einer beaufsichtigten Administration und lies ihn anschließend neu.', 'wp-agent-companion' ),
		array( 'status' => 409, 'manual_only' => true, 'recovery_required' => false )
	);
}

/**
 * @param mixed $input
 * @return WP_Error
 */
function wpagent_exec_update_post( $input ) {
	return wpagent_post_update_manual_write_required();
}

/**
 * Returns an uncached post snapshot for the post/media writers that retain a
 * provider-level compare-and-set implementation.
 */
function wpagent_update_post_fresh( int $post_id ): ?WP_Post {
	clean_post_cache( $post_id );
	wp_cache_delete( $post_id, 'post_meta' );
	$post = get_post( $post_id );
	return $post instanceof WP_Post ? $post : null;
}
