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

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

/** @return array<string,mixed> */
function wpagent_fluent_forms_write_properties_schema(): array {
	return array(
		'title' => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 255 ),
		'status' => array( 'type' => 'string', 'enum' => array( 'published', 'unpublished' ) ),
		'submit_label' => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 255 ),
	);
}

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

/** @param mixed $form @return array{form:array<string,mixed>,verified:bool}|WP_Error */
function wpagent_fluent_forms_readback( object $service, int $form_id, $form ) {
	try {
		$fresh = $service->find( $form_id );
	} catch ( Throwable $error ) {
		return new WP_Error( 'wpagent_fluent_forms_readback_failed', __( 'Das Fluent-Forms-Formular wurde gespeichert, konnte aber nicht erneut gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	$expected = wpagent_fluent_forms_form_payload( $form );
	$actual   = wpagent_fluent_forms_form_payload( $fresh );
	$verified = $expected['id'] === $actual['id']
		&& $expected['title'] === $actual['title']
		&& $expected['status'] === $actual['status']
		&& wp_json_encode( $expected['form_fields'] ) === wp_json_encode( $actual['form_fields'] );
	return array( 'form' => wpagent_fluent_forms_public_form_payload( $fresh ), 'verified' => $verified );
}

/** @param array<string,mixed> $attributes @param mixed $current @return array<string,mixed> */
function wpagent_fluent_forms_expected_payload( array $attributes, $current ): array {
	$expected = wpagent_fluent_forms_form_payload( $current );
	if ( array_key_exists( 'title', $attributes ) ) {
		$expected['title'] = sanitize_text_field( (string) $attributes['title'] );
	}
	if ( array_key_exists( 'status', $attributes ) ) {
		$expected['status'] = sanitize_key( (string) $attributes['status'] );
	}
	if ( array_key_exists( 'formFields', $attributes ) ) {
		$expected['form_fields'] = wpagent_fluent_forms_json_object( $attributes['formFields'] );
	}
	return $expected;
}

function wpagent_fluent_forms_delete_and_verify( object $service, int $form_id ): bool {
	try {
		$service->delete( $form_id );
	} catch ( Throwable $error ) {
		return false;
	}
	try {
		$remaining = $service->find( $form_id );
		return ! wpagent_fluent_forms_model_array( $remaining );
	} catch ( Throwable $error ) {
		return true;
	}
}

/** @param array<string,mixed> $snapshot */
function wpagent_fluent_forms_restore_snapshot( object $service, array $snapshot ): bool {
	$form_id = absint( $snapshot['id'] ?? 0 );
	$fields  = wp_json_encode( $snapshot['form_fields'] ?? array() );
	if ( $form_id <= 0 || false === $fields ) {
		return false;
	}
	try {
		$service->update(
			array(
				'form_id'   => $form_id,
				'title'     => (string) ( $snapshot['title'] ?? '' ),
				'status'    => (string) ( $snapshot['status'] ?? 'published' ),
				'formFields' => $fields,
			)
		);
	} catch ( Throwable $error ) {
		return false;
	}
	$readback = wpagent_fluent_forms_readback( $service, $form_id, $snapshot );
	return ! is_wp_error( $readback ) && true === $readback['verified'];
}

/** @param array<string,mixed> $input @param mixed $current @return array<string,mixed>|WP_Error */
function wpagent_fluent_forms_update_attributes( array $input, $current, bool $allow_trusted_fields = false ) {
	$current = wpagent_fluent_forms_form_payload( $current );
	$allowed = $allow_trusted_fields ? array( 'title', 'status', 'submit_label', 'form_fields' ) : array( 'title', 'status', 'submit_label' );
	$changes = array_intersect_key( $input, array_flip( $allowed ) );
	if ( ! $changes ) {
		return new WP_Error( 'wpagent_no_fields', __( 'Keine zu aktualisierende Formulareigenschaft übergeben.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$title = array_key_exists( 'title', $changes ) ? trim( (string) $changes['title'] ) : $current['title'];
	if ( '' === $title ) {
		return new WP_Error( 'wpagent_fluent_forms_title_required', __( 'Der Formulartitel darf nicht leer sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$attributes = array(
		'form_id' => $current['id'], 'title' => $title,
		'status' => array_key_exists( 'status', $changes ) ? (string) $changes['status'] : $current['status'],
	);
	if ( array_key_exists( 'form_fields', $changes ) || array_key_exists( 'submit_label', $changes ) ) {
		$form_fields = array_key_exists( 'form_fields', $changes ) ? $changes['form_fields'] : $current['form_fields'];
		if ( array_key_exists( 'submit_label', $changes ) ) {
			$submit_label = sanitize_text_field( trim( (string) $changes['submit_label'] ) );
			if ( '' === $submit_label ) {
				return new WP_Error( 'wpagent_fluent_forms_submit_label_required', __( 'Die Beschriftung der Absende-Schaltfläche darf nicht leer sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
			}
			if ( ! isset( $form_fields['submitButton'] ) || ! is_array( $form_fields['submitButton'] ) ) {
				return new WP_Error( 'wpagent_fluent_forms_bad_fields', __( 'Die gespeicherte Fluent-Forms-Schaltflächenstruktur ist ungültig.', 'wp-agent-companion' ), array( 'status' => 500 ) );
			}
			$form_fields['submitButton']['settings']['button_ui']['text'] = $submit_label;
		}
		$encoded = wpagent_fluent_forms_encode_fields( $form_fields );
		if ( is_wp_error( $encoded ) ) {
			return $encoded;
		}
		$attributes['formFields'] = $encoded;
	}
	return $attributes;
}

function wpagent_ability_create_fluent_form(): array {
	return array(
		'label' => __( 'Fluent-Forms-Formular erstellen', 'wp-agent-companion' ),
		'description' => __( 'Erstellt ein leeres Fluent-Forms-Formular über den nativen FormService, setzt Titel, Status und die Absende-Beschriftung und verifiziert das Ergebnis per Read-back. Felder werden anschließend über die sichere Feld-Ability angelegt.', 'wp-agent-companion' ),
		'category' => 'wp-agent',
		'input_schema' => array( 'type' => 'object', 'additionalProperties' => false, 'properties' => wpagent_fluent_forms_write_properties_schema(), 'required' => array( 'title' ) ),
		'output_schema' => wpagent_fluent_forms_write_output_schema(),
		'execute_callback' => 'wpagent_exec_create_fluent_form',
		'permission_callback' => 'wpagent_perm_fluent_forms_manage',
		'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_fluent_form( $input ) {
	return wpagent_exec_create_fluent_form_internal( $input, false );
}

/** @param mixed $input @return array|WP_Error */
function wpagent_exec_create_fluent_form_internal( $input, bool $allow_trusted_fields ) {
	$input = is_array( $input ) ? $input : array();
	if ( ! wpagent_perm_fluent_forms_manage() ) {
		return new WP_Error( 'wpagent_forbidden', __( 'Keine Berechtigung zum Erstellen von Fluent-Forms-Formularen.', 'wp-agent-companion' ), array( 'status' => 403 ) );
	}
	if ( ! $allow_trusted_fields ) {
		unset( $input['form_fields'] );
	}
	$title = trim( (string) ( $input['title'] ?? '' ) );
	if ( '' === $title ) {
		return new WP_Error( 'wpagent_fluent_forms_title_required', __( 'Ein nicht leerer Formulartitel ist erforderlich.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$service = wpagent_fluent_forms_service();
	if ( is_wp_error( $service ) ) {
		return $service;
	}
	try {
		$created = $service->store( array( 'title' => $title, 'predefined' => 'blank_form', 'type' => 'form' ) );
	} catch ( Throwable $error ) {
		return new WP_Error( 'wpagent_fluent_forms_create_failed', __( 'Das Fluent-Forms-Formular konnte nicht erstellt werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	$created_data = wpagent_fluent_forms_model_array( $created );
	$form_id      = absint( $created_data['id'] ?? 0 );
	if ( $form_id <= 0 ) {
		return new WP_Error( 'wpagent_fluent_forms_create_failed', __( 'Das Fluent-Forms-Formular konnte nicht erstellt werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	$attributes = wpagent_fluent_forms_update_attributes( array_merge( array( 'title' => $title ), $input ), $created, $allow_trusted_fields );
	if ( is_wp_error( $attributes ) ) {
		if ( ! wpagent_fluent_forms_delete_and_verify( $service, $form_id ) ) {
			return new WP_Error( 'wpagent_fluent_forms_rollback_failed', __( 'Das unvollständige Fluent-Forms-Formular konnte nicht zurückgerollt werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		}
		return $attributes;
	}
	$expected = wpagent_fluent_forms_expected_payload( $attributes, $created );
	try {
		$service->update( $attributes );
	} catch ( Throwable $error ) {
		if ( ! wpagent_fluent_forms_delete_and_verify( $service, $form_id ) ) {
			return new WP_Error( 'wpagent_fluent_forms_rollback_failed', __( 'Das unvollständige Fluent-Forms-Formular konnte nicht zurückgerollt werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		}
		return new WP_Error( 'wpagent_fluent_forms_create_failed', __( 'Das Fluent-Forms-Formular konnte nicht vollständig erstellt werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	$readback = wpagent_fluent_forms_readback( $service, $form_id, $expected );
	if ( is_wp_error( $readback ) || true !== $readback['verified'] ) {
		if ( ! wpagent_fluent_forms_delete_and_verify( $service, $form_id ) ) {
			return new WP_Error( 'wpagent_fluent_forms_rollback_failed', __( 'Das unvollständige Fluent-Forms-Formular konnte nicht zurückgerollt werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		}
		return new WP_Error( 'wpagent_fluent_forms_create_unverified', __( 'Das Fluent-Forms-Formular wich nach dem Speichern vom erwarteten Zustand ab und wurde entfernt.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	return $readback;
}

function wpagent_ability_update_fluent_form(): array {
	$properties                  = array_merge( array( 'form_id' => array( 'type' => 'integer', 'minimum' => 1 ) ), wpagent_fluent_forms_write_properties_schema() );
	$properties['expected_hash'] = array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' );
	return array(
		'label' => __( 'Fluent-Forms-Formular aktualisieren', 'wp-agent-companion' ),
		'description' => __( 'Aktualisiert Titel, Status oder die Absende-Beschriftung über den nativen Fluent-Forms-Updater und verifiziert das Ergebnis per Read-back. Änderungen der Absende-Beschriftung erfordern den aktuellen Feld-Hash.', 'wp-agent-companion' ),
		'category' => 'wp-agent',
		'input_schema' => array( 'type' => 'object', 'additionalProperties' => false, 'properties' => $properties, 'required' => array( 'form_id' ) ),
		'output_schema' => wpagent_fluent_forms_write_output_schema(),
		'execute_callback' => 'wpagent_exec_update_fluent_form',
		'permission_callback' => 'wpagent_perm_fluent_forms_manage',
		'meta' => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => false, 'idempotent' => true ) ),
	);
}

/** @param mixed $input @return array|WP_Error */
function wpagent_exec_update_fluent_form( $input ) {
	$input = is_array( $input ) ? $input : array();
	$form_id = absint( $input['form_id'] ?? 0 );
	if ( array_key_exists( 'submit_label', $input ) ) {
		$expected_hash = wpagent_fluent_forms_validate_fields_hash( $input['expected_hash'] ?? '' );
		if ( is_wp_error( $expected_hash ) ) {
			return $expected_hash;
		}
	}
	$lock = wpagent_fluent_forms_fields_acquire_lock( $form_id );
	if ( is_wp_error( $lock ) ) {
		return $lock;
	}
	try {
		$authorized = wpagent_fluent_forms_get_authorized_form( $input );
		if ( is_wp_error( $authorized ) ) {
			return $authorized;
		}
		if ( isset( $expected_hash ) ) {
			$current_hash = wpagent_fluent_forms_fields_hash( wpagent_fluent_forms_form_payload( $authorized['form'] )['form_fields'] );
			if ( ! hash_equals( $current_hash, $expected_hash ) ) {
				return new WP_Error( 'wpagent_fluent_forms_fields_conflict', __( 'Die Fluent-Forms-Felder wurden seit dem Lesen verändert.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $current_hash ) );
			}
		}
		return wpagent_exec_update_fluent_form_unlocked( $input, $authorized );
	} finally {
		wpagent_fluent_forms_fields_release_lock( $form_id, $lock );
	}
}

/** @param array<string,mixed> $input @param array{service:object,form:mixed}|null $authorized @return array|WP_Error */
function wpagent_exec_update_fluent_form_unlocked( array $input, ?array $authorized = null ) {
	$authorized = $authorized ?? wpagent_fluent_forms_get_authorized_form( $input );
	if ( is_wp_error( $authorized ) ) {
		return $authorized;
	}
	$attributes = wpagent_fluent_forms_update_attributes( $input, $authorized['form'] );
	if ( is_wp_error( $attributes ) ) {
		return $attributes;
	}
	$snapshot = wpagent_fluent_forms_form_payload( $authorized['form'] );
	$expected = wpagent_fluent_forms_expected_payload( $attributes, $authorized['form'] );
	try {
		$authorized['service']->update( $attributes );
	} catch ( Throwable $error ) {
		if ( ! wpagent_fluent_forms_restore_snapshot( $authorized['service'], $snapshot ) ) {
			return new WP_Error( 'wpagent_fluent_forms_rollback_failed', __( 'Der vorherige Zustand des Fluent-Forms-Formulars konnte nicht wiederhergestellt werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		}
		return new WP_Error( 'wpagent_fluent_forms_update_failed', __( 'Das Fluent-Forms-Formular konnte nicht aktualisiert werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	$readback = wpagent_fluent_forms_readback( $authorized['service'], absint( $attributes['form_id'] ), $expected );
	if ( is_wp_error( $readback ) || true !== $readback['verified'] ) {
		if ( ! wpagent_fluent_forms_restore_snapshot( $authorized['service'], $snapshot ) ) {
			return new WP_Error( 'wpagent_fluent_forms_rollback_failed', __( 'Der vorherige Zustand des Fluent-Forms-Formulars konnte nicht wiederhergestellt werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		}
		return new WP_Error( 'wpagent_fluent_forms_update_unverified', __( 'Die gespeicherte Änderung wich vom erwarteten Zustand ab und wurde zurückgerollt.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	return $readback;
}

function wpagent_ability_duplicate_fluent_form(): array {
	return array(
		'label' => __( 'Fluent-Forms-Formular duplizieren', 'wp-agent-companion' ),
		'description' => __( 'Dupliziert ein Fluent-Forms-Formular mit seinen nativen Metadaten und Dateien. Eine optionale Umbenennung wird bei Fehler vollständig zurückgerollt.', 'wp-agent-companion' ),
		'category' => 'wp-agent',
		'input_schema' => array( 'type' => 'object', 'additionalProperties' => false, 'properties' => array( 'form_id' => array( 'type' => 'integer', 'minimum' => 1 ), 'title' => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 255 ) ), 'required' => array( 'form_id' ) ),
		'output_schema' => wpagent_fluent_forms_write_output_schema(),
		'execute_callback' => 'wpagent_exec_duplicate_fluent_form',
		'permission_callback' => 'wpagent_perm_fluent_forms_manage',
		'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_fluent_form( $input ) {
	$input   = is_array( $input ) ? $input : array();
	$form_id = absint( $input['form_id'] ?? 0 );
	$lock    = wpagent_fluent_forms_fields_acquire_lock( $form_id );
	if ( is_wp_error( $lock ) ) {
		return $lock;
	}
	try {
		$authorized = wpagent_fluent_forms_get_authorized_form( $input );
		if ( is_wp_error( $authorized ) ) {
			return $authorized;
		}
		$service = $authorized['service'];
		$source  = wpagent_fluent_forms_form_payload( $authorized['form'] );
		try {
			$copy = $service->duplicate( array( 'form_id' => $source['id'] ) );
		} catch ( Throwable $error ) {
			return new WP_Error( 'wpagent_fluent_forms_duplicate_failed', __( 'Das Fluent-Forms-Formular konnte nicht dupliziert werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		}
		$copy_id = absint( wpagent_fluent_forms_model_array( $copy )['id'] ?? 0 );
		if ( $copy_id <= 0 ) {
			return new WP_Error( 'wpagent_fluent_forms_duplicate_failed', __( 'Das Fluent-Forms-Formular konnte nicht dupliziert werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		}
		$title = trim( (string) ( $input['title'] ?? '' ) );
		if ( '' !== $title ) {
			try {
				$copy = $service->update(
					array( 'form_id' => $copy_id, 'title' => $title, 'status' => wpagent_fluent_forms_form_payload( $copy )['status'] )
				);
			} catch ( Throwable $error ) {
				if ( ! wpagent_fluent_forms_delete_and_verify( $service, $copy_id ) ) {
					return new WP_Error( 'wpagent_fluent_forms_rollback_failed', __( 'Die unvollständige Formularkopie konnte nicht zurückgerollt werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
				}
				return new WP_Error( 'wpagent_fluent_forms_rename_failed', __( 'Die Formularkopie konnte nicht sicher benannt werden und wurde entfernt.', 'wp-agent-companion' ), array( 'status' => 500 ) );
			}
		}
		$readback = wpagent_fluent_forms_readback( $service, $copy_id, $copy );
		if ( is_wp_error( $readback ) ) {
			if ( ! wpagent_fluent_forms_delete_and_verify( $service, $copy_id ) ) {
				return new WP_Error( 'wpagent_fluent_forms_rollback_failed', __( 'Die unvollständige Formularkopie konnte nicht zurückgerollt werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
			}
			return new WP_Error( 'wpagent_fluent_forms_duplicate_unverified', __( 'Die Formularkopie konnte nicht verifiziert werden und wurde entfernt.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		}
		try {
			$copy_payload = wpagent_fluent_forms_form_payload( $service->find( $copy_id ) );
		} catch ( Throwable $error ) {
			$copy_payload = array();
		}
		$readback['verified'] = $readback['verified']
			&& ( $copy_payload['id'] ?? 0 ) !== $source['id']
			&& ( $copy_payload['status'] ?? '' ) === $source['status']
			&& wp_json_encode( $copy_payload['form_fields'] ?? array() ) === wp_json_encode( $source['form_fields'] )
			&& ( '' === $title || ( $copy_payload['title'] ?? '' ) === $title );
		if ( true !== $readback['verified'] ) {
			if ( ! wpagent_fluent_forms_delete_and_verify( $service, $copy_id ) ) {
				return new WP_Error( 'wpagent_fluent_forms_rollback_failed', __( 'Die unvollständige Formularkopie konnte nicht zurückgerollt werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
			}
			return new WP_Error( 'wpagent_fluent_forms_duplicate_unverified', __( 'Die Formularkopie wich vom Quellformular ab und wurde entfernt.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		}
		return $readback;
	} finally {
		wpagent_fluent_forms_fields_release_lock( $form_id, $lock );
	}
}

function wpagent_ability_delete_fluent_form(): array {
	return array(
		'label' => __( 'Fluent-Forms-Formular dauerhaft löschen', 'wp-agent-companion' ),
		'description' => __( 'Löscht ein Fluent-Forms-Formular über den nativen FormService. confirm=true ist zwingend erforderlich.', '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' ) ), '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_fluent_form',
		'permission_callback' => 'wpagent_perm_fluent_forms_manage',
		'meta' => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => true, 'idempotent' => false ) ),
	);
}

/** @param mixed $input @return array|WP_Error */
function wpagent_exec_delete_fluent_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_id = absint( $input['form_id'] ?? 0 );
	$lock    = wpagent_fluent_forms_fields_acquire_lock( $form_id );
	if ( is_wp_error( $lock ) ) {
		return $lock;
	}
	try {
		$authorized = wpagent_fluent_forms_get_authorized_form( $input );
		if ( is_wp_error( $authorized ) ) {
			return $authorized;
		}
		if ( ! wpagent_fluent_forms_delete_and_verify( $authorized['service'], $form_id ) ) {
			return new WP_Error( 'wpagent_fluent_forms_delete_failed', __( 'Das Fluent-Forms-Formular konnte nicht gelöscht werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		}
		return array( 'form_id' => $form_id, 'deleted' => true );
	} finally {
		wpagent_fluent_forms_fields_release_lock( $form_id, $lock );
	}
}
