<?php
/** Fluent Forms submission-confirmation write ability. */

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

/** @return string|WP_Error */
function wpagent_fluent_forms_delivery_plain_message( $value, string $field, int $max_length ) {
	$text = is_string( $value ) ? trim( $value ) : '';
	if ( '' === $text || strlen( $text ) > $max_length ) {
		/* translators: 1: input field name, 2: maximum byte length. */
		return new WP_Error( 'wpagent_fluent_forms_delivery_text', sprintf( __( '%1$s muss zwischen 1 und %2$d Byte lang sein.', 'wp-agent-companion' ), $field, $max_length ), array( 'status' => 400 ) );
	}
	if ( str_contains( $text, '<' ) || str_contains( $text, '>' ) || preg_match( '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/', $text ) ) {
		/* translators: %s: input field name. */
		return new WP_Error( 'wpagent_fluent_forms_delivery_markup', sprintf( __( '%s akzeptiert nur Text und Smartcodes, kein HTML oder Steuerzeichen.', 'wp-agent-companion' ), $field ), array( 'status' => 400 ) );
	}
	return wpautop( esc_html( $text ) );
}

/** @param array<string,mixed> $current @param array<string,mixed> $patch @return array<string,mixed>|WP_Error */
function wpagent_fluent_forms_prepare_confirmation( array $current, array $patch ) {
	$allowed = array( 'redirect_to', 'message', 'same_page_behavior', 'custom_page_id', 'custom_url', 'redirect_message', 'enable_query_string', 'query_strings' );
	if ( ! $patch || array_diff( array_keys( $patch ), $allowed ) ) {
		return new WP_Error( 'wpagent_fluent_forms_confirmation_fields', __( 'Übergebe mindestens ein unterstütztes Bestätigungsfeld.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$result = $current;
	if ( array_key_exists( 'redirect_to', $patch ) ) {
		$map = array( 'same_page' => 'samePage', 'custom_url' => 'customUrl', 'custom_page' => 'customPage' );
		$key = is_string( $patch['redirect_to'] ) ? $patch['redirect_to'] : '';
		if ( ! isset( $map[ $key ] ) ) {
			return new WP_Error( 'wpagent_fluent_forms_confirmation_redirect', __( 'redirect_to muss same_page, custom_url oder custom_page sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$result['redirectTo'] = $map[ $key ];
	}
	if ( array_key_exists( 'message', $patch ) ) {
		$message = wpagent_fluent_forms_delivery_plain_message( $patch['message'], 'message', 100000 );
		if ( is_wp_error( $message ) ) {
			return $message;
		}
		$result['messageToShow'] = $message;
	}
	if ( array_key_exists( 'same_page_behavior', $patch ) ) {
		$behavior = is_string( $patch['same_page_behavior'] ) ? $patch['same_page_behavior'] : '';
		if ( ! in_array( $behavior, array( 'hide_form', 'reset_form' ), true ) ) {
			return new WP_Error( 'wpagent_fluent_forms_confirmation_behavior', __( 'same_page_behavior muss hide_form oder reset_form sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$result['samePageFormBehavior'] = $behavior;
	}
	if ( array_key_exists( 'custom_page_id', $patch ) ) {
		$page_id = absint( $patch['custom_page_id'] );
		$post    = get_post( $page_id );
		if ( ! $post instanceof WP_Post || 'page' !== $post->post_type || 'trash' === $post->post_status ) {
			return new WP_Error( 'wpagent_fluent_forms_confirmation_page', __( 'custom_page_id muss auf eine vorhandene Seite außerhalb des Papierkorbs zeigen.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$result['customPage'] = $page_id;
	}
	if ( array_key_exists( 'custom_url', $patch ) ) {
		$url    = is_string( $patch['custom_url'] ) ? trim( $patch['custom_url'] ) : '';
		$parsed = wp_parse_url( $url );
		if ( ! is_array( $parsed ) || ! in_array( strtolower( (string) ( $parsed['scheme'] ?? '' ) ), array( 'http', 'https' ), true ) || empty( $parsed['host'] ) || isset( $parsed['user'] ) || isset( $parsed['pass'] ) ) {
			return new WP_Error( 'wpagent_fluent_forms_confirmation_url', __( 'custom_url muss eine vollständige HTTP- oder HTTPS-URL ohne Zugangsdaten sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$result['customUrl'] = esc_url_raw( $url );
	}
	if ( array_key_exists( 'redirect_message', $patch ) ) {
		$message = wpagent_fluent_forms_delivery_plain_message( $patch['redirect_message'], 'redirect_message', 20000 );
		if ( is_wp_error( $message ) ) {
			return $message;
		}
		$result['redirectMessage'] = $message;
	}
	if ( array_key_exists( 'enable_query_string', $patch ) ) {
		$result['enable_query_string'] = rest_sanitize_boolean( $patch['enable_query_string'] ) ? 'yes' : 'no';
	}
	if ( array_key_exists( 'query_strings', $patch ) ) {
		$query = is_string( $patch['query_strings'] ) ? trim( $patch['query_strings'] ) : '';
		$query = ltrim( $query, '?' );
		if ( strlen( $query ) > 4096 || str_contains( $query, '#' ) || preg_match( '/[\x00-\x20\x7F]/', $query ) ) {
			return new WP_Error( 'wpagent_fluent_forms_confirmation_query', __( 'query_strings darf höchstens 4.096 Byte lang sein und keine Leer-, Steuer- oder Fragmentzeichen enthalten.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$result['query_strings'] = $query;
	}
	$redirect_to = (string) ( $result['redirectTo'] ?? 'samePage' );
	if ( 'customUrl' === $redirect_to && '' === (string) ( $result['customUrl'] ?? '' ) ) {
		return new WP_Error( 'wpagent_fluent_forms_confirmation_url', __( 'Für custom_url ist custom_url erforderlich.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	if ( 'customPage' === $redirect_to && absint( $result['customPage'] ?? 0 ) <= 0 ) {
		return new WP_Error( 'wpagent_fluent_forms_confirmation_page', __( 'Für custom_page ist custom_page_id erforderlich.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	return $result;
}

/** @param object $service @param array<string,mixed> $form_settings @param array<string,mixed> $advanced */
function wpagent_fluent_forms_save_general_settings( object $service, int $form_id, array $form_settings, array $advanced ): bool {
	$form_json = wp_json_encode( $form_settings );
	$advanced_json = wp_json_encode( $advanced );
	if ( false === $form_json || false === $advanced_json ) {
		return false;
	}
	try {
		$service->saveGeneral( array( 'form_id' => $form_id, 'formSettings' => $form_json, 'advancedValidationSettings' => $advanced_json ) );
		return true;
	} catch ( Throwable $error ) {
		return false;
	}
}

/** @param array<string,mixed> $snapshot */
function wpagent_fluent_forms_restore_general_settings( array $snapshot ): bool {
	// A full settings restore is an unconditional provider write. It cannot prove
	// that a native editor did not change another delivery setting after readback.
	return false;
}

function wpagent_ability_update_fluent_form_confirmation(): array {
	$properties = wpagent_fluent_forms_confirmation_schema()['properties'];
	$properties['message'] = array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 100000 );
	$properties['custom_page_id'] = array( 'type' => 'integer', 'minimum' => 1 );
	$properties['custom_url'] = array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 4096 );
	$properties['redirect_message'] = array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 20000 );
	$properties['query_strings'] = array( 'type' => 'string', 'maxLength' => 4096 );
	return array(
		'label' => __( 'Fluent-Forms-Bestätigung aktualisieren', 'wp-agent-companion' ),
		'description' => __( 'Prüft eine Bestätigungsänderung gegen den vollständigen Formular- und Zustellungszustand. Das Speichern bleibt ohne atomare Fluent-Forms-Compare-and-Update-Operation manuell.', 'wp-agent-companion' ),
		'category' => 'wp-agent',
		'input_schema' => array(
			'type' => 'object', 'additionalProperties' => false,
			'properties' => array(
				'form_id' => array( 'type' => 'integer', 'minimum' => 1 ),
				'expected_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
				'confirmation' => array( 'type' => 'object', 'additionalProperties' => false, 'minProperties' => 1, 'properties' => $properties ),
			),
			'required' => array( 'form_id', 'expected_hash', 'confirmation' ),
		),
		'output_schema' => array( 'type' => 'object', 'properties' => array_merge( wpagent_fluent_forms_delivery_output_schema()['properties'], array( 'verified' => array( 'type' => 'boolean' ) ) ) ),
		'execute_callback' => 'wpagent_exec_update_fluent_form_confirmation',
		'permission_callback' => 'wpagent_perm_fluent_forms_manage',
		'meta' => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => false, 'idempotent' => false, 'manual_only' => true ) ),
	);
}

/** @param mixed $input @return array<string,mixed>|WP_Error */
function wpagent_exec_update_fluent_form_confirmation( $input ) {
	$input = is_array( $input ) ? $input : array();
	$form_id = absint( $input['form_id'] ?? 0 );
	$expected_hash = wpagent_fluent_forms_delivery_expected_hash( $input['expected_hash'] ?? '' );
	if ( is_wp_error( $expected_hash ) ) {
		return $expected_hash;
	}
	$lock = wpagent_fluent_forms_delivery_acquire_lock( $form_id );
	if ( is_wp_error( $lock ) ) {
		return $lock;
	}
	try {
		if ( ! wpagent_fluent_forms_delivery_lock_is_owned( $form_id, $lock ) ) {
			return new WP_Error( 'wpagent_fluent_forms_delivery_lock_lost', __( 'Die Sperre für die Fluent-Forms-Zustellung ging verloren. Lies den Zustand erneut.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$before = wpagent_fluent_forms_delivery_state( $form_id );
		if ( is_wp_error( $before ) ) {
			return $before;
		}
		if ( ! hash_equals( $before['state_hash'], $expected_hash ) ) {
			return new WP_Error( 'wpagent_fluent_forms_delivery_conflict', __( 'Das Fluent-Forms-Formular oder seine Zustellung wurde seit dem Lesen verändert.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $before['state_hash'] ) );
		}
		$current_native = wpagent_fluent_forms_delivery_array( $before['form_settings']['confirmation'] ?? array() );
		$prepared = wpagent_fluent_forms_prepare_confirmation( $current_native, is_array( $input['confirmation'] ?? null ) ? $input['confirmation'] : array() );
		if ( is_wp_error( $prepared ) ) {
			return $prepared;
		}
		return new WP_Error( 'wpagent_fluent_forms_confirmation_update_manual_only', __( 'Fluent Forms bietet keine atomare Compare-and-Update-Operation für die Zustellungsbestätigung. Nimm diese Änderung in WordPress manuell vor, damit parallele Editor-Änderungen erhalten bleiben.', 'wp-agent-companion' ), array( 'status' => 409, 'form_id' => $form_id, 'current_hash' => $before['state_hash'] ) );
	} finally {
		wpagent_fluent_forms_delivery_release_lock( $form_id, $lock );
	}
}
