<?php
/** Transactional Weglot settings writes. */

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

/** @return string|WP_Error */
function wpagent_weglot_acquire_lock() {
	$token = wpagent_companion_acquire_option_lock( WPAGENT_WEGLOT_LOCK_OPTION, WPAGENT_WEGLOT_LOCK_TTL );
	if ( is_string( $token ) ) {
		return $token;
	}
	return new WP_Error( 'wpagent_weglot_locked', __( 'Die Weglot-Einstellungen werden gerade durch einen anderen Vorgang geändert.', 'wp-agent-companion' ), array( 'status' => 409 ) );
}

function wpagent_weglot_release_lock( string $token ): void {
	wpagent_companion_release_option_lock( WPAGENT_WEGLOT_LOCK_OPTION, $token );
}

function wpagent_weglot_lock_is_owned( string $token ): bool {
	return wpagent_companion_option_lock_is_owned( WPAGENT_WEGLOT_LOCK_OPTION, $token );
}

function wpagent_weglot_refresh_lock( string $token ): bool {
	return wpagent_companion_refresh_option_lock( WPAGENT_WEGLOT_LOCK_OPTION, $token, WPAGENT_WEGLOT_LOCK_TTL );
}

/** @return WP_Error */
function wpagent_weglot_recovery_required() {
	return new WP_Error(
		'wpagent_weglot_recovery_required',
		__( 'Der Weglot-Schreibvorgang hat begonnen, aber die exklusive Sperre oder Berechtigung ging vor der abschließenden Bestätigung verloren. Es wurde kein automatisches Rollback ausgeführt. Prüfe die Weglot-Einstellungen manuell und lies sie anschließend neu.', 'wp-agent-companion' ),
		array( 'status' => 409, 'recovery_required' => true )
	);
}

function wpagent_weglot_save( $service, array $options ): bool {
	try {
		$response = $service->save_options_to_weglot( $options );
	} catch ( Throwable $error ) {
		return false;
	}
	return is_array( $response ) && ! empty( $response['success'] );
}

/** @return true|WP_Error */
function wpagent_weglot_rollback( $service, array $previous, string $previous_hash, string $lock_token ) {
	if ( ! current_user_can( 'manage_options' ) || ! wpagent_weglot_refresh_lock( $lock_token ) ) {
		return wpagent_weglot_recovery_required();
	}
	delete_transient( 'weglot_cache_cdn' );
	if ( ! wpagent_weglot_save( $service, $previous ) ) {
		if ( ! wpagent_weglot_lock_is_owned( $lock_token ) ) {
			return wpagent_weglot_recovery_required();
		}
		return new WP_Error( 'wpagent_weglot_rollback_failed', __( 'Weglot konnte die Änderung nicht bestätigen, und auch das Rollback wurde abgelehnt. Prüfe die Weglot-Einstellungen sofort manuell.', 'wp-agent-companion' ), array( 'status' => 500, 'rollback_verified' => false ) );
	}
	if ( ! current_user_can( 'manage_options' ) || ! wpagent_weglot_lock_is_owned( $lock_token ) ) {
		return wpagent_weglot_recovery_required();
	}
	delete_transient( 'weglot_cache_cdn' );
	$restored = wpagent_weglot_read_options( $service, true );
	$settings = is_wp_error( $restored ) ? $restored : wpagent_weglot_project_settings( $restored );
	if ( ! wpagent_weglot_lock_is_owned( $lock_token ) ) {
		return wpagent_weglot_recovery_required();
	}
	if ( is_wp_error( $settings ) || ! hash_equals( $previous_hash, wpagent_weglot_state_hash( $settings ) ) ) {
		return new WP_Error( 'wpagent_weglot_rollback_unverified', __( 'Das Weglot-Rollback konnte nicht verifiziert werden. Prüfe die Weglot-Einstellungen sofort manuell.', 'wp-agent-companion' ), array( 'status' => 500, 'rollback_verified' => false ) );
	}
	return true;
}

