<?php
/** Conflict-protected Kadence Blocks Free advanced-form settings write. */

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

/** @return true|WP_Error */
function wpagent_kadence_form_validate_plain( $value, string $field, int $max_bytes, bool $allow_empty = true ) {
	if ( ! is_string( $value ) || strlen( $value ) > $max_bytes || ( ! $allow_empty && '' === $value ) ) {
		return new WP_Error( 'wpagent_kadence_form_text', __( 'Eine Kadence-Formularangabe besitzt nicht die erlaubte Textlänge.', 'wp-agent-companion' ), array( 'status' => 400, 'field' => $field ) );
	}
	if ( wp_check_invalid_utf8( $value, true ) !== $value || preg_match( '/[<>\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/u', $value ) ) {
		return new WP_Error( 'wpagent_kadence_form_text', __( 'HTML und steuernde Kontrollzeichen sind in Kadence-Formularangaben nicht erlaubt.', 'wp-agent-companion' ), array( 'status' => 400, 'field' => $field ) );
	}
	return true;
}

/** @return string|WP_Error */
function wpagent_kadence_form_validate_email( $value, string $field ) {
	$plain = wpagent_kadence_form_validate_plain( $value, $field, 254, false );
	if ( is_wp_error( $plain ) || ! is_email( $value ) || sanitize_email( $value ) !== $value ) {
		return is_wp_error( $plain ) ? $plain : new WP_Error( 'wpagent_kadence_form_email', __( 'Die Kadence-Formular-E-Mail-Adresse ist ungültig.', 'wp-agent-companion' ), array( 'status' => 400, 'field' => $field ) );
	}
	return $value;
}

