<?php
/**
 * Minimal WordPress test doubles for feedback helper tests.
 *
 * @package GravityOps\Core
 */

/**
 * Sanitizes a text value for tests.
 *
 * @param mixed $value Input value.
 *
 * @return string
 */
function sanitize_text_field( $value ): string {
	return trim( (string) $value );
}

/**
 * Sanitizes textarea content for tests.
 *
 * @param mixed $value Input value.
 *
 * @return string
 */
function sanitize_textarea_field( $value ): string {
	return trim( (string) $value );
}

/**
 * Returns a test admin URL.
 *
 * @param string $path Relative admin path.
 *
 * @return string
 */
function admin_url( string $path = '' ): string {
	return 'https://example.test/wp-admin/' . ltrim( $path, '/' );
}

/**
 * Sanitizes an identifier key.
 *
 * @param mixed $value Input value.
 *
 * @return string
 */
function sanitize_key( $value ): string {
	return strtolower( preg_replace( '/[^a-z0-9_\-]/', '', (string) $value ) );
}

/**
 * Returns a test value without slashes.
 *
 * @param mixed $value Input value.
 *
 * @return mixed
 */
function wp_unslash( $value ) {
	return $value;
}

/**
 * Returns an absolute integer.
 *
 * @param mixed $value Input value.
 *
 * @return int
 */
function absint( $value ): int {
	return abs( (int) $value );
}

/**
 * Checks a capability against the current test list.
 *
 * @param string $capability Capability name.
 *
 * @return bool
 */
function current_user_can( string $capability ): bool {
	return in_array( $capability, $GLOBALS['_test_caps'] ?? [], true );
}

/**
 * Returns an option from test storage.
 *
 * @param string $name          Option name.
 * @param mixed  $default_value Default value.
 *
 * @return mixed
 */
function get_option( string $name, $default_value = false ) {
	return $GLOBALS['_test_options'][ $name ] ?? $default_value;
}

/**
 * Stores an option in test storage.
 *
 * @param string $name  Option name.
 * @param mixed  $value Option value.
 *
 * @return bool
 */
function update_option( string $name, $value ): bool {
	$GLOBALS['_test_options'][ $name ] = $value;

	return true;
}

/**
 * Deletes an option from test storage.
 *
 * @param string $name Option name.
 *
 * @return bool
 */
function delete_option( string $name ): bool {
	unset( $GLOBALS['_test_options'][ $name ] );

	return true;
}

/**
 * Registers a callback in test storage.
 *
 * @param string   $hook          Hook name.
 * @param callable $callback      Hook callback.
 * @param int      $priority      Hook priority.
 * @param int      $accepted_args Accepted argument count.
 *
 * @return bool
 */
function add_action( string $hook, $callback, int $priority = 10, int $accepted_args = 1 ): bool {
	$GLOBALS['_test_actions'][ $hook ][] = [
		'callback'      => $callback,
		'priority'      => $priority,
		'accepted_args' => $accepted_args,
	];

	return true;
}

/**
 * Returns a scheduled test timestamp.
 *
 * @param string $hook Hook name.
 *
 * @return int|false
 */
function wp_next_scheduled( string $hook ) {
	return $GLOBALS['_test_scheduled'][ $hook ] ?? false;
}

/**
 * Clears a scheduled test hook.
 *
 * @param string $hook Hook name.
 *
 * @return int
 */
function wp_clear_scheduled_hook( string $hook ): int {
	$GLOBALS['_test_cleared_schedules'][] = $hook;
	unset( $GLOBALS['_test_scheduled'][ $hook ] );

	return 1;
}

/**
 * Creates a deterministic nonce.
 *
 * @param string $action Nonce action.
 *
 * @return string
 */
function wp_create_nonce( string $action ): string {
	return 'nonce-' . $action;
}

/**
 * Verifies a deterministic nonce.
 *
 * @param string $nonce  Nonce value.
 * @param string $action Nonce action.
 *
 * @return int|false
 */
function wp_verify_nonce( string $nonce, string $action ) {
	return hash_equals( wp_create_nonce( $action ), $nonce ) ? 1 : false;
}

/**
 * Returns the test site URL.
 *
 * @return string
 */
function get_site_url(): string {
	return 'https://example.test';
}

/**
 * Records and returns a test HTTP response.
 *
 * @param string $url       Request URL.
 * @param array  $arguments Request arguments.
 *
 * @return array|WP_Error
 */
function wp_remote_post( string $url, array $arguments = [] ) {
	$GLOBALS['_test_remote_posts'][] = [ $url, $arguments ];

	return $GLOBALS['_test_remote_response'] ?? [
		'response' => [ 'code' => 200 ],
		'body'     => '{}',
	];
}

/**
 * Returns a test HTTP status code.
 *
 * @param mixed $response HTTP response.
 *
 * @return int
 */
function wp_remote_retrieve_response_code( $response ): int {
	return absint( $response['response']['code'] ?? 0 );
}

/**
 * Returns a test HTTP response body.
 *
 * @param mixed $response HTTP response.
 *
 * @return string
 */
function wp_remote_retrieve_body( $response ): string {
	return (string) ( $response['body'] ?? '' );
}

/**
 * Checks whether a value is a WordPress error.
 *
 * @param mixed $value Test value.
 *
 * @return bool
 */
function is_wp_error( $value ): bool {
	return $value instanceof WP_Error;
}

/**
 * Escapes an HTML attribute for tests.
 *
 * @param mixed $value Input value.
 *
 * @return string
 */
function esc_attr( $value ): string {
	return htmlspecialchars( (string) $value, ENT_QUOTES, 'UTF-8' );
}

/**
 * Escapes HTML for tests.
 *
 * @param mixed $value Input value.
 *
 * @return string
 */
function esc_html( $value ): string {
	return esc_attr( $value );
}

/**
 * Escapes a URL for tests.
 *
 * @param mixed $value Input value.
 *
 * @return string
 */
function esc_url( $value ): string {
	return esc_attr( $value );
}

/**
 * Renders a deterministic nonce field.
 *
 * @param string $action Nonce action.
 * @param string $name   Field name.
 *
 * @return void
 */
function wp_nonce_field( string $action, string $name ): void {
	echo '<input type="hidden" name="' . esc_attr( $name ) . '" value="' . esc_attr( wp_create_nonce( $action ) ) . '">';
}

/**
 * Throws a failed JSON response for tests.
 *
 * @param array $data        Response data.
 * @param int   $status_code HTTP status.
 *
 * @return void
 * @throws TestJsonResponse Always.
 */
function wp_send_json_error( array $data = [], int $status_code = 200 ): void {
	throw new TestJsonResponse( $data, $status_code, false ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Test response transport.
}

/**
 * Throws a successful JSON response for tests.
 *
 * @param array $data        Response data.
 * @param int   $status_code HTTP status.
 *
 * @throws TestJsonResponse Always.
 */
function wp_send_json_success( array $data = [], int $status_code = 200 ): void {
	throw new TestJsonResponse( $data, $status_code, true ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Test response transport.
}