/** @return array<string,mixed>|WP_Error */
function wpagent_exec_update_weglot_settings( $input ) {
	$input = is_array( $input ) ? $input : array();
	$mutable = array_intersect( array_keys( $input ), array( 'original_language', 'destination_languages', 'auto_redirect', 'switcher', 'excluded_urls', 'excluded_blocks' ) );
	if ( ! $mutable ) {
		return new WP_Error( 'wpagent_weglot_no_changes', __( 'Gib mindestens eine zu ändernde Weglot-Einstellung an.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$service = wpagent_weglot_service();
	if ( is_wp_error( $service ) ) {
		return $service;
	}
	$key = wpagent_weglot_private_key( $service );
	if ( is_wp_error( $key ) ) {
		return $key;
	}
	if ( '' === $key ) {
		return new WP_Error( 'wpagent_weglot_not_configured', __( 'Verbinde Weglot zuerst in dessen WordPress-Einstellungen mit einem Projekt. wpagently übernimmt keine API-Schlüssel.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$lock = wpagent_weglot_acquire_lock();
	if ( is_wp_error( $lock ) ) {
		return $lock;
	}
	try {
		$previous = wpagent_weglot_read_options( $service, true );
		if ( is_wp_error( $previous ) ) {
			return $previous;
		}
		$previous_settings = wpagent_weglot_project_settings( $previous );
		if ( is_wp_error( $previous_settings ) ) {
			return $previous_settings;
		}
		$previous_hash = wpagent_weglot_state_hash( $previous_settings );
		$expected_hash = strtolower( (string) ( $input['expected_hash'] ?? '' ) );
		if ( ! preg_match( '/^[a-f0-9]{64}$/', $expected_hash ) || ! hash_equals( $previous_hash, $expected_hash ) ) {
			return new WP_Error( 'wpagent_weglot_conflict', __( 'Die Weglot-Einstellungen haben sich seit dem Lesen geändert. Lies sie neu und wiederhole den Vorgang.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $previous_hash ) );
		}
		$candidate = wpagent_weglot_apply_patch( $previous, $input );
		if ( is_wp_error( $candidate ) ) {
			return $candidate;
		}
		$candidate['api_key_private'] = $key;
		$candidate_settings = wpagent_weglot_project_settings( $candidate );
		if ( is_wp_error( $candidate_settings ) ) {
			return $candidate_settings;
		}
		$candidate_hash = wpagent_weglot_state_hash( $candidate_settings );
		if ( hash_equals( $previous_hash, $candidate_hash ) ) {
			return array( 'settings' => $previous_settings, 'previous_hash' => $previous_hash, 'state_hash' => $previous_hash, 'verified' => true );
		}
		if ( ! current_user_can( 'manage_options' ) ) {
			return new WP_Error( 'wpagent_weglot_forbidden', __( 'Die Berechtigung zum Ändern der Weglot-Einstellungen wurde entzogen.', 'wp-agent-companion' ), array( 'status' => 403 ) );
		}
		if ( ! wpagent_weglot_refresh_lock( $lock ) ) {
			return new WP_Error( 'wpagent_weglot_locked', __( 'Die Weglot-Sperre ging vor dem Schreibvorgang verloren. Es wurde nichts geändert.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}

		$saved = wpagent_weglot_save( $service, $candidate );
		if ( ! current_user_can( 'manage_options' ) || ! wpagent_weglot_lock_is_owned( $lock ) ) {
			return wpagent_weglot_recovery_required();
		}
		delete_transient( 'weglot_cache_cdn' );
		$fresh = $saved ? wpagent_weglot_read_options( $service, true ) : new WP_Error( 'wpagent_weglot_provider_write_failed', '' );
		$fresh_settings = is_wp_error( $fresh ) ? $fresh : wpagent_weglot_project_settings( $fresh );
		if ( ! current_user_can( 'manage_options' ) || ! wpagent_weglot_lock_is_owned( $lock ) ) {
			return wpagent_weglot_recovery_required();
		}
		if ( is_wp_error( $fresh_settings ) || ! hash_equals( $candidate_hash, wpagent_weglot_state_hash( $fresh_settings ) ) ) {
			$rollback = wpagent_weglot_rollback( $service, $previous, $previous_hash, $lock );
			if ( is_wp_error( $rollback ) ) {
				return $rollback;
			}
			return new WP_Error( 'wpagent_weglot_write_unverified', __( 'Weglot hat die Änderung nicht exakt bestätigt. Der vorherige Zustand wurde verifiziert wiederhergestellt.', 'wp-agent-companion' ), array( 'status' => 502, 'rollback_verified' => true ) );
		}
		return array( 'settings' => $fresh_settings, 'previous_hash' => $previous_hash, 'state_hash' => $candidate_hash, 'verified' => true );
	} finally {
		wpagent_weglot_release_lock( $lock );
	}
}
