<?php
/** Shared CAS, locking and recovery helpers for reusable blocks. */

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

define( 'WPAGENT_REUSABLE_BLOCK_LOCK_TTL', 60 );

/** @return WP_Post|WP_Error */
function wpagent_reusable_block_snapshot( int $block_id ) {
	clean_post_cache( $block_id );
	$block = get_post( $block_id );
	if ( ! $block instanceof WP_Post || 'wp_block' !== $block->post_type ) {
		return new WP_Error( 'wpagent_no_block', __( 'Wiederverwendbarer Block nicht gefunden.', 'wp-agent-companion' ), array( 'status' => 404 ) );
	}
	return $block;
}

/**
 * Hashes every persisted wp_block column that this ability family can observe
 * or whose concurrent mutation would make an automatic recovery unsafe.
 */
function wpagent_reusable_block_state_hash( WP_Post $block ): string {
	$state = array(
		'ID'             => (int) $block->ID,
		'post_type'      => (string) $block->post_type,
		'post_author'    => (int) $block->post_author,
		'post_title'     => (string) $block->post_title,
		'post_content'   => (string) $block->post_content,
		'post_excerpt'   => (string) $block->post_excerpt,
		'post_name'      => (string) $block->post_name,
		'post_status'    => (string) $block->post_status,
		'post_date'      => (string) $block->post_date,
		'post_date_gmt'  => (string) $block->post_date_gmt,
		'post_parent'    => (int) $block->post_parent,
		'menu_order'     => (int) $block->menu_order,
		'post_password'  => (string) $block->post_password,
		'comment_status' => (string) $block->comment_status,
		'ping_status'    => (string) $block->ping_status,
	);
	return hash( 'sha256', "wpagently-reusable-block-state-v1\0" . serialize( $state ) );
}

function wpagent_reusable_block_lock_option( int $block_id ): string {
	return 'wp_agent_reusable_block_lock_' . $block_id;
}

/** @return string|WP_Error */
function wpagent_reusable_block_acquire_lock( int $block_id ) {
	$token = wpagent_companion_acquire_option_lock( wpagent_reusable_block_lock_option( $block_id ), WPAGENT_REUSABLE_BLOCK_LOCK_TTL );
	if ( is_string( $token ) ) {
		return $token;
	}
	return new WP_Error( 'wpagent_reusable_block_locked', __( 'Dieser wiederverwendbare Block wird gerade geändert.', 'wp-agent-companion' ), array( 'status' => 409 ) );
}

function wpagent_reusable_block_release_lock( int $block_id, string $token ): void {
	wpagent_companion_release_option_lock( wpagent_reusable_block_lock_option( $block_id ), $token );
}

function wpagent_reusable_block_refresh_lock( int $block_id, string $token ): bool {
	return wpagent_companion_refresh_option_lock( wpagent_reusable_block_lock_option( $block_id ), $token, WPAGENT_REUSABLE_BLOCK_LOCK_TTL );
}

function wpagent_reusable_block_lock_is_owned( int $block_id, string $token ): bool {
	return wpagent_companion_option_lock_is_owned( wpagent_reusable_block_lock_option( $block_id ), $token );
}

/** @return string|WP_Error */
function wpagent_reusable_block_expected_hash( array $input ) {
	$hash = is_string( $input['expected_state_hash'] ?? null ) ? strtolower( $input['expected_state_hash'] ) : '';
	if ( preg_match( '/^[a-f0-9]{64}$/', $hash ) ) {
		return $hash;
	}
	return new WP_Error( 'wpagent_reusable_block_expected_hash', __( 'expected_state_hash muss der vollständige state_hash aus list-reusable-blocks sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
}

/** @return WP_Error */
function wpagent_reusable_block_conflict( string $current_hash ) {
	return new WP_Error(
		'wpagent_reusable_block_conflict',
		__( 'Der wiederverwendbare Block wurde seit dem Lesen verändert. Lies ihn neu und wiederhole den Vorgang mit dem aktuellen state_hash.', 'wp-agent-companion' ),
		array( 'status' => 409, 'current_state_hash' => $current_hash )
	);
}

/** @return WP_Error */
function wpagent_reusable_block_recovery_required( int $block_id, string $message ) {
	return new WP_Error(
		'wpagent_reusable_block_recovery_required',
		$message,
		array( 'status' => 500, 'block_id' => $block_id, 'recovery_required' => true, 'rollback_verified' => false )
	);
}
