<?php
/** Gravity Forms create, update, duplicate and delete through GFAPI. */

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

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

/** @return array<string,mixed>|WP_Error */
function wpagent_gravity_changes( array $input, bool $creating = false ) {
	$changes = array();
	foreach ( array( 'title', 'description', 'fields', 'notifications', 'confirmations' ) as $key ) {
		if ( array_key_exists( $key, $input ) ) {
			$changes[ $key ] = $input[ $key ];
		}
	}
	if ( array_key_exists( 'submit_label', $input ) ) {
		$submit_label = trim( (string) $input['submit_label'] );
		if ( '' === $submit_label ) {
			return new WP_Error( 'wpagent_gravity_submit_label_required', __( 'Die Beschriftung der Absende-Schaltfläche darf nicht leer sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$changes['button'] = array( 'type' => 'text', 'text' => sanitize_text_field( $submit_label ), 'imageUrl' => '' );
	}
	if ( $creating && '' === trim( (string) ( $changes['title'] ?? '' ) ) ) {
		return new WP_Error( 'wpagent_gravity_title_required', __( 'Ein nicht leerer Formulartitel ist erforderlich.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	if ( array_key_exists( 'title', $changes ) && '' === trim( (string) $changes['title'] ) ) {
		return new WP_Error( 'wpagent_gravity_title_required', __( 'Der Formulartitel darf nicht leer sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	if ( $creating && ! isset( $changes['fields'] ) ) {
		$changes['fields'] = array();
	}
	$settings = is_array( $input['settings'] ?? null ) ? $input['settings'] : array();
	$unknown_settings = array_diff( array_keys( $settings ), wpagent_gravity_setting_keys() );
	if ( ! empty( $unknown_settings ) ) {
		return new WP_Error( 'wpagent_gravity_unknown_setting', __( 'Mindestens eine Gravity-Forms-Einstellung wird nicht unterstützt.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	foreach ( wpagent_gravity_setting_keys() as $key ) {
		if ( array_key_exists( $key, $settings ) ) {
			$changes[ $key ] = $settings[ $key ];
		}
	}
	return $changes;
}

/** @param array<string,mixed> $expected @return array{form:array<string,mixed>,verified:bool}|WP_Error */
function wpagent_gravity_readback( int $form_id, array $expected ) {
	if ( ! is_callable( array( 'GFAPI', 'get_form' ) ) ) {
		return wpagent_gravity_missing_error();
	}
	$fresh = GFAPI::get_form( $form_id );
	if ( ! is_array( $fresh ) ) {
		return new WP_Error( 'wpagent_gravity_readback_failed', __( 'Das Gravity-Forms-Formular wurde gespeichert, konnte aber nicht erneut gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	$remaining_expected = $expected;
	$verified           = true;
	foreach ( array( 'fields', 'notifications', 'confirmations' ) as $collection ) {
		if ( ! array_key_exists( $collection, $remaining_expected ) ) {
			continue;
		}
		if ( ! wpagent_gravity_collection_matches( $remaining_expected[ $collection ], $fresh[ $collection ] ?? null ) ) {
			$verified = false;
			break;
		}
		unset( $remaining_expected[ $collection ] );
	}
	if ( $verified ) {
		$verified = wpagent_gravity_subset_matches( $remaining_expected, $fresh );
	}
	return array( 'form' => wpagent_gravity_form_payload( $fresh ), 'verified' => $verified );
}

function wpagent_ability_create_gravity_form(): array {
	return array(
		'label' => __( 'Gravity-Forms-Formular erstellen', 'wp-agent-companion' ),
		'description' => __( 'Erstellt ein Gravity-Forms-Formular über GFAPI::add_form() und verifiziert Felder und Einstellungen per Read-back.', 'wp-agent-companion' ),
		'category' => 'wp-agent',
		'input_schema' => array( 'type' => 'object', 'additionalProperties' => false, 'properties' => wpagent_gravity_write_properties_schema(), 'required' => array( 'title' ) ),
		'output_schema' => wpagent_gravity_write_output_schema(),
		'execute_callback' => 'wpagent_exec_create_gravity_form',
		'permission_callback' => 'wpagent_perm_gravity_create',
		'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_gravity_form( $input ) {
	if ( ! wpagent_gravity_available() || ! is_callable( array( 'GFAPI', 'add_form' ) ) ) {
		return wpagent_gravity_missing_error();
	}
	if ( ! current_user_can( 'gravityforms_create_form' ) ) {
		return new WP_Error( 'wpagent_forbidden', __( 'Keine Berechtigung zum Erstellen von Gravity-Forms-Formularen.', 'wp-agent-companion' ), array( 'status' => 403 ) );
	}
	$changes = wpagent_gravity_changes( is_array( $input ) ? $input : array(), true );
	if ( is_wp_error( $changes ) ) {
		return $changes;
	}
	$form_id = GFAPI::add_form( $changes );
	if ( is_wp_error( $form_id ) ) {
		return $form_id;
	}
	$form_id = absint( $form_id );
	return $form_id > 0 ? wpagent_gravity_readback( $form_id, $changes ) : new WP_Error( 'wpagent_gravity_create_failed', __( 'Das Gravity-Forms-Formular konnte nicht erstellt werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
}

function wpagent_ability_update_gravity_form(): array {
	return array(
		'label' => __( 'Gravity-Forms-Formular aktualisieren', 'wp-agent-companion' ),
		'description' => __( 'Aktualisiert dokumentierte Eigenschaften über GFAPI::update_form() und verifiziert die Änderung per Read-back.', 'wp-agent-companion' ),
		'category' => 'wp-agent',
		'input_schema' => array( 'type' => 'object', 'additionalProperties' => false, 'properties' => array_merge( array( 'form_id' => array( 'type' => 'integer', 'minimum' => 1 ) ), wpagent_gravity_write_properties_schema() ), 'required' => array( 'form_id' ) ),
		'output_schema' => wpagent_gravity_write_output_schema(),
		'execute_callback' => 'wpagent_exec_update_gravity_form',
		'permission_callback' => 'wpagent_perm_gravity_edit',
		'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_gravity_form( $input ) {
	if ( ! is_callable( array( 'GFAPI', 'update_form' ) ) ) {
		return wpagent_gravity_missing_error();
	}
	$input = is_array( $input ) ? $input : array();
	$form  = wpagent_gravity_get_authorized_form( $input, 'gravityforms_edit_forms' );
	if ( is_wp_error( $form ) ) {
		return $form;
	}
	$changes = wpagent_gravity_changes( $input );
	if ( is_wp_error( $changes ) ) {
		return $changes;
	}
	if ( empty( $changes ) ) {
		return new WP_Error( 'wpagent_no_fields', __( 'Keine zu aktualisierende Formulareigenschaft übergeben.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$updated = array_replace( $form, $changes );
	$result  = GFAPI::update_form( $updated, absint( $form['id'] ?? 0 ) );
	if ( is_wp_error( $result ) ) {
		return $result;
	}
	if ( true !== $result ) {
		return new WP_Error( 'wpagent_gravity_update_failed', __( 'Das Gravity-Forms-Formular konnte nicht aktualisiert werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	return wpagent_gravity_readback( absint( $form['id'] ?? 0 ), $changes );
}

function wpagent_ability_duplicate_gravity_form(): array {
	return array(
		'label' => __( 'Gravity-Forms-Formular duplizieren', 'wp-agent-companion' ),
		'description' => __( 'Dupliziert ein Gravity-Forms-Formular über GFAPI::duplicate_form() und verifiziert die Kopie.', '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_gravity_write_output_schema(),
		'execute_callback' => 'wpagent_exec_duplicate_gravity_form',
		'permission_callback' => 'wpagent_perm_gravity_duplicate',
		'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_gravity_form( $input ) {
	$input  = is_array( $input ) ? $input : array();
	$source = wpagent_gravity_get_authorized_form( $input, 'gravityforms_edit_forms' );
	if ( is_wp_error( $source ) ) {
		return $source;
	}
	if ( ! current_user_can( 'gravityforms_create_form' ) ) {
		return new WP_Error( 'wpagent_forbidden', __( 'Keine Berechtigung zum Duplizieren von Gravity-Forms-Formularen.', 'wp-agent-companion' ), array( 'status' => 403 ) );
	}
	$title = trim( (string) ( $input['title'] ?? '' ) );
	if ( ! is_callable( array( 'GFAPI', 'duplicate_form' ) )
		|| ( '' !== $title && ( ! is_callable( array( 'GFAPI', 'update_form_property' ) ) || ! is_callable( array( 'GFAPI', 'delete_form' ) ) ) ) ) {
		return wpagent_gravity_missing_error();
	}
	$form_id = GFAPI::duplicate_form( absint( $source['id'] ?? 0 ) );
	if ( is_wp_error( $form_id ) ) {
		return $form_id;
	}
	$form_id = absint( $form_id );
	if ( '' !== $title ) {
		$renamed = GFAPI::update_form_property( $form_id, 'title', $title );
		if ( is_wp_error( $renamed ) || false === $renamed ) {
			GFAPI::delete_form( $form_id );
			return is_wp_error( $renamed ) ? $renamed : new WP_Error( 'wpagent_gravity_copy_rename_failed', __( 'Die Formularkopie konnte nicht sicher benannt werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		}
	}
	$expected = array();
	foreach ( array( 'description', 'fields', 'button', 'notifications', 'confirmations' ) as $key ) {
		if ( array_key_exists( $key, $source ) ) {
			$expected[ $key ] = $source[ $key ];
		}
	}
	foreach ( wpagent_gravity_setting_keys() as $key ) {
		if ( array_key_exists( $key, $source ) ) {
			$expected[ $key ] = $source[ $key ];
		}
	}
	if ( '' !== $title ) {
		$expected['title'] = $title;
	}
	return wpagent_gravity_readback( $form_id, $expected );
}

function wpagent_ability_delete_gravity_form(): array {
	return array(
		'label' => __( 'Gravity-Forms-Formular dauerhaft löschen', 'wp-agent-companion' ),
		'description' => __( 'Löscht ein Gravity-Forms-Formular dauerhaft über GFAPI::delete_form(). 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_gravity_form',
		'permission_callback' => 'wpagent_perm_gravity_delete',
		'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_gravity_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_gravity_get_authorized_form( $input, 'gravityforms_delete_forms' );
	if ( is_wp_error( $form ) ) {
		return $form;
	}
	if ( ! is_callable( array( 'GFAPI', 'delete_form' ) ) ) {
		return wpagent_gravity_missing_error();
	}
	$form_id = absint( $form['id'] ?? 0 );
	$deleted = GFAPI::delete_form( $form_id );
	if ( is_wp_error( $deleted ) ) {
		return $deleted;
	}
	if ( true !== $deleted ) {
		return new WP_Error( 'wpagent_gravity_delete_failed', __( 'Das Gravity-Forms-Formular konnte nicht gelöscht werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	if ( false !== GFAPI::get_form( $form_id ) ) {
		return new WP_Error( 'wpagent_gravity_delete_unverified', __( 'Gravity Forms meldete das Formular als gelöscht, die anschließende Prüfung konnte dies aber nicht bestätigen.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	return array( 'form_id' => $form_id, 'deleted' => true );
}
