<?php
/**
 * Core-compatible execution wrapper for Companion write-operation logging.
 *
 * @package WPAgentCompanion
 */

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

if ( class_exists( 'WP_Ability' ) && ! class_exists( 'WPAgent_Companion_Operation_Ledger_Ability' ) ) {
	class WPAgent_Companion_Operation_Ledger_Ability extends WP_Ability {
		/** @param mixed $input @return mixed */
		public function execute( $input = null ) {
			$context = wpagent_companion_activity_log_begin( $this->get_name(), $input );
			$settled = false;
			try {
				$input    = $this->normalize_input( $input );
				$is_valid = $this->validate_input( $input );
				if ( is_wp_error( $is_valid ) ) {
					wpagent_companion_activity_log_settle( $context, 'rejected' );
					$settled = true;
					return $is_valid;
				}
				$has_permissions = $this->check_permissions( $input );
				if ( true !== $has_permissions ) {
					if ( is_wp_error( $has_permissions ) ) {
						_doing_it_wrong( WP_Ability::class . '::execute', esc_html( $has_permissions->get_error_message() ), '6.9.0' );
					}
					$result = new WP_Error( 'ability_invalid_permissions', sprintf( __( 'Ability "%s" does not have necessary permission.' ), esc_html( $this->get_name() ) ) );
					wpagent_companion_activity_log_settle( $context, 'rejected' );
					$settled = true;
					return $result;
				}
				do_action( 'wp_before_execute_ability', $this->get_name(), $input );
				$result = $this->do_execute( $input );
				if ( is_wp_error( $result ) ) {
					wpagent_companion_activity_log_settle( $context, 'failed' );
					$settled = true;
					return $result;
				}
				$is_valid = $this->validate_output( $result );
				if ( is_wp_error( $is_valid ) ) {
					wpagent_companion_activity_log_settle( $context, 'failed' );
					$settled = true;
					return $is_valid;
				}
				do_action( 'wp_after_execute_ability', $this->get_name(), $input, $result );
				wpagent_companion_activity_log_settle( $context, 'succeeded' );
				$settled = true;
				return $result;
			} finally {
				if ( ! $settled ) {
					wpagent_companion_activity_log_settle( $context, 'recovery_required' );
				}
			}
		}
	}
}

/** @param array<string,mixed> $args @return array<string,mixed> */
function wpagent_companion_activity_log_instrument_write_ability( array $args, string $name ): array {
	$ability = wpagent_companion_activity_log_catalog()[ $name ] ?? null;
	if ( ! class_exists( 'WPAgent_Companion_Operation_Ledger_Ability' ) || ! is_array( $ability ) || ! array_key_exists( 'readonly', $ability ) || false !== $ability['readonly'] ) {
		return $args;
	}
	$args['ability_class'] = 'WPAgent_Companion_Operation_Ledger_Ability';
	return $args;
}
add_filter( 'wp_register_ability_args', 'wpagent_companion_activity_log_instrument_write_ability', 20, 2 );
