<?php
/**
 * Verified, narrow SEOPress Free redirections for published posts.
 *
 * Provider writes always go through SEOPress' own REST endpoint. The raw
 * post-meta snapshot binds state hashes and detects mutations that cannot be
 * attributed solely to this ability. It is intentionally never auto-restored:
 * external WordPress writers do not participate in this ability's lock.
 */

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

define( 'WPAGENT_SEOPRESS_POST_REDIRECTION_LOCK_TTL', 300 );
define( 'WPAGENT_SEOPRESS_POST_REDIRECTION_MAX_RECORDS', 1000 );
define( 'WPAGENT_SEOPRESS_POST_REDIRECTION_MAX_RAW_VALUE_BYTES', 65536 );
define( 'WPAGENT_SEOPRESS_POST_REDIRECTION_MAX_RAW_TOTAL_BYTES', 262144 );
define( 'WPAGENT_SEOPRESS_POST_REDIRECTION_MAX_GRAPH_ROWS', 6001 );
define( 'WPAGENT_SEOPRESS_POST_REDIRECTION_MAX_GRAPH_BYTES', 1048576 );
define( 'WPAGENT_SEOPRESS_REDIRECTION_GRAPH_LOCK_OPTION', 'wp_agent_seopress_redirection_graph_lock' );

/** @return array<int,string> */
function wpagent_seopress_post_redirection_meta_keys(): array {
	return array(
		'_seopress_redirections_enabled',
		'_seopress_redirections_type',
		'_seopress_redirections_value',
		'_seopress_redirections_enabled_regex',
		'_seopress_redirections_logged_status',
		'_seopress_redirections_param',
	);
}

function wpagent_perm_edit_seopress_post_redirection( $input = null ): bool {
	$post_id = is_array( $input ) ? absint( $input['post_id'] ?? 0 ) : 0;
	return $post_id > 0 && current_user_can( 'edit_post', $post_id );
}

function wpagent_seopress_post_redirection_pro_runtime_detected(): bool {
	if ( defined( 'SEOPRESS_PRO_VERSION' ) ) {
		return true;
	}
	$pro_plugin = 'wp-seopress-pro/seopress-pro.php';
	if ( in_array( $pro_plugin, (array) get_option( 'active_plugins', array() ), true ) ) {
		return true;
	}
	return is_multisite() && in_array( $pro_plugin, array_keys( (array) get_site_option( 'active_sitewide_plugins', array() ) ), true );
}