/** @return string|WP_Error */
function wpagent_kadence_form_validate_redirect( $value ) {
	if ( ! is_string( $value )
		|| strlen( $value ) > 2048
		|| str_contains( $value, '\\' )
		|| preg_match( '/[\x00-\x20\x7F]/', $value )
		|| preg_match( '/%(?:0[0-9a-f]|1[0-9a-f]|5c|7f)/i', $value ) ) {
		return new WP_Error( 'wpagent_kadence_form_redirect', __( 'Der Kadence-Formular-Redirect ist ungültig.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	if ( '' === $value ) {
		return '';
	}
	if ( str_starts_with( $value, '/' ) && ! str_starts_with( $value, '//' ) ) {
		return $value;
	}
	$target = wp_parse_url( $value );
	$home   = wp_parse_url( home_url( '/' ) );
	if ( ! is_array( $target ) || ! is_array( $home )
		|| ! in_array( strtolower( (string) ( $target['scheme'] ?? '' ) ), array( 'http', 'https' ), true )
		|| strtolower( (string) ( $target['scheme'] ?? '' ) ) !== strtolower( (string) ( $home['scheme'] ?? '' ) )
		|| strtolower( (string) ( $target['host'] ?? '' ) ) !== strtolower( (string) ( $home['host'] ?? '' ) )
		|| (int) ( $target['port'] ?? 0 ) !== (int) ( $home['port'] ?? 0 )
		|| isset( $target['user'] ) || isset( $target['pass'] ) ) {
		return new WP_Error( 'wpagent_kadence_form_redirect', __( 'Kadence-Formulare dürfen nur auf einen Pfad derselben öffentlichen Website weiterleiten.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	return $value;
}

/** @param mixed $value @return mixed */
function wpagent_kadence_form_normalize_meta_value( string $key, $value ) {
	if ( in_array( $key, array( '_kad_form_browserValidation', '_kad_form_submitHide' ), true ) ) {
		return (bool) $value;
	}
	return $value;
}

/** @return WP_Error */
function wpagent_kadence_form_recovery_error( int $form_id, string $message ) {
	$snapshot = wpagent_kadence_form_snapshot( $form_id );
	return new WP_Error(
		'wpagent_kadence_form_recovery_required',
		$message,
		array(
			'status'            => 409,
			'recovery_required' => true,
			'form_id'           => $form_id,
			'current_hash'      => is_array( $snapshot ) && is_string( $snapshot['hash'] ?? null ) ? $snapshot['hash'] : '',
		)
	);
}

/** @param mixed $value */
function wpagent_kadence_form_canonical_bool( $value ): bool {
	return in_array( $value, array( false, true, 0, 1, '', '0', '1' ), true );
}

/** @return WP_Error */
function wpagent_kadence_form_provider_state_error(): WP_Error {
	return new WP_Error(
		'wpagent_kadence_form_state',
		__( 'Der native Kadence-Formularzustand ist nicht kanonisch und bleibt deshalb schreibgeschützt.', 'wp-agent-companion' ),
		array( 'status' => 409 )
	);
}

/** @param array<string,mixed> $snapshot @param array<string,mixed> $current @return array{actions:array<int,string>,email:array<string,mixed>}|WP_Error */
function wpagent_kadence_form_validate_writable_state( array $snapshot, array $current ) {
	$keys = array(
		'_kad_form_actions', '_kad_form_email', '_kad_form_browserValidation',
		'_kad_form_redirect', '_kad_form_submitHide', '_kad_form_description',
	);
	$rows = is_array( $snapshot['meta'] ?? null ) ? $snapshot['meta'] : array();
	$raw  = array();
	foreach ( $keys as $key ) {
		$value = wpagent_kadence_form_meta_value_from_rows( $rows, $key );
		if ( is_wp_error( $value ) ) {
			return $value;
		}
		$raw[ $key ] = $value;
	}
	$actions = $raw['_kad_form_actions'];
	$email   = $raw['_kad_form_email'];
	if ( ! is_array( $actions )
		|| ! wp_is_numeric_array( $actions )
		|| count( array_filter( $actions, 'is_string' ) ) !== count( $actions )
		|| count( array_unique( $actions ) ) !== count( $actions )
		|| array() !== array_values( array_diff( $actions, array( 'email', 'redirect' ) ) )
		|| ! is_array( $email )
		|| ! is_string( $raw['_kad_form_description'] )
		|| ! is_string( $raw['_kad_form_redirect'] )
		|| ! wpagent_kadence_form_canonical_bool( $raw['_kad_form_browserValidation'] )
		|| ! wpagent_kadence_form_canonical_bool( $raw['_kad_form_submitHide'] ) ) {
		return wpagent_kadence_form_provider_state_error();
	}
	foreach ( array( 'emailTo', 'subject', 'fromEmail', 'fromName', 'replyTo', 'cc', 'bcc' ) as $key ) {
		if ( array_key_exists( $key, $email ) && ! is_string( $email[ $key ] ) ) {
			return wpagent_kadence_form_provider_state_error();
		}
	}
	if ( array_key_exists( 'html', $email ) && ! wpagent_kadence_form_canonical_bool( $email['html'] ) ) {
		return wpagent_kadence_form_provider_state_error();
	}
	$reply_to = $email['replyTo'] ?? 'email_field';
	$canonical_actions = array();
	if ( in_array( 'email', $actions, true ) ) {
		$canonical_actions[] = 'email';
	}
	if ( '' !== $raw['_kad_form_redirect'] ) {
		$canonical_actions[] = 'redirect';
	}
	if ( ! in_array( $reply_to, array( 'email_field', 'from_email' ), true )
		|| $actions !== $canonical_actions
		|| in_array( 'redirect', $actions, true ) !== ( '' !== $raw['_kad_form_redirect'] ) ) {
		return wpagent_kadence_form_provider_state_error();
	}
	if ( in_array( 'email', $actions, true ) ) {
		$to      = wpagent_kadence_form_validate_email( $email['emailTo'] ?? null, 'email.to' );
		$from    = wpagent_kadence_form_validate_email( $email['fromEmail'] ?? null, 'email.from_email' );
		$subject = wpagent_kadence_form_validate_plain( $email['subject'] ?? null, 'email.subject', 200, false );
		$name    = wpagent_kadence_form_validate_plain( $email['fromName'] ?? '', 'email.from_name', 100 );
		if ( is_wp_error( $to ) || is_wp_error( $from ) || is_wp_error( $subject ) || is_wp_error( $name )
			|| preg_match( '/[\r\n]/', (string) ( $email['subject'] ?? '' ) )
			|| preg_match( '/[\r\n]/', (string) ( $email['fromName'] ?? '' ) )
			|| ( 'email_field' === $reply_to && ! in_array( 'email', $current['field_types'] ?? array(), true ) ) ) {
			return wpagent_kadence_form_provider_state_error();
		}
	}
	return array( 'actions' => array_values( $actions ), 'email' => $email );
}

/** @param array<string,mixed> $input @param array<string,mixed> $current @param array<string,mixed> $snapshot @return array<string,mixed>|WP_Error */
function wpagent_kadence_form_build_targets( array $input, array $current, array $snapshot ) {
	if ( $current['advanced_actions_present'] || $current['email']['advanced_headers_present'] ) {
		return new WP_Error( 'wpagent_kadence_form_advanced_state', __( 'Das Formular besitzt nicht freigegebene Aktionen oder erweiterte E-Mail-Header und bleibt deshalb schreibgeschützt.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$provider_state = wpagent_kadence_form_validate_writable_state( $snapshot, $current );
	if ( is_wp_error( $provider_state ) ) {
		return $provider_state;
	}
	$actions_raw = $provider_state['actions'];
	$email_raw   = $provider_state['email'];

	$targets = array();
	$string_fields = array(
		'description' => array( '_kad_form_description', 500 ),
	);
	foreach ( $string_fields as $input_key => [ $meta_key, $limit ] ) {
		if ( array_key_exists( $input_key, $input ) ) {
			$valid = wpagent_kadence_form_validate_plain( $input[ $input_key ], $input_key, $limit );
			if ( is_wp_error( $valid ) ) {
				return $valid;
			}
			if ( $input[ $input_key ] !== $current[ $input_key ] ) {
				$targets[ $meta_key ] = $input[ $input_key ];
			}
		}
	}
	foreach ( array( 'browser_validation' => '_kad_form_browserValidation', 'hide_after_submit' => '_kad_form_submitHide' ) as $input_key => $meta_key ) {
		if ( array_key_exists( $input_key, $input ) && (bool) $input[ $input_key ] !== $current[ $input_key ] ) {
			$targets[ $meta_key ] = (bool) $input[ $input_key ];
		}
	}

	$redirect = $current['redirect'];
	if ( array_key_exists( 'redirect', $input ) ) {
		$redirect = wpagent_kadence_form_validate_redirect( $input['redirect'] );
		if ( is_wp_error( $redirect ) ) {
			return $redirect;
		}
		if ( $redirect !== $current['redirect'] ) {
			$targets['_kad_form_redirect'] = $redirect;
		}
	}

	$email_enabled = $current['email']['enabled'];
	if ( array_key_exists( 'email', $input ) && ! is_array( $input['email'] ) ) {
		return new WP_Error( 'wpagent_kadence_form_state', __( 'Die nativen Kadence-Formulareinstellungen besitzen einen unerwarteten Typ.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$email_input   = is_array( $input['email'] ?? null ) ? $input['email'] : array();
	$email_next    = $email_raw;
	if ( array_key_exists( 'enabled', $email_input ) ) {
		$email_enabled = (bool) $email_input['enabled'];
	}
	$email_map = array(
		'to' => array( 'emailTo', 'email' ), 'subject' => array( 'subject', 'text' ),
		'from_email' => array( 'fromEmail', 'email' ), 'from_name' => array( 'fromName', 'text' ),
		'reply_to' => array( 'replyTo', 'reply' ), 'html' => array( 'html', 'bool' ),
	);
	foreach ( $email_map as $input_key => [ $provider_key, $type ] ) {
		if ( ! array_key_exists( $input_key, $email_input ) ) {
			continue;
		}
		$value = $email_input[ $input_key ];
		if ( 'email' === $type ) {
			$value = wpagent_kadence_form_validate_email( $value, 'email.' . $input_key );
		} elseif ( 'text' === $type ) {
			$value = wpagent_kadence_form_validate_plain( $value, 'email.' . $input_key, 'subject' === $input_key ? 200 : 100, 'subject' !== $input_key );
			if ( ! is_wp_error( $value ) && preg_match( '/[\r\n]/', $email_input[ $input_key ] ) ) {
				$value = new WP_Error( 'wpagent_kadence_form_email_header', __( 'Kadence-E-Mail-Kopfzeilen dürfen keine Zeilenumbrüche enthalten.', 'wp-agent-companion' ), array( 'status' => 400, 'field' => 'email.' . $input_key ) );
			} elseif ( ! is_wp_error( $value ) ) {
				$value = $email_input[ $input_key ];
			}
		} elseif ( 'reply' === $type && ! in_array( $value, array( 'email_field', 'from_email' ), true ) ) {
			$value = new WP_Error( 'wpagent_kadence_form_reply_to', __( 'reply_to ist für Kadence Forms nicht erlaubt.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		} elseif ( 'bool' === $type ) {
			$value = is_bool( $value )
				? $value
				: new WP_Error( 'wpagent_kadence_form_state', __( 'Die nativen Kadence-Formulareinstellungen besitzen einen unerwarteten Typ.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		if ( is_wp_error( $value ) ) {
			return $value;
		}
		$email_next[ $provider_key ] = $value;
	}
	if ( $email_next !== $email_raw ) {
		$targets['_kad_form_email'] = $email_next;
	}
	if ( $email_enabled ) {
		$effective_email = $email_next;
		$to              = wpagent_kadence_form_validate_email( $effective_email['emailTo'] ?? null, 'email.to' );
		$from            = wpagent_kadence_form_validate_email( $effective_email['fromEmail'] ?? null, 'email.from_email' );
		$subject         = wpagent_kadence_form_validate_plain( $effective_email['subject'] ?? null, 'email.subject', 200, false );
		$reply_to        = $effective_email['replyTo'] ?? 'email_field';
		if ( is_wp_error( $to ) || is_wp_error( $from ) || is_wp_error( $subject )
			|| ! in_array( $reply_to, array( 'email_field', 'from_email' ), true )
			|| ( 'email_field' === $reply_to && ! in_array( 'email', $current['field_types'] ?? array(), true ) ) ) {
			return wpagent_kadence_form_provider_state_error();
		}
	}

	if ( array_key_exists( 'redirect', $input ) || array_key_exists( 'enabled', $email_input ) ) {
		$actions_next = array();
		if ( $email_enabled ) {
			$actions_next[] = 'email';
		}
		if ( '' !== $redirect ) {
			$actions_next[] = 'redirect';
		}
		if ( $actions_next !== array_values( $actions_raw ) ) {
			$targets['_kad_form_actions'] = $actions_next;
		}
	}
	return $targets;
}

/** @param array<string,mixed> $before @return array<string,mixed>|WP_Error */
function wpagent_kadence_form_write_target( int $form_id, string $key, $value, array $before, string $lock ) {
	if ( ! wpagent_kadence_form_refresh_lock( $form_id, $lock ) ) {
		return new WP_Error( 'wpagent_kadence_form_locked', __( 'Der Kadence-Formular-Lock ging vor dem Write verloren.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$authorized = wpagent_kadence_form_get_authorized( $form_id );
	if ( is_wp_error( $authorized ) ) {
		return $authorized;
	}
	$fresh_before = wpagent_kadence_form_snapshot( $form_id );
	if ( is_wp_error( $fresh_before ) || ! hash_equals( (string) $before['hash'], (string) ( $fresh_before['hash'] ?? '' ) ) ) {
		return new WP_Error( 'wpagent_kadence_form_conflict', __( 'Das Kadence-Formular wurde parallel verändert.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => is_array( $fresh_before ) ? ( $fresh_before['hash'] ?? '' ) : '' ) );
	}
	try {
		$written = update_post_meta( $form_id, $key, wp_slash( $value ) );
	} catch ( Throwable $error ) {
		return wpagent_kadence_form_recovery_error( $form_id, __( 'Der native Kadence-Write wurde unterbrochen. Der aktuelle Zustand muss geprüft werden.', 'wp-agent-companion' ) );
	}
	$after = wpagent_kadence_form_snapshot( $form_id );
	if ( is_wp_error( $after )
		|| false === $written
		|| ! wpagent_kadence_form_refresh_lock( $form_id, $lock )
		|| ! wpagent_kadence_form_snapshot_changed_only_key( $before, $after, $key ) ) {
		return wpagent_kadence_form_recovery_error( $form_id, __( 'Der Kadence-Providerzustand ist nach dem Write nicht eindeutig verifizierbar.', 'wp-agent-companion' ) );
	}
	$readback = wpagent_kadence_form_meta_value( $form_id, $key );
	if ( is_wp_error( $readback ) || wpagent_kadence_form_normalize_meta_value( $key, $readback ) !== wpagent_kadence_form_normalize_meta_value( $key, $value ) ) {
		return wpagent_kadence_form_recovery_error( $form_id, __( 'Der Kadence-Provider-Read-back weicht vom bestätigten Write ab.', 'wp-agent-companion' ) );
	}
	return $after;
}

function wpagent_ability_update_kadence_form_settings(): array {
	return array(
		'label' => __( 'Kadence-Formulareinstellungen aktualisieren', 'wp-agent-companion' ),
		'description' => __( 'Aktualisiert eine enge Kadence-Blocks-Free-Schnittmenge für E-Mail, lokalen Redirect und Formularverhalten mit Rohzustands-Hash, erneuerbarem Lock und exaktem Provider-Read-back. Nach einem unklaren Write erfolgt keine automatische Folgemutation.', 'wp-agent-companion' ),
		'category' => 'wp-agent',
		'input_schema' => array(
			'type' => 'object', 'minProperties' => 3, 'additionalProperties' => false,
			'properties' => array(
				'form_id' => array( 'type' => 'integer', 'minimum' => 1 ),
				'expected_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
				'description' => array( 'type' => 'string', 'maxLength' => 500 ),
				'browser_validation' => array( 'type' => 'boolean' ),
				'redirect' => array( 'type' => 'string', 'maxLength' => 2048 ),
				'hide_after_submit' => array( 'type' => 'boolean' ),
				'email' => array(
					'type' => 'object', 'minProperties' => 1, 'additionalProperties' => false,
					'properties' => array(
						'enabled' => array( 'type' => 'boolean' ), 'to' => array( 'type' => 'string', 'maxLength' => 254 ),
						'subject' => array( 'type' => 'string', 'maxLength' => 200 ), 'from_email' => array( 'type' => 'string', 'maxLength' => 254 ),
						'from_name' => array( 'type' => 'string', 'maxLength' => 100 ), 'reply_to' => array( 'type' => 'string', 'enum' => array( 'email_field', 'from_email' ) ),
						'html' => array( 'type' => 'boolean' ),
					),
				),
			),
			'required' => array( 'form_id', 'expected_hash' ),
		),
		'output_schema' => array(
			'type' => 'object', 'additionalProperties' => false,
			'properties' => array( 'form' => wpagent_kadence_form_payload_schema(), 'changed' => array( 'type' => 'boolean' ), 'verified' => array( 'type' => 'boolean' ) ),
			'required' => array( 'form', 'changed', 'verified' ),
		),
		'execute_callback' => 'wpagent_exec_update_kadence_form_settings',
		'permission_callback' => 'wpagent_perm_kadence_form',
		'meta' => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => false, 'idempotent' => true ) ),
	);
}

/** @param mixed $input @return array<string,mixed>|WP_Error */
function wpagent_exec_update_kadence_form_settings( $input ) {
	$input   = is_array( $input ) ? $input : array();
	$form_id = (int) ( $input['form_id'] ?? 0 );
	$post    = wpagent_kadence_form_get_authorized( $form_id );
	if ( is_wp_error( $post ) ) {
		return $post;
	}
	$lock = wpagent_kadence_form_acquire_lock( $form_id );
	if ( is_wp_error( $lock ) ) {
		return $lock;
	}
	$started = false;
	try {
		$post = wpagent_kadence_form_get_authorized( $form_id );
		if ( is_wp_error( $post ) || ! wpagent_kadence_form_refresh_lock( $form_id, $lock ) ) {
			return is_wp_error( $post ) ? $post : new WP_Error( 'wpagent_kadence_form_locked', __( 'Der Kadence-Formular-Lock ging verloren.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$snapshot = wpagent_kadence_form_snapshot( $form_id );
		$expected = is_string( $input['expected_hash'] ?? null ) ? $input['expected_hash'] : '';
		if ( is_wp_error( $snapshot ) || ! preg_match( '/^[a-f0-9]{64}$/', $expected ) || ! hash_equals( (string) ( $snapshot['hash'] ?? '' ), $expected ) ) {
			return new WP_Error( 'wpagent_kadence_form_conflict', __( 'Das Kadence-Formular wurde seit dem Lesen verändert.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => is_array( $snapshot ) ? ( $snapshot['hash'] ?? '' ) : '' ) );
		}
		$current = wpagent_kadence_form_payload( $post );
		if ( is_wp_error( $current ) ) {
			return $current;
		}
		if ( ! hash_equals( (string) $snapshot['hash'], (string) ( $current['hash'] ?? '' ) ) ) {
			return new WP_Error( 'wpagent_kadence_form_conflict', __( 'Das Kadence-Formular wurde seit dem Lesen verändert.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $current['hash'] ?? '' ) );
		}
		$targets = wpagent_kadence_form_build_targets( $input, $current, $snapshot );
		if ( is_wp_error( $targets ) ) {
			return $targets;
		}
		if ( array() === $targets ) {
			return array( 'form' => $current, 'changed' => false, 'verified' => true );
		}
		foreach ( $targets as $key => $value ) {
			$result = wpagent_kadence_form_write_target( $form_id, $key, $value, $snapshot, $lock );
			if ( is_wp_error( $result ) ) {
				return 'wpagent_kadence_form_recovery_required' === $result->get_error_code() || $started
					? wpagent_kadence_form_recovery_error( $form_id, $result->get_error_message() )
					: $result;
			}
			$started  = true;
			$snapshot = $result;
		}
		if ( ! wpagent_kadence_form_refresh_lock( $form_id, $lock ) || ! current_user_can( 'edit_post', $form_id ) ) {
			return wpagent_kadence_form_recovery_error( $form_id, __( 'Der Kadence-Formular-Lock oder die Berechtigung ging nach dem Write verloren.', 'wp-agent-companion' ) );
		}
		$fresh_post = wpagent_kadence_form_get_authorized( $form_id );
		$fresh      = $fresh_post instanceof WP_Post ? wpagent_kadence_form_payload( $fresh_post ) : null;
		if ( ! is_array( $fresh ) || ! hash_equals( (string) $snapshot['hash'], (string) ( $fresh['hash'] ?? '' ) ) ) {
			return wpagent_kadence_form_recovery_error( $form_id, __( 'Der abschließende Kadence-Providerzustand ist nicht eindeutig verifizierbar.', 'wp-agent-companion' ) );
		}
		return array( 'form' => $fresh, 'changed' => true, 'verified' => true );
	} finally {
		wpagent_kadence_form_release_lock( $form_id, $lock );
	}
}
