<?php
/** Formidable Forms create, update, duplicate and delete abilities. */

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

/** @return array<string,mixed> */
function wpagent_formidable_write_properties_schema(): array {
	return array(
		'form_key' => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 100, 'pattern' => '^[A-Za-z0-9_-]+$' ),
		'name' => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 255 ),
		'description' => array( 'type' => 'string', 'maxLength' => 10000 ),
		'status' => array( 'type' => 'string', 'enum' => array( 'published', 'draft' ) ),
	);
}

/** @return array<string,mixed> */
function wpagent_formidable_write_output_schema(): array {
	return array(
		'type'       => 'object',
		'properties' => array(
			'form' => wpagent_formidable_form_output_schema(),
			'verified' => array( 'type' => 'boolean' ),
		),
	);
}

/**
 * Validates Formidable field documents after the public envelope boundary has
 * verified and decoded them. The public schema cannot expose arbitrary nested
 * provider objects, but the provider must still receive exactly the former
 * closed field contract rather than an opaque JSON payload.
 *
 * @param array<string,mixed> $input
 * @return true|WP_Error
 */
function wpagent_formidable_validate_decoded_fields( array $input, bool $allow_id ) {
	if ( ! array_key_exists( 'fields', $input ) ) {
		return true;
	}
	if ( ! is_array( $input['fields'] ) || count( $input['fields'] ) > 500 ) {
		return new WP_Error( 'wpagent_formidable_bad_fields', __( 'Die Formidable-Forms-Felder müssen eine begrenzte Liste sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	foreach ( $input['fields'] as $index => $field ) {
		// The outer public envelope already enforces total size, depth and
		// integrity. This original closed provider contract supplies the
		// semantic field validation after decoding without treating it as a
		// second public schema transformation.
		$valid = rest_validate_value_from_schema( $field, wpagent_formidable_field_schema( $allow_id ), 'input[fields][' . (string) $index . ']' );
		if ( is_wp_error( $valid ) ) {
			return new WP_Error( 'wpagent_formidable_bad_field', __( 'Ein Formidable-Forms-Feld entspricht nicht dem erlaubten Schema.', 'wp-agent-companion' ), array( 'status' => 400, 'field_index' => (int) $index ) );
		}
	}
	return true;
}

/** @param array<string,mixed> $input @return array<string,mixed> */
function wpagent_formidable_prepare_form_values( array $input, bool $creating ): array {
	$values = array();
	foreach ( array( 'name', 'description', 'status' ) as $key ) {
		if ( array_key_exists( $key, $input ) ) {
			$values[ $key ] = $input[ $key ];
		}
	}
	if ( isset( $values['name'] ) ) {
		$values['name'] = sanitize_text_field( (string) $values['name'] );
	}
	if ( isset( $values['description'] ) ) {
		$values['description'] = sanitize_textarea_field( (string) $values['description'] );
	}
	if ( isset( $values['status'] ) ) {
		$values['status'] = sanitize_key( (string) $values['status'] );
	}
	if ( $creating ) {
		$values['description'] = (string) ( $values['description'] ?? '' );
		$values['form_key']    = sanitize_title( (string) ( $input['form_key'] ?? $input['name'] ?? '' ) );
		if ( '' === $values['form_key'] ) {
			$values['form_key'] = 'wpagently-form';
		}
		$values['options']  = array();
	}
	return $values;
}

/** @param array<string,mixed> $field @return array<string,mixed> */
function wpagent_formidable_comparable_field( array $field ): array {
	unset( $field['id'], $field['field_key'] );
	return $field;
}

/** @param array<string,mixed> $field @return array<string,mixed> */
function wpagent_formidable_duplicate_comparable_field( array $field ): array {
	unset( $field['id'], $field['field_key'], $field['description'], $field['default_value'] );
	return $field;
}

/** @param mixed $field @return array<string,mixed> */
function wpagent_formidable_raw_field_values( $field ): array {
	$data   = is_object( $field ) ? get_object_vars( $field ) : ( is_array( $field ) ? $field : array() );
	$values = array();
	foreach ( array( 'field_key', 'name', 'description', 'type', 'default_value', 'options', 'field_order', 'required', 'field_options' ) as $key ) {
		if ( array_key_exists( $key, $data ) ) {
			$values[ $key ] = wpagent_formidable_json_value( $data[ $key ] );
		}
	}
	return $values;
}

/**
 * Captures public verification data and complete provider-owned field options for rollback.
 * The raw part never leaves the server.
 *
 * @param mixed $form
 * @param int[] $raw_field_ids
 * @return array{public:array<string,mixed>,form_values:array<string,mixed>,fields:array<int,array<string,mixed>>}
 */
function wpagent_formidable_capture_snapshot( $form, array $raw_field_ids = array() ): array {
	$data       = is_object( $form ) ? get_object_vars( $form ) : ( is_array( $form ) ? $form : array() );
	$form_id    = absint( $data['id'] ?? 0 );
	$public     = wpagent_formidable_form_payload( $form, false );
	$raw_fields = array();
	$raw_lookup = array_fill_keys( array_filter( array_map( 'absint', $raw_field_ids ) ), true );
	foreach ( wpagent_formidable_bounded_fields( $form_id ) as $field ) {
		$field_id = absint( is_object( $field ) ? ( $field->id ?? 0 ) : ( $field['id'] ?? 0 ) );
		if ( $field_id <= 0 ) {
			continue;
		}
		$public['fields'][] = wpagent_formidable_field_payload( $field );
		if ( isset( $raw_lookup[ $field_id ] ) ) {
			$raw_fields[ $field_id ] = wpagent_formidable_raw_field_values( $field );
		}
	}
	$form_values = array();
	foreach ( array( 'name', 'description', 'status' ) as $key ) {
		if ( array_key_exists( $key, $data ) ) {
			$form_values[ $key ] = $data[ $key ];
		}
	}
	return array( 'public' => $public, 'form_values' => $form_values, 'fields' => $raw_fields );
}

/** @param array<int,array<string,mixed>> $expected @param array<int,array<string,mixed>> $actual */
function wpagent_formidable_comparable_fields_match( array $expected, array $actual ): bool {
	if ( count( $expected ) !== count( $actual ) ) {
		return false;
	}
	$normalize = static function ( array $fields ): array {
		$values = array_map(
			static fn( array $field ): string => (string) wp_json_encode( wpagent_formidable_duplicate_comparable_field( $field ) ),
			$fields
		);
		sort( $values, SORT_STRING );
		return $values;
	};
	return $normalize( $expected ) === $normalize( $actual );
}

/** @param array<string,mixed> $expected @param array<string,mixed> $actual */
function wpagent_formidable_form_request_matches( array $expected, array $actual ): bool {
	foreach ( array( 'form_key', 'name', 'description', 'status' ) as $key ) {
		if ( array_key_exists( $key, $expected ) && (string) $expected[ $key ] !== (string) ( $actual[ $key ] ?? '' ) ) {
			return false;
		}
	}
	return true;
}

/** @param array<string,mixed> $requested @param array<string,mixed> $actual */
function wpagent_formidable_field_request_matches( array $requested, array $actual ): bool {
	$prepared = wpagent_formidable_prepare_field_values( $requested, 0, false );
	foreach ( $prepared as $key => $value ) {
		$matches = 'options' === $key
			? wpagent_formidable_exact_matches( $value, $actual[ $key ] ?? null )
			: wpagent_formidable_subset_matches( $value, $actual[ $key ] ?? null );
		if ( 'form_id' === $key || ! array_key_exists( $key, $actual ) || ! $matches ) {
			return false;
		}
	}
	return true;
}

/**
 * @param array{public:array<string,mixed>,form_values:array<string,mixed>,fields:array<int,array<string,mixed>>} $snapshot
 * @param int[] $created_field_ids
 * @param int[] $modified_field_ids
 * @param string[] $modified_form_keys
 */
function wpagent_formidable_restore_snapshot( array $snapshot, array $created_field_ids, array $modified_field_ids, array $modified_form_keys ): bool {
	$form_id = absint( $snapshot['public']['id'] ?? 0 );
	if ( $form_id <= 0 ) {
		return false;
	}
	$restored           = true;
	$modified_field_ids = array_unique( array_filter( array_map( 'absint', $modified_field_ids ) ) );
	$created_field_ids  = array_unique( array_filter( array_map( 'absint', $created_field_ids ) ) );
	$form_values        = array_intersect_key( $snapshot['form_values'], array_fill_keys( $modified_form_keys, true ) );
	try {
		if ( $form_values ) {
			FrmForm::update( $form_id, $form_values );
		}
	} catch ( Throwable $error ) {
		$restored = false;
	}
	foreach ( $modified_field_ids as $field_id ) {
		try {
			if ( ! isset( $snapshot['fields'][ $field_id ] ) || ! is_object( FrmField::getOne( $field_id ) ) ) {
				$restored = false;
				continue;
			}
			FrmField::update( $field_id, $snapshot['fields'][ $field_id ] );
		} catch ( Throwable $error ) {
			$restored = false;
		}
	}
	foreach ( $created_field_ids as $field_id ) {
		try {
			if ( is_object( FrmField::getOne( $field_id ) ) ) {
				FrmField::destroy( $field_id );
			}
		} catch ( Throwable $error ) {
			$restored = false;
		}
	}
	try {
		$fresh        = FrmForm::getOne( $form_id );
		$fresh_fields = array();
		foreach ( $modified_field_ids as $field_id ) {
			$fresh_fields[ $field_id ] = FrmField::getOne( $field_id );
		}
	} catch ( Throwable $error ) {
		return false;
	}
	if ( ! $restored || ! is_object( $fresh ) ) {
		return false;
	}
	try {
		$actual = wpagent_formidable_form_payload( $fresh );
	} catch ( Throwable $error ) {
		return false;
	}
	$public = $snapshot['public'];
	if ( ! wpagent_formidable_form_request_matches( $public, $actual ) || count( $actual['fields'] ) !== count( $public['fields'] ?? array() ) ) {
		return false;
	}
	$actual_by_id = array_column( $actual['fields'], null, 'id' );
	foreach ( $public['fields'] ?? array() as $field ) {
		$field_id = absint( $field['id'] ?? 0 );
		if ( ! isset( $actual_by_id[ $field_id ] ) || ! wpagent_formidable_exact_matches( wpagent_formidable_comparable_field( $field ), wpagent_formidable_comparable_field( $actual_by_id[ $field_id ] ) ) ) {
			return false;
		}
	}
	$fresh_form_data = get_object_vars( $fresh );
	foreach ( $modified_form_keys as $key ) {
		if ( ! array_key_exists( $key, $snapshot['form_values'] ) || ! array_key_exists( $key, $fresh_form_data ) || ! wpagent_formidable_exact_matches( $snapshot['form_values'][ $key ], $fresh_form_data[ $key ] ) ) {
			return false;
		}
	}
	foreach ( $modified_field_ids as $field_id ) {
		if ( ! is_object( $fresh_fields[ $field_id ] ?? null ) || ! wpagent_formidable_exact_matches( $snapshot['fields'][ $field_id ], wpagent_formidable_raw_field_values( $fresh_fields[ $field_id ] ) ) ) {
			return false;
		}
	}
	return true;
}

function wpagent_formidable_recovery_required( int $form_id = 0 ): WP_Error {
	$data = array( 'status' => 409, 'recovery_required' => true );
	if ( $form_id > 0 ) {
		$data['form_id'] = $form_id;
		return new WP_Error( 'wpagent_formidable_recovery_required', __( 'Die Formidable-Forms-Änderung konnte nicht vollständig verifiziert werden. Das Formular und mögliche Einreichungen bleiben erhalten und müssen vor einem weiteren Schreibversuch manuell geprüft werden.', 'wp-agent-companion' ), $data );
	}
	return new WP_Error( 'wpagent_formidable_recovery_required', __( 'Die Formidable-Forms-Änderung konnte nicht vollständig verifiziert werden. Der mögliche Formularzustand muss vor einem weiteren Schreibversuch manuell geprüft werden.', 'wp-agent-companion' ), $data );
}

function wpagent_ability_create_formidable_form(): array {
	$properties           = wpagent_formidable_write_properties_schema();
	// A field is a bounded, integrity-protected public JSON document. The
	// decoded value is revalidated against wpagent_formidable_field_schema()
	// before the native provider sees it.
	$properties['fields'] = array( 'type' => 'array', 'maxItems' => 500, 'items' => array( 'type' => 'object' ) );
	return array(
		'label'               => __( 'Formidable-Forms-Formular erstellen', 'wp-agent-companion' ),
		'description'         => __( 'Erstellt ein Formidable-Forms-Formular mit bis zu 500 strikt validierten Feldern über die native Modell-API. Nicht verifizierbare Neuanlagen bleiben für eine manuelle Prüfung erhalten.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array( 'type' => 'object', 'additionalProperties' => false, 'properties' => $properties, 'required' => array( 'name' ) ),
		'output_schema'       => wpagent_formidable_write_output_schema(),
		'execute_callback'    => 'wpagent_exec_create_formidable_form',
		'permission_callback' => 'wpagent_perm_formidable_edit',
		'meta'                => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => false, 'idempotent' => false ) ),
	);
}

/** @param mixed $input @return array|WP_Error */
function wpagent_exec_create_formidable_form( $input ) {
	$input = is_array( $input ) ? $input : array();
	$valid = wpagent_formidable_validate_decoded_fields( $input, false );
	if ( is_wp_error( $valid ) ) {
		return $valid;
	}
	if ( ! wpagent_formidable_available() ) {
		return wpagent_formidable_missing_error();
	}
	$lock  = wpagent_formidable_acquire_mutation_lock();
	if ( is_wp_error( $lock ) ) {
		return $lock;
	}
	$form_id = 0;
	try {
		try {
			$form_id = absint( FrmForm::create( wpagent_formidable_prepare_form_values( $input, true ) ) );
		} catch ( Throwable $error ) {
			// FrmForm::create() invalidates its cache after the native insert. An
			// object-cache backend can fail in that post-write step before it returns
			// the ID, so a candidate cannot be located safely.
			return wpagent_formidable_recovery_required();
		}
		if ( $form_id <= 0 ) {
			// FrmForm::create() returns false/zero after a failed allocation. No
			// identifier exists to locate a candidate, so do not imply one does.
			return new WP_Error( 'wpagent_formidable_create_failed', __( 'Das Formidable-Forms-Formular konnte nicht vollständig erstellt werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		}
		try {
			$candidate = FrmForm::getOne( $form_id );
			if ( ! is_object( $candidate ) ) {
				throw new RuntimeException( 'Created form could not be read.' );
			}
			foreach ( is_array( $input['fields'] ?? null ) ? $input['fields'] : array() as $field ) {
				$field_id = absint( FrmField::create( wpagent_formidable_prepare_field_values( $field, $form_id, true ) ) );
				if ( $field_id <= 0 ) {
					throw new RuntimeException( 'Field creation failed.' );
				}
			}
			$fresh  = FrmForm::getOne( $form_id );
			$actual = is_object( $fresh ) ? wpagent_formidable_form_payload( $fresh ) : array();
		} catch ( Throwable $error ) {
			// Formidable has no provider-wide CAS for a newly created form. A native
			// writer may have added a submission after creation, so deleting this
			// request-owned form could erase foreign state. Preserve it for review.
			return wpagent_formidable_recovery_required( $form_id );
		}
		$requested = wpagent_formidable_prepare_form_values( $input, true );
		unset( $requested['options'] );
		if ( ! array_key_exists( 'form_key', $input ) ) {
			unset( $requested['form_key'] );
		}
		$verified  = wpagent_formidable_form_request_matches( $requested, $actual )
			&& count( $actual['fields'] ?? array() ) === count( $input['fields'] ?? array() );
		foreach ( $input['fields'] ?? array() as $index => $field ) {
			$verified = $verified && isset( $actual['fields'][ $index ] ) && wpagent_formidable_field_request_matches( $field, $actual['fields'][ $index ] );
		}
		if ( ! $verified ) {
			// Do not remove an unverified created form. Native Formidable writers may
			// have attached entries outside this request's mutation lock.
			return wpagent_formidable_recovery_required( $form_id );
		}
		return array( 'form' => $actual, 'verified' => true );
	} finally {
		wpagent_formidable_release_mutation_lock( $lock );
	}
}

function wpagent_ability_update_formidable_form(): array {
	$properties              = array( 'form_id' => array( 'type' => 'integer', 'minimum' => 1 ) ) + wpagent_formidable_write_properties_schema();
	unset( $properties['form_key'] );
	$properties['fields']    = array( 'type' => 'array', 'maxItems' => 500, 'items' => array( 'type' => 'object' ) );
	return array(
		'label'               => __( 'Formidable-Forms-Formular aktualisieren', 'wp-agent-companion' ),
		'description'         => __( 'Aktualisiert Formulardaten und Felder additiv. Nicht genannte Felder bleiben erhalten. Jede Änderung wird rückgelesen. Nicht bestätigte Teiländerungen erfordern eine manuelle Prüfung.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array( 'type' => 'object', 'additionalProperties' => false, 'properties' => $properties, 'required' => array( 'form_id' ), 'minProperties' => 2 ),
		'output_schema'       => wpagent_formidable_write_output_schema(),
		'execute_callback'    => 'wpagent_exec_update_formidable_form',
		'permission_callback' => 'wpagent_perm_formidable_edit',
		'meta'                => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => false, 'idempotent' => false ) ),
	);
}

/** @param mixed $input @return array|WP_Error */
function wpagent_exec_update_formidable_form( $input ) {
	$input = is_array( $input ) ? $input : array();
	$valid = wpagent_formidable_validate_decoded_fields( $input, true );
	if ( is_wp_error( $valid ) ) {
		return $valid;
	}
	$form  = wpagent_formidable_get_authorized_form( $input, 'frm_edit_forms' );
	if ( is_wp_error( $form ) ) {
		return $form;
	}
	$lock = wpagent_formidable_acquire_mutation_lock();
	if ( is_wp_error( $lock ) ) {
		return $lock;
	}
	$form_id           = absint( $input['form_id'] ?? 0 );
	$created_field_ids = array();
	$modified_field_ids = array();
	$modified_form_keys = array();
	try {
		try {
			$fresh_form = FrmForm::getOne( $form_id );
			if ( ! is_object( $fresh_form ) ) {
				return new WP_Error( 'wpagent_formidable_form_not_found', __( 'Formidable-Forms-Formular nicht gefunden.', 'wp-agent-companion' ), array( 'status' => 404 ) );
			}
			$requested_field_ids = array();
			foreach ( is_array( $input['fields'] ?? null ) ? $input['fields'] : array() as $requested_field ) {
				if ( absint( $requested_field['id'] ?? 0 ) > 0 ) {
					$requested_field_ids[] = absint( $requested_field['id'] );
				}
			}
			$snapshot = wpagent_formidable_capture_snapshot( $fresh_form, $requested_field_ids );
		} catch ( OverflowException $error ) {
			return wpagent_formidable_payload_limit_error();
		} catch ( Throwable $error ) {
			return wpagent_formidable_provider_error();
		}
		$snapshot_by_id = array_column( $snapshot['public']['fields'], null, 'id' );
		foreach ( is_array( $input['fields'] ?? null ) ? $input['fields'] : array() as $field ) {
			$field_id = absint( $field['id'] ?? 0 );
			if ( $field_id <= 0 ) {
				continue;
			}
			if ( ! isset( $snapshot_by_id[ $field_id ] ) ) {
				return new WP_Error( 'wpagent_formidable_foreign_field', __( 'Mindestens ein Feld gehört nicht zu diesem Formidable-Forms-Formular.', 'wp-agent-companion' ), array( 'status' => 400 ) );
			}
			$target_type = sanitize_key( (string) ( $field['type'] ?? $snapshot_by_id[ $field_id ]['type'] ?? '' ) );
			if ( wpagent_formidable_sensitive_field_type( $target_type ) && array_key_exists( 'default_value', $field ) ) {
				return new WP_Error( 'wpagent_formidable_sensitive_default', __( 'Standardwerte von Passwort- und versteckten Feldern können aus Sicherheitsgründen nicht über die Agent-Schnittstelle geändert werden.', 'wp-agent-companion' ), array( 'status' => 400 ) );
			}
		}
		try {
			$form_values = wpagent_formidable_prepare_form_values( $input, false );
			if ( $form_values ) {
				$modified_form_keys = array_keys( $form_values );
				FrmForm::update( $form_id, $form_values );
			}
			foreach ( is_array( $input['fields'] ?? null ) ? $input['fields'] : array() as $field ) {
				$field_id = absint( $field['id'] ?? 0 );
				if ( $field_id > 0 ) {
					$values = wpagent_formidable_prepare_field_values( $field, $form_id, false );
					if ( $values ) {
						if ( isset( $values['field_options'] ) ) {
							$existing_options        = is_array( $snapshot['fields'][ $field_id ]['field_options'] ?? null ) ? $snapshot['fields'][ $field_id ]['field_options'] : array();
							$values['field_options'] = array_replace( $existing_options, $values['field_options'] );
						}
						$modified_field_ids[] = $field_id;
						FrmField::update( $field_id, $values );
					}
				} else {
					$field_id = absint( FrmField::create( wpagent_formidable_prepare_field_values( $field, $form_id, true ) ) );
					if ( $field_id <= 0 ) {
						throw new RuntimeException( 'Field creation failed.' );
					}
					$created_field_ids[] = $field_id;
				}
			}
			$fresh  = FrmForm::getOne( $form_id );
			$actual = is_object( $fresh ) ? wpagent_formidable_form_payload( $fresh ) : array();
		} catch ( Throwable $error ) {
			return wpagent_formidable_recovery_required( $form_id );
		}
		$verified = wpagent_formidable_form_request_matches( wpagent_formidable_prepare_form_values( $input, false ), $actual )
			&& count( $actual['fields'] ?? array() ) === count( $snapshot['public']['fields'] ) + count( $created_field_ids );
		$actual_by_id = array_column( $actual['fields'] ?? array(), null, 'id' );
		$new_index     = 0;
		foreach ( $input['fields'] ?? array() as $field ) {
			$field_id = absint( $field['id'] ?? 0 );
			if ( $field_id <= 0 ) {
				$field_id = $created_field_ids[ $new_index ] ?? 0;
				++$new_index;
			}
			$verified = $verified && isset( $actual_by_id[ $field_id ] ) && wpagent_formidable_field_request_matches( $field, $actual_by_id[ $field_id ] );
		}
		if ( ! $verified ) {
			return wpagent_formidable_recovery_required( $form_id );
		}
		return array( 'form' => $actual, 'verified' => true );
	} finally {
		wpagent_formidable_release_mutation_lock( $lock );
	}
}

function wpagent_ability_duplicate_formidable_form(): array {
	return array(
		'label'               => __( 'Formidable-Forms-Formular duplizieren', 'wp-agent-companion' ),
		'description'         => __( 'Dupliziert ein Formidable-Forms-Formular nativ und prüft die vollständige Feldstruktur per Read-back. Nicht verifizierbare Kopien bleiben für eine manuelle Prüfung erhalten.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array( 'type' => 'object', 'additionalProperties' => false, 'properties' => array( 'form_id' => array( 'type' => 'integer', 'minimum' => 1 ), 'name' => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 255 ) ), 'required' => array( 'form_id' ) ),
		'output_schema'       => wpagent_formidable_write_output_schema(),
		'execute_callback'    => 'wpagent_exec_duplicate_formidable_form',
		'permission_callback' => 'wpagent_perm_formidable_edit',
		'meta'                => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => false, 'idempotent' => false ) ),
	);
}

/** @param mixed $input @return array|WP_Error */
function wpagent_exec_duplicate_formidable_form( $input ) {
	$input  = is_array( $input ) ? $input : array();
	$source = wpagent_formidable_get_authorized_form( $input, 'frm_edit_forms' );
	if ( is_wp_error( $source ) ) {
		return $source;
	}
	$lock = wpagent_formidable_acquire_mutation_lock();
	if ( is_wp_error( $lock ) ) {
		return $lock;
	}
	$copy_id = 0;
	try {
		try {
			$source = FrmForm::getOne( absint( $input['form_id'] ?? 0 ) );
			if ( ! is_object( $source ) ) {
				return new WP_Error( 'wpagent_formidable_form_not_found', __( 'Formidable-Forms-Formular nicht gefunden.', 'wp-agent-companion' ), array( 'status' => 404 ) );
			}
			$source_payload = wpagent_formidable_form_payload( $source );
		} catch ( OverflowException $error ) {
			return wpagent_formidable_payload_limit_error();
		} catch ( Throwable $error ) {
			return wpagent_formidable_provider_error();
		}
		try {
			$copy_id = absint( FrmForm::duplicate( $source_payload['id'], false, false, false ) );
		} catch ( Throwable $error ) {
			// FrmForm::duplicate() writes the form before it duplicates fields and
			// runs its post-duplicate hook. A failure there can hide the new ID.
			return wpagent_formidable_recovery_required();
		}
		if ( $copy_id <= 0 ) {
			return new WP_Error( 'wpagent_formidable_duplicate_failed', __( 'Das Formidable-Forms-Formular konnte nicht dupliziert werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		}
		try {
			$candidate = FrmForm::getOne( $copy_id );
			if ( ! is_object( $candidate ) ) {
				throw new RuntimeException( 'Duplicated form could not be read.' );
			}
			if ( isset( $input['name'] ) ) {
				FrmForm::update( $copy_id, array( 'name' => sanitize_text_field( (string) $input['name'] ) ) );
			}
			$copy   = FrmForm::getOne( $copy_id );
			$actual = is_object( $copy ) ? wpagent_formidable_form_payload( $copy ) : array();
		} catch ( Throwable $error ) {
			// A copied form may already have received a native submission. Formidable
			// has no collection-wide CAS, so preserve the candidate for manual review.
			return wpagent_formidable_recovery_required( $copy_id );
		}
		$verified = $actual
			&& $actual['id'] !== $source_payload['id']
			&& $actual['status'] === $source_payload['status']
			&& $actual['description'] === $source_payload['description']
			&& $actual['name'] === ( isset( $input['name'] ) ? sanitize_text_field( (string) $input['name'] ) : $source_payload['name'] )
			&& wpagent_formidable_comparable_fields_match( $source_payload['fields'], $actual['fields'] );
		if ( ! $verified ) {
			// An unverified copy may contain a foreign submission added concurrently.
			// Do not delete it without an atomic provider compare-and-delete operation.
			return wpagent_formidable_recovery_required( $copy_id );
		}
		return array( 'form' => $actual, 'verified' => true );
	} finally {
		wpagent_formidable_release_mutation_lock( $lock );
	}
}

function wpagent_ability_delete_formidable_form(): array {
	return array(
		'label'               => __( 'Formidable-Forms-Formular manuell löschen', 'wp-agent-companion' ),
		'description'         => __( 'Die Fernlöschung bestehender Formidable-Forms-Formulare ist ohne atomare Provider-Prüfung nicht verfügbar. Lösche das Formular manuell in WordPress.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array(
			'type' => 'object', 'additionalProperties' => false,
			'properties' => array(
				'form_id' => array( 'type' => 'integer', 'minimum' => 1 ),
				'confirm' => array( 'type' => 'boolean' ),
				'expected_form_key' => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 100, 'pattern' => '^[A-Za-z0-9_-]+$' ),
			),
			'required' => array( 'form_id', 'confirm' ),
		),
		'output_schema'       => array( 'type' => 'object', 'properties' => array( 'form_id' => array( 'type' => 'integer' ), 'deleted' => array( 'type' => 'boolean' ) ) ),
		'execute_callback'    => 'wpagent_exec_delete_formidable_form',
		'permission_callback' => 'wpagent_perm_formidable_delete',
		'meta'                => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => true, 'idempotent' => false, 'manual_only' => true ) ),
	);
}

/** @param mixed $input @return array|WP_Error */
function wpagent_exec_delete_formidable_form( $input ) {
	$input = is_array( $input ) ? $input : array();
	if ( true !== ( $input['confirm'] ?? false ) ) {
		return new WP_Error( 'wpagent_confirmation_required', __( 'Dauerhaftes Löschen erfordert confirm=true.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$form = wpagent_formidable_get_authorized_form( $input, 'frm_delete_forms' );
	if ( is_wp_error( $form ) ) {
		return $form;
	}
	$lock = wpagent_formidable_acquire_mutation_lock();
	if ( is_wp_error( $lock ) ) {
		return $lock;
	}
	try {
		$form_id = absint( $input['form_id'] ?? 0 );
		try {
			$fresh = FrmForm::getOne( $form_id );
		} catch ( Throwable $error ) {
			return wpagent_formidable_provider_error();
		}
		if ( ! is_object( $fresh ) ) {
			return new WP_Error( 'wpagent_formidable_form_not_found', __( 'Formidable-Forms-Formular nicht gefunden.', 'wp-agent-companion' ), array( 'status' => 404 ) );
		}
		$form_key = sanitize_key( (string) ( $fresh->form_key ?? '' ) );
		if ( isset( $input['expected_form_key'] ) && sanitize_key( (string) $input['expected_form_key'] ) !== $form_key ) {
			return new WP_Error( 'wpagent_formidable_stale_form', __( 'expected_form_key stimmt nicht mehr mit dem Formular überein. Das Formular wurde nicht gelöscht.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		return new WP_Error( 'wpagent_formidable_delete_manual_only', __( 'Das dauerhafte Löschen bestehender Formidable-Forms-Formulare kann ohne atomare Provider-Prüfung nicht sicher gegen parallele Änderungen abgesichert werden. Lösche das Formular in WordPress manuell.', 'wp-agent-companion' ), array( 'status' => 409, 'form_id' => $form_id ) );
	} finally {
		wpagent_formidable_release_mutation_lock( $lock );
	}
}