/** @return true|WP_Error */
function wpagent_seopress_post_redirection_runtime() {
	if ( ! defined( 'SEOPRESS_VERSION' ) || ! function_exists( 'seopress_get_service' ) ) {
		return new WP_Error( 'wpagent_seopress_redirection_unavailable', __( 'SEOPress ist nicht aktiv.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	if ( wpagent_seopress_post_redirection_pro_runtime_detected() ) {
		return new WP_Error( 'wpagent_seopress_redirection_provider_untrusted', __( 'SEOPress Pro ist aktiv. Diese Ability arbeitet ausschließlich mit dem verifizierten SEOPress-Free-Provider.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	return true;
}

/** @return true|WP_Error */
function wpagent_seopress_post_redirection_route_is_trusted( string $method ) {
	$method = strtoupper( $method );
	if ( ! in_array( $method, array( 'GET', 'PUT' ), true ) ) {
		return new WP_Error( 'wpagent_seopress_redirection_provider_untrusted', __( 'SEOPress stellt keine vertrauenswürdige native Weiterleitungsroute bereit.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$root = realpath( WP_PLUGIN_DIR . '/wp-seopress' );
	if ( false === $root || ! defined( 'SEOPRESS_VERSION' ) || ! preg_match( '/^10\.1(?:\.|$)/', (string) SEOPRESS_VERSION ) || wpagent_seopress_post_redirection_pro_runtime_detected() ) {
		return new WP_Error( 'wpagent_seopress_redirection_provider_untrusted', __( 'SEOPress stellt keine vertrauenswürdige native Weiterleitungsroute bereit.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$route = '/seopress/v1/posts/(?P<id>\d+)/redirection-settings';
	try {
		$routes = rest_get_server()->get_routes();
	} catch ( Throwable $error ) {
		return new WP_Error( 'wpagent_seopress_redirection_provider_untrusted', __( 'SEOPress stellt keine vertrauenswürdige native Weiterleitungsroute bereit.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$handlers = is_array( $routes ) ? ( $routes[ $route ] ?? array() ) : array();
	$matches  = array();
	foreach ( $handlers as $handler ) {
		if ( ! is_array( $handler ) ) {
			continue;
		}
		$methods = is_array( $handler['methods'] ?? null )
			? array_map( 'strtoupper', array_keys( array_filter( $handler['methods'] ) ) )
			: array();
		if ( in_array( $method, $methods, true ) ) {
			$matches[] = $handler['callback'] ?? null;
		}
	}
	$expected_method = 'GET' === $method ? 'processGet' : 'processPut';
	$callback        = 1 === count( $matches ) ? $matches[0] : null;
	if ( ! is_array( $callback ) || 2 !== count( $callback ) || ! is_object( $callback[0] ) || ! is_string( $callback[1] )
		|| 'SEOPress\\Actions\\Api\\Metas\\RedirectionSettings' !== get_class( $callback[0] ) || $expected_method !== $callback[1] ) {
		return new WP_Error( 'wpagent_seopress_redirection_provider_untrusted', __( 'SEOPress stellt keine vertrauenswürdige native Weiterleitungsroute bereit.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	try {
		$file = realpath( (string) ( new ReflectionMethod( $callback[0], $callback[1] ) )->getFileName() );
	} catch ( Throwable $error ) {
		$file = false;
	}
	$root = trailingslashit( wp_normalize_path( $root ) );
	if ( false === $file || ! str_starts_with( wp_normalize_path( $file ), $root ) ) {
		return new WP_Error( 'wpagent_seopress_redirection_provider_untrusted', __( 'SEOPress stellt keine vertrauenswürdige native Weiterleitungsroute bereit.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	return true;
}

/** @return array{post:WP_Post,source:string}|WP_Error */
function wpagent_seopress_post_redirection_target( int $post_id ) {
	$post = get_post( $post_id );
	if ( ! $post instanceof WP_Post ) {
		return new WP_Error( 'wpagent_seopress_redirection_not_found', __( 'Der Beitrag für die Weiterleitung wurde nicht gefunden.', 'wp-agent-companion' ), array( 'status' => 404 ) );
	}
	$type = get_post_type_object( $post->post_type );
	if ( ! $type instanceof WP_Post_Type || ! is_post_type_viewable( $type ) || 'publish' !== $post->post_status ) {
		return new WP_Error( 'wpagent_seopress_redirection_not_public', __( 'Weiterleitungen sind nur für veröffentlichte Beiträge öffentlicher Post-Typen verfügbar.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	if ( ! current_user_can( 'edit_post', $post_id ) ) {
		return new WP_Error( 'wpagent_seopress_redirection_forbidden', __( 'Keine Berechtigung für diese SEOPress-Weiterleitung.', 'wp-agent-companion' ), array( 'status' => 403 ) );
	}
	$source = get_permalink( $post );
	if ( ! is_string( $source ) || '' === $source ) {
		return new WP_Error( 'wpagent_seopress_redirection_source_invalid', __( 'SEOPress konnte keine sichere Beitrags-URL als Weiterleitungsquelle bestimmen.', 'wp-agent-companion' ), array( 'status' => 502 ) );
	}
	$validated_source = wpagent_seopress_post_redirection_source_path( $source );
	if ( is_wp_error( $validated_source ) ) {
		return $validated_source;
	}
	return array( 'post' => $post, 'source' => $source );
}

/** @return array{scheme:string,host:string,port:int,path:string}|WP_Error */
function wpagent_seopress_post_redirection_home_endpoint() {
	$parts = wp_parse_url( home_url( '/' ) );
	if ( false === $parts || ! isset( $parts['scheme'], $parts['host'] ) || ! in_array( strtolower( (string) $parts['scheme'] ), array( 'http', 'https' ), true ) ) {
		return new WP_Error( 'wpagent_seopress_redirection_home_invalid', __( 'Die Site-URL ist für sichere SEOPress-Weiterleitungen ungeeignet.', 'wp-agent-companion' ), array( 'status' => 502 ) );
	}
	$path = '/' . trim( (string) ( $parts['path'] ?? '' ), '/' );
	return array(
		'scheme' => strtolower( (string) $parts['scheme'] ),
		'host' => strtolower( rtrim( (string) $parts['host'], '.' ) ),
		'port' => absint( $parts['port'] ?? 0 ),
		'path' => '/' === $path ? '' : untrailingslashit( $path ),
	);
}

/** @return string|WP_Error */
function wpagent_seopress_post_redirection_source_path( string $source ) {
	$home  = wpagent_seopress_post_redirection_home_endpoint();
	$parts = wp_parse_url( $source );
	if ( is_wp_error( $home ) || false === $parts || ! isset( $parts['scheme'], $parts['host'], $parts['path'] )
		|| isset( $parts['user'] ) || isset( $parts['pass'] ) || isset( $parts['query'] ) || isset( $parts['fragment'] )
		|| strtolower( (string) $parts['scheme'] ) !== $home['scheme']
		|| strtolower( rtrim( (string) $parts['host'], '.' ) ) !== $home['host']
		|| absint( $parts['port'] ?? 0 ) !== $home['port']
		|| '' === esc_url_raw( $source, array( 'http', 'https' ) ) ) {
		return new WP_Error( 'wpagent_seopress_redirection_source_invalid', __( 'Die Beitrags-URL liegt nicht auf der aktuellen WordPress-Site.', 'wp-agent-companion' ), array( 'status' => 502 ) );
	}
	$path = wpagent_seopress_post_redirection_site_path( (string) $parts['path'], $home );
	return is_wp_error( $path )
		? new WP_Error( 'wpagent_seopress_redirection_source_invalid', __( 'Die Beitrags-URL enthält einen nicht sicheren lokalen Pfad.', 'wp-agent-companion' ), array( 'status' => 502 ) )
		: $path;
}

/** @return string|null */
function wpagent_seopress_post_redirection_canonical_path( string $path ): ?string {
	if ( '' === $path || '/' !== $path[0] || str_starts_with( $path, '//' ) || strlen( $path ) > 2048
		|| ! wp_is_valid_utf8( $path ) || preg_match( '/[\x00-\x1F\x7F\\\\]/u', $path )
		|| preg_match( '/%(?:00|0a|0d|2f|5c|3f|23)/i', $path ) ) {
		return null;
	}
	$decoded = rawurldecode( $path );
	if ( ! wp_is_valid_utf8( $decoded ) || preg_match( '/[\x00-\x1F\x7F\\\\]/u', $decoded )
		|| false !== strpbrk( $decoded, '?#%' ) || false !== strpos( substr( $decoded, 1 ), '//' ) ) {
		return null;
	}
	foreach ( explode( '/', $decoded ) as $segment ) {
		if ( '.' === $segment || '..' === $segment ) {
			return null;
		}
	}
	return '/' === $decoded ? '/' : untrailingslashit( $decoded );
}

/** @return string|WP_Error */
function wpagent_seopress_post_redirection_site_path( string $path, array $home ) {
	$canonical = wpagent_seopress_post_redirection_canonical_path( $path );
	if ( null === $canonical ) {
		return new WP_Error( 'wpagent_seopress_redirection_destination_invalid', __( 'destination enthält einen mehrdeutigen oder nicht erlaubten lokalen Pfad.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$base = (string) $home['path'];
	if ( '' === $base ) {
		return $canonical;
	}
	if ( $base !== $canonical && ! str_starts_with( $canonical, $base . '/' ) ) {
		return new WP_Error( 'wpagent_seopress_redirection_destination_invalid', __( 'destination gehört nicht zur aktuellen WordPress-Site.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$relative = substr( $canonical, strlen( $base ) );
	return '' === $relative ? '/' : $relative;
}

/** @return string|WP_Error */
function wpagent_seopress_post_redirection_validate_destination( $value, string $source ) {
	if ( ! is_string( $value ) || '' === $value || strlen( $value ) > 4096 || ! wp_is_valid_utf8( $value ) || preg_match( '/[\x00-\x1F\x7F\\\\]/u', $value ) ) {
		return new WP_Error( 'wpagent_seopress_redirection_destination_invalid', __( 'destination muss eine nicht leere lokale HTTP- oder HTTPS-URL sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$home = wpagent_seopress_post_redirection_home_endpoint();
	if ( is_wp_error( $home ) ) {
		return $home;
	}
	if ( str_starts_with( $value, '/' ) ) {
		if ( str_starts_with( $value, '//' ) || false !== strpbrk( $value, '?#' ) ) {
			return new WP_Error( 'wpagent_seopress_redirection_destination_invalid', __( 'destination darf weder eine Protokoll-relative URL noch Query oder Fragment enthalten.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$relative = wpagent_seopress_post_redirection_site_path( $value, $home );
		if ( is_wp_error( $relative ) ) {
			return $relative;
		}
		$absolute = home_url( $relative );
	} else {
		$parts = wp_parse_url( $value );
		if ( false === $parts || ! isset( $parts['scheme'], $parts['host'], $parts['path'] )
			|| ! in_array( strtolower( (string) $parts['scheme'] ), array( 'http', 'https' ), true )
			|| isset( $parts['user'] ) || isset( $parts['pass'] ) || isset( $parts['query'] ) || isset( $parts['fragment'] )
			|| strtolower( (string) $parts['scheme'] ) !== $home['scheme']
			|| strtolower( rtrim( (string) $parts['host'], '.' ) ) !== $home['host']
			|| absint( $parts['port'] ?? 0 ) !== $home['port'] ) {
			return new WP_Error( 'wpagent_seopress_redirection_destination_invalid', __( 'destination muss zur selben WordPress-Site gehören und darf weder Zugangsdaten, Portabweichungen, Query noch Fragment enthalten.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$relative = wpagent_seopress_post_redirection_site_path( (string) $parts['path'], $home );
		if ( is_wp_error( $relative ) ) {
			return $relative;
		}
		$absolute = home_url( $relative );
	}
	$sanitized = esc_url_raw( $absolute, array( 'http', 'https' ) );
	if ( '' === $sanitized || $sanitized !== $absolute ) {
		return new WP_Error( 'wpagent_seopress_redirection_destination_invalid', __( 'destination enthält nicht erlaubte URL-Bestandteile.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$source_path = wpagent_seopress_post_redirection_source_path( $source );
	$target_parts = wp_parse_url( $absolute );
	if ( is_wp_error( $source_path ) || false === $target_parts || (string) ( $target_parts['path'] ?? '' ) === '' ) {
		return new WP_Error( 'wpagent_seopress_redirection_source_invalid', __( 'Die Beitrags-URL kann nicht sicher mit dem Weiterleitungsziel verglichen werden.', 'wp-agent-companion' ), array( 'status' => 502 ) );
	}
	$target_path = wpagent_seopress_post_redirection_site_path( (string) $target_parts['path'], $home );
	if ( is_wp_error( $target_path ) ) {
		return new WP_Error( 'wpagent_seopress_redirection_source_invalid', __( 'Die Beitrags-URL enthält einen nicht sicheren lokalen Pfad.', 'wp-agent-companion' ), array( 'status' => 502 ) );
	}
	if ( $source_path === $target_path ) {
		return new WP_Error( 'wpagent_seopress_redirection_self_loop', __( 'Eine SEOPress-Weiterleitung darf nicht auf ihre eigene Beitrags-URL zeigen.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	return $absolute;
}

/** @return array<int,array{meta_id:int,meta_key:string,meta_value:string}>|WP_Error */
function wpagent_seopress_post_redirection_capture_raw( int $post_id ) {
	global $wpdb;
	$prefix = $wpdb->esc_like( '_seopress_redirections_' ) . '%';
	$rows   = $wpdb->get_results(
		$wpdb->prepare(
			"SELECT meta_id, meta_key, meta_value FROM {$wpdb->postmeta} WHERE post_id = %d AND meta_key LIKE %s ORDER BY meta_id ASC LIMIT %d",
			$post_id,
			$prefix,
			WPAGENT_SEOPRESS_POST_REDIRECTION_MAX_RECORDS + 1
		),
		ARRAY_A
	);
	if ( ! is_array( $rows ) ) {
		return new WP_Error( 'wpagent_seopress_redirection_snapshot_failed', __( 'Der rohe SEOPress-Weiterleitungszustand konnte nicht gesichert werden.', 'wp-agent-companion' ), array( 'status' => 502 ) );
	}
	if ( count( $rows ) > WPAGENT_SEOPRESS_POST_REDIRECTION_MAX_RECORDS ) {
		return new WP_Error( 'wpagent_seopress_redirection_snapshot_limit', __( 'Der SEOPress-Weiterleitungszustand enthält zu viele Einträge für eine sichere Verifikation.', 'wp-agent-companion' ), array( 'status' => 413 ) );
	}
	$snapshot = array();
	$total    = 0;
	foreach ( $rows as $row ) {
		if ( ! is_array( $row ) || ! isset( $row['meta_id'], $row['meta_key'], $row['meta_value'] ) || ! str_starts_with( (string) $row['meta_key'], '_seopress_redirections_' ) ) {
			return new WP_Error( 'wpagent_seopress_redirection_snapshot_invalid', __( 'SEOPress enthält einen nicht sicher lesbaren Weiterleitungszustand.', 'wp-agent-companion' ), array( 'status' => 502 ) );
		}
		$value_bytes = strlen( (string) $row['meta_value'] );
		$total      += strlen( (string) $row['meta_key'] ) + $value_bytes;
		if ( $value_bytes > WPAGENT_SEOPRESS_POST_REDIRECTION_MAX_RAW_VALUE_BYTES || $total > WPAGENT_SEOPRESS_POST_REDIRECTION_MAX_RAW_TOTAL_BYTES ) {
			return new WP_Error( 'wpagent_seopress_redirection_snapshot_limit', __( 'Der SEOPress-Weiterleitungszustand ist für eine sichere Verifikation zu groß.', 'wp-agent-companion' ), array( 'status' => 413 ) );
		}
		$snapshot[] = array(
			'meta_id'    => absint( $row['meta_id'] ),
			'meta_key'   => (string) $row['meta_key'],
			'meta_value' => (string) $row['meta_value'],
		);
	}
	return $snapshot;
}

/** @return array<string,mixed>|WP_Error */
function wpagent_seopress_post_redirection_provider_request( int $post_id, string $method, array $params = array() ) {
	$trusted = wpagent_seopress_post_redirection_route_is_trusted( $method );
	if ( is_wp_error( $trusted ) ) {
		return $trusted;
	}
	$request = new WP_REST_Request( $method, '/seopress/v1/posts/' . $post_id . '/redirection-settings' );
	foreach ( $params as $key => $value ) {
		$request->set_param( $key, $value );
	}
	$response = rest_do_request( $request );
	if ( ! $response instanceof WP_REST_Response ) {
		return new WP_Error( 'wpagent_seopress_redirection_provider_failed', __( 'SEOPress lieferte keine gültige REST-Antwort.', 'wp-agent-companion' ), array( 'status' => 502 ) );
	}
	$status = $response->get_status();
	if ( $status >= 200 && $status < 300 ) {
		return array( 'data' => $response->get_data(), 'status' => $status );
	}
	if ( 404 === $status ) {
		return new WP_Error( 'wpagent_seopress_redirection_unavailable', __( 'SEOPress stellt die benötigte native Weiterleitungs-REST-Schnittstelle nicht bereit.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	return new WP_Error( 'wpagent_seopress_redirection_provider_failed', __( 'SEOPress hat die Weiterleitungs-REST-Anfrage abgelehnt.', 'wp-agent-companion' ), array( 'status' => 502, 'provider_status' => $status ) );
}

/** @return array<string,mixed>|WP_Error */
function wpagent_seopress_post_redirection_read( int $post_id, string $source ) {
	$raw = wpagent_seopress_post_redirection_capture_raw( $post_id );
	if ( is_wp_error( $raw ) ) {
		return $raw;
	}
	foreach ( wpagent_seopress_post_redirection_meta_keys() as $key ) {
		$count = count( array_filter( $raw, static fn( array $row ): bool => $key === $row['meta_key'] ) );
		if ( $count > 1 ) {
			return new WP_Error( 'wpagent_seopress_redirection_provider_state_invalid', __( 'SEOPress enthält doppelte Weiterleitungswerte. Der Schreibpfad bleibt geschlossen.', 'wp-agent-companion' ), array( 'status' => 409, 'meta_key' => $key ) );
		}
	}
	$provider = wpagent_seopress_post_redirection_provider_request( $post_id, 'GET' );
	if ( is_wp_error( $provider ) ) {
		return $provider;
	}
	$fields = array();
	foreach ( (array) $provider['data'] as $item ) {
		if ( is_array( $item ) && isset( $item['key'] ) && is_string( $item['key'] ) ) {
			if ( array_key_exists( $item['key'], $fields ) ) {
				return new WP_Error( 'wpagent_seopress_redirection_provider_state_invalid', __( 'SEOPress lieferte doppelte Pflichtfelder für die Weiterleitung.', 'wp-agent-companion' ), array( 'status' => 502, 'meta_key' => $item['key'] ) );
			}
			$fields[ $item['key'] ] = $item['value'] ?? null;
		}
	}
	$enabled = $fields['_seopress_redirections_enabled'] ?? null;
	$type    = $fields['_seopress_redirections_type'] ?? null;
	$value   = $fields['_seopress_redirections_value'] ?? null;
	$login   = $fields['_seopress_redirections_logged_status'] ?? null;
	if ( ! is_bool( $enabled ) || ! is_numeric( $type ) || ! is_string( $value ) || ! is_string( $login )
		|| ! in_array( (int) $type, array( 301, 302, 307 ), true ) ) {
		return new WP_Error( 'wpagent_seopress_redirection_provider_state_invalid', __( 'SEOPress lieferte einen unbestätigten Weiterleitungszustand.', 'wp-agent-companion' ), array( 'status' => 502 ) );
	}
	if ( 'both' !== $login ) {
		return new WP_Error( 'wpagent_seopress_redirection_conditional_unsupported', __( 'SEOPress-Weiterleitungen mit Anmeldebedingung werden nicht verändert.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$destination = '';
	if ( '' !== $value ) {
		$destination = wpagent_seopress_post_redirection_validate_destination( $value, $source );
		if ( is_wp_error( $destination ) ) {
			return new WP_Error( 'wpagent_seopress_redirection_provider_state_invalid', __( 'SEOPress enthält ein nicht sicher verwaltbares Weiterleitungsziel.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
	}
	$state = array(
		'post_id'     => $post_id,
		'provider'    => 'seopress',
		'source'      => $source,
		'destination' => $destination,
		'http_code'   => (int) $type,
		'enabled'     => $enabled,
		'login_status' => $login,
	);
	$state['state_hash'] = hash( 'sha256', (string) wp_json_encode( array( 'blog_id' => get_current_blog_id(), 'state' => $state, 'raw' => $raw ), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) );
	return array( 'state' => $state, 'raw' => $raw );
}

function wpagent_seopress_post_redirection_lock_option( int $post_id ): string {
	return 'wp_agent_seopress_redirection_lock_' . $post_id;
}

function wpagent_seopress_post_redirection_lock_owned( string $option, string $token ): bool {
	return wpagent_companion_option_lock_is_owned( $option, $token );
}

function wpagent_seopress_post_redirection_refresh_lock_option( string $option, string $token ): bool {
	return wpagent_companion_refresh_option_lock( $option, $token, WPAGENT_SEOPRESS_POST_REDIRECTION_LOCK_TTL );
}

/** @return string|WP_Error */
function wpagent_seopress_post_redirection_acquire_lock( int $post_id ) {
	$option = wpagent_seopress_post_redirection_lock_option( $post_id );
	$token  = wpagent_companion_acquire_option_lock( $option, WPAGENT_SEOPRESS_POST_REDIRECTION_LOCK_TTL );
	if ( is_string( $token ) ) {
		return $token;
	}
	return new WP_Error( 'wpagent_seopress_redirection_locked', __( 'Diese SEOPress-Weiterleitung wird gerade geändert. Bitte erneut versuchen.', 'wp-agent-companion' ), array( 'status' => 409 ) );
}

function wpagent_seopress_post_redirection_release_lock( int $post_id, string $token ): void {
	wpagent_companion_release_option_lock( wpagent_seopress_post_redirection_lock_option( $post_id ), $token );
}

function wpagent_seopress_post_redirection_refresh_lock( int $post_id, string $token ): bool {
	return wpagent_seopress_post_redirection_refresh_lock_option( wpagent_seopress_post_redirection_lock_option( $post_id ), $token );
}

/** @return string|WP_Error */
function wpagent_seopress_post_redirection_acquire_graph_lock() {
	$token = wpagent_companion_acquire_option_lock( WPAGENT_SEOPRESS_REDIRECTION_GRAPH_LOCK_OPTION, WPAGENT_SEOPRESS_POST_REDIRECTION_LOCK_TTL );
	if ( is_string( $token ) ) {
		return $token;
	}
	return new WP_Error( 'wpagent_seopress_redirection_graph_locked', __( 'SEOPress-Weiterleitungen werden gerade geprüft oder geändert. Bitte erneut versuchen.', 'wp-agent-companion' ), array( 'status' => 409 ) );
}

function wpagent_seopress_post_redirection_release_graph_lock( string $token ): void {
	wpagent_companion_release_option_lock( WPAGENT_SEOPRESS_REDIRECTION_GRAPH_LOCK_OPTION, $token );
}

function wpagent_seopress_post_redirection_refresh_graph_lock( string $token ): bool {
	return wpagent_seopress_post_redirection_refresh_lock_option( WPAGENT_SEOPRESS_REDIRECTION_GRAPH_LOCK_OPTION, $token );
}
