<?php
/** Verified native Elementor create, update and revision restore abilities. */

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

/** @return array<string,mixed> */
function wpagent_elementor_elements_input_schema(): array {
	return array( 'type' => 'array', 'maxItems' => WPAGENT_ELEMENTOR_MAX_ELEMENTS, 'items' => array( 'type' => 'object', 'additionalProperties' => true ) );
}

function wpagent_ability_create_elementor_page(): array {
	return array(
		'label' => __( 'Elementor-Seite erstellen', 'wp-agent-companion' ),
		'description' => __( 'Erstellt eine Elementor-Seite über die öffentliche Dokument-API und prüft Struktur, Einstellungen sowie Frontend-Ausgabe nach dem Speichern.', 'wp-agent-companion' ),
		'category' => 'wp-agent',
		'input_schema' => array(
			'type' => 'object',
			'properties' => array(
				'title' => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 200 ),
				'post_type' => array( 'type' => 'string', 'default' => 'page' ),
				'status' => array( 'type' => 'string', 'enum' => array( 'draft', 'pending', 'private', 'publish' ), 'default' => 'draft' ),
				'elements' => wpagent_elementor_elements_input_schema(),
				'settings' => array( 'type' => 'object', 'additionalProperties' => true ),
			),
			'required' => array( 'title', 'elements' ),
		),
		'output_schema' => wpagent_elementor_write_output_schema(),
		'execute_callback' => 'wpagent_exec_create_elementor_page',
		'permission_callback' => 'wpagent_perm_edit_posts',
		'meta' => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => false, 'idempotent' => false ) ),
	);
}

function wpagent_ability_update_elementor_document(): array {
	return array(
		'label' => __( 'Elementor-Dokument aktualisieren', 'wp-agent-companion' ),
		'description' => __( 'Ersetzt Struktur und/oder Seiteneinstellungen konfliktgeschützt über Elementors Dokument-API. Vorher entsteht eine wiederherstellbare Revision; bei Prüfproblemen erfolgt automatischer Rollback.', 'wp-agent-companion' ),
		'category' => 'wp-agent',
		'input_schema' => array(
			'type' => 'object',
			'properties' => array(
				'post_id' => array( 'type' => 'integer' ),
				'expected_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
				'elements' => wpagent_elementor_elements_input_schema(),
				'settings' => array( 'type' => 'object', 'additionalProperties' => true ),
			),
			'required' => array( 'post_id', 'expected_hash' ),
		),
		'output_schema' => wpagent_elementor_write_output_schema(),
		'execute_callback' => 'wpagent_exec_update_elementor_document',
		'permission_callback' => 'wpagent_perm_edit_posts',
		'meta' => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => false, 'idempotent' => true ) ),
	);
}

function wpagent_ability_restore_elementor_revision(): array {
	return array(
		'label' => __( 'Elementor-Revision wiederherstellen', 'wp-agent-companion' ),
		'description' => __( 'Stellt eine zu diesem Beitrag gehörende Elementor-Revision nur bei unverändertem Konflikt-Hash wieder her und prüft das Ergebnis. Vor dem Restore entsteht eine neue Sicherheitsrevision.', 'wp-agent-companion' ),
		'category' => 'wp-agent',
		'input_schema' => array(
			'type' => 'object',
			'properties' => array(
				'post_id' => array( 'type' => 'integer' ),
				'revision_id' => array( 'type' => 'integer' ),
				'expected_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
			),
			'required' => array( 'post_id', 'revision_id', 'expected_hash' ),
		),
		'output_schema' => wpagent_elementor_write_output_schema(),
		'execute_callback' => 'wpagent_exec_restore_elementor_revision',
		'permission_callback' => 'wpagent_perm_edit_posts',
		'meta' => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => true, 'idempotent' => false ) ),
	);
}

/** @return array<string,mixed> */
function wpagent_elementor_write_output_schema(): array {
	$schema = wpagent_elementor_document_output_schema();
	$schema['properties']['verified'] = array( 'type' => 'boolean' );
	$schema['properties']['frontend_verified'] = array( 'type' => 'boolean' );
	$schema['properties']['previous_hash'] = array( 'type' => 'string' );
	$schema['properties']['revision_id'] = array( 'type' => 'integer' );
	$schema['properties']['safety_revision_id'] = array( 'type' => 'integer' );
	return $schema;
}

/** @return array<string,mixed>|WP_Error */
function wpagent_exec_create_elementor_page( $input ) {
	$input = is_array( $input ) ? $input : array();
	if ( ! wpagent_elementor_available() ) {
		return wpagent_elementor_unavailable_error();
	}
	$title = is_string( $input['title'] ?? null ) ? trim( $input['title'] ) : '';
	$title_length = function_exists( 'mb_strlen' ) ? mb_strlen( $title, 'UTF-8' ) : strlen( $title );
	if ( '' === $title || $title_length > 200 ) {
		return new WP_Error( 'wpagent_elementor_title', __( 'Der Titel muss 1-200 Zeichen lang sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$post_type = sanitize_key( (string) ( $input['post_type'] ?? 'page' ) );
	$post_type_object = get_post_type_object( $post_type );
	if ( ! $post_type_object || ! post_type_supports( $post_type, 'elementor' ) ) {
		return new WP_Error( 'wpagent_elementor_post_type', __( 'Der Beitragstyp unterstützt Elementor nicht.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	if ( ! current_user_can( $post_type_object->cap->create_posts ) ) {
		return new WP_Error( 'wpagent_forbidden', __( 'Keine Berechtigung.', 'wp-agent-companion' ), array( 'status' => 403 ) );
	}
	$status = (string) ( $input['status'] ?? 'draft' );
	if ( ! in_array( $status, array( 'draft', 'pending', 'private', 'publish' ), true ) ) {
		return new WP_Error( 'wpagent_bad_status', __( 'Ungültiger Beitragsstatus.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$status_cap = wpagent_check_post_status_cap( $post_type, $status );
	if ( is_wp_error( $status_cap ) ) {
		return $status_cap;
	}
	$elements = $input['elements'] ?? null;
	$has_settings = array_key_exists( 'settings', $input );
	$settings = $input['settings'] ?? array();
	if ( ! is_array( $elements ) || ! array_is_list( $elements ) || ! is_array( $settings ) ) {
		return new WP_Error( 'wpagent_elementor_bad_shape', __( 'elements muss eine Liste und settings ein Objekt sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$valid = wpagent_elementor_validate_elements( $elements );
	if ( is_wp_error( $valid ) ) {
		return $valid;
	}
	$settings_valid = wpagent_elementor_validate_settings( $settings );
	if ( is_wp_error( $settings_valid ) ) {
		return $settings_valid;
	}

	$post_id = wp_insert_post( wp_slash( array( 'post_title' => $title, 'post_status' => 'draft', 'post_type' => $post_type ) ), true );
	if ( is_wp_error( $post_id ) ) {
		return $post_id;
	}
	try {
		$document = \Elementor\Plugin::$instance->documents->get( $post_id, false );
		if ( ! is_object( $document ) || ! $document->is_editable_by_current_user() ) {
			throw new RuntimeException( 'Elementor document could not be loaded.' );
		}
		$normalized = wpagent_elementor_normalize_elements( $document, $elements );
		if ( is_wp_error( $normalized ) ) {
			wp_delete_post( $post_id, true );
			return $normalized;
		}
		$document->set_is_built_with_elementor( true );
		$save_data = array( 'elements' => $elements );
		if ( $has_settings ) {
			$save_data['settings'] = $settings;
		}
		if ( ! wpagent_elementor_save_document( $document, $save_data, $has_settings ) ) {
			throw new RuntimeException( 'Elementor document save failed.' );
		}
		if ( 'draft' !== $status ) {
			$status_result = wp_update_post( array( 'ID' => $post_id, 'post_status' => $status ), true );
			if ( is_wp_error( $status_result ) ) {
				throw new RuntimeException( $status_result->get_error_message() );
			}
		}
		$fresh_document = \Elementor\Plugin::$instance->documents->get( $post_id, false );
		$state = wpagent_elementor_document_state( $post_id, $fresh_document );
		$verified = $state['built_with_elementor']
			&& wpagent_elementor_elements_contain_requested( $state['elements'], $normalized )
			&& ( ! $has_settings || wpagent_elementor_array_contains( $state['settings'], $settings ) )
			&& $status === get_post_status( $post_id );
		$frontend = $verified ? wpagent_elementor_verify_frontend( $post_id, $state['element_count'] ) : false;
		if ( ! $verified || is_wp_error( $frontend ) ) {
			wp_delete_post( $post_id, true );
			return is_wp_error( $frontend ) ? $frontend : new WP_Error( 'wpagent_elementor_verify_failed', __( 'Die Elementor-Seite bestand die Rückleseprüfung nicht und wurde entfernt.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		}
		$state['verified'] = true;
		$state['frontend_verified'] = true;
		return $state;
	} catch ( Throwable ) {
		wp_delete_post( $post_id, true );
		return new WP_Error( 'wpagent_elementor_create_failed', __( 'Die Elementor-Seite konnte nicht erstellt werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
}

/** @return array<string,mixed>|WP_Error */
function wpagent_exec_update_elementor_document( $input ) {
	$input = is_array( $input ) ? $input : array();
	$post_id = absint( $input['post_id'] ?? 0 );
	$loaded = wpagent_elementor_editable_document( $post_id );
	if ( is_wp_error( $loaded ) ) {
		return $loaded;
	}
	$expected_hash = is_string( $input['expected_hash'] ?? null ) ? $input['expected_hash'] : '';
	if ( ! preg_match( '/^[a-f0-9]{64}$/', $expected_hash ) ) {
		return new WP_Error( 'wpagent_elementor_hash', __( 'expected_hash muss ein SHA-256-Hash sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$lock = wpagent_elementor_acquire_lock( $post_id );
	if ( is_wp_error( $lock ) ) {
		return $lock;
	}
	try {
		$loaded = wpagent_elementor_editable_document( $post_id );
		if ( is_wp_error( $loaded ) ) {
			return $loaded;
		}
		$before = wpagent_elementor_document_state( $post_id, $loaded['document'] );
		if ( ! hash_equals( $before['hash'], $expected_hash ) ) {
			return new WP_Error( 'wpagent_elementor_conflict', __( 'Das Elementor-Dokument wurde seit dem Lesen verändert.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $before['hash'] ) );
		}
		$has_elements = array_key_exists( 'elements', $input );
		$has_settings = array_key_exists( 'settings', $input );
		if ( ! $has_elements && ! $has_settings ) {
			return new WP_Error( 'wpagent_elementor_no_fields', __( 'elements oder settings ist erforderlich.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$save_data = array();
		$normalized = null;
		$settings = array();
		if ( $has_elements ) {
			if ( ! is_array( $input['elements'] ) || ! array_is_list( $input['elements'] ) ) {
				return new WP_Error( 'wpagent_elementor_bad_shape', __( 'elements muss eine Liste sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
			}
			$normalized = wpagent_elementor_normalize_elements( $loaded['document'], $input['elements'] );
			if ( is_wp_error( $normalized ) ) {
				return $normalized;
			}
			$save_data['elements'] = $input['elements'];
		}
		if ( $has_settings ) {
			if ( ! is_array( $input['settings'] ) ) {
				return new WP_Error( 'wpagent_elementor_bad_shape', __( 'settings muss ein Objekt sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
			}
			$settings = $input['settings'];
			$settings_valid = wpagent_elementor_validate_settings( $settings );
			if ( is_wp_error( $settings_valid ) ) {
				return $settings_valid;
			}
			$save_data['settings'] = $settings;
		}
		$revision_id = wpagent_elementor_save_revision( $post_id, $before['hash'] );
		if ( is_wp_error( $revision_id ) ) {
			return $revision_id;
		}
		try {
			$saved = wpagent_elementor_save_document( $loaded['document'], $save_data, $has_settings );
		} catch ( Throwable ) {
			$rolled_back = wpagent_elementor_restore_revision_internal( $post_id, $revision_id, $before['hash'] );
			return new WP_Error( 'wpagent_elementor_save_failed', __( 'Elementor konnte das Dokument nicht speichern.', 'wp-agent-companion' ), array( 'status' => 500, 'rolled_back' => $rolled_back ) );
		}
		$fresh_document = \Elementor\Plugin::$instance->documents->get( $post_id, false );
		$after = is_object( $fresh_document ) ? wpagent_elementor_document_state( $post_id, $fresh_document ) : null;
		$verified = is_array( $after )
			&& true === $saved
			&& ( ! $has_elements || wpagent_elementor_elements_contain_requested( $after['elements'], $normalized ) )
			&& ( ! $has_settings || wpagent_elementor_array_contains( $after['settings'], $settings ) );
		$frontend = $verified ? wpagent_elementor_verify_frontend( $post_id, $after['element_count'] ) : false;
		if ( ! $verified || is_wp_error( $frontend ) ) {
			$rolled_back = wpagent_elementor_restore_revision_internal( $post_id, $revision_id, $before['hash'] );
			return new WP_Error(
				'wpagent_elementor_verify_failed',
				__( 'Die Elementor-Änderung bestand die Rücklese- oder Frontend-Prüfung nicht.', 'wp-agent-companion' ),
				array( 'status' => 500, 'rolled_back' => $rolled_back, 'revision_id' => $revision_id )
			);
		}
		$after['verified'] = true;
		$after['frontend_verified'] = true;
		$after['previous_hash'] = $before['hash'];
		$after['revision_id'] = $revision_id;
		return $after;
	} finally {
		wpagent_elementor_release_lock( $post_id, $lock );
	}
}

/** @return array<string,mixed>|WP_Error */
function wpagent_exec_restore_elementor_revision( $input ) {
	$input = is_array( $input ) ? $input : array();
	$post_id = absint( $input['post_id'] ?? 0 );
	$revision_id = absint( $input['revision_id'] ?? 0 );
	$loaded = wpagent_elementor_editable_document( $post_id );
	if ( is_wp_error( $loaded ) ) {
		return $loaded;
	}
	$expected_hash = is_string( $input['expected_hash'] ?? null ) ? $input['expected_hash'] : '';
	if ( ! preg_match( '/^[a-f0-9]{64}$/', $expected_hash ) ) {
		return new WP_Error( 'wpagent_elementor_hash', __( 'expected_hash muss ein SHA-256-Hash sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$lock = wpagent_elementor_acquire_lock( $post_id );
	if ( is_wp_error( $lock ) ) {
		return $lock;
	}
	try {
		$loaded = wpagent_elementor_editable_document( $post_id );
		if ( is_wp_error( $loaded ) ) {
			return $loaded;
		}
		$current = wpagent_elementor_document_state( $post_id, $loaded['document'] );
		if ( ! hash_equals( $current['hash'], $expected_hash ) ) {
			return new WP_Error( 'wpagent_elementor_conflict', __( 'Das Elementor-Dokument wurde seit dem Lesen verändert.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $current['hash'] ) );
		}
		if ( $post_id !== (int) wp_is_post_revision( $revision_id ) ) {
			return new WP_Error( 'wpagent_elementor_bad_revision', __( 'Die Revision gehört nicht zu diesem Beitrag.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$revision_document = \Elementor\Plugin::$instance->documents->get( $revision_id, false );
		if ( ! is_object( $revision_document ) || ! $revision_document->is_built_with_elementor() ) {
			return new WP_Error( 'wpagent_elementor_bad_revision', __( 'Die Revision enthält kein wiederherstellbares Elementor-Dokument.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$target = wpagent_elementor_document_state( $revision_id, $revision_document );
		$target_elements_valid = wpagent_elementor_validate_elements( $target['elements'] );
		if ( is_wp_error( $target_elements_valid ) ) {
			return $target_elements_valid;
		}
		$target_settings_valid = wpagent_elementor_validate_settings( $target['settings'] );
		if ( is_wp_error( $target_settings_valid ) ) {
			return $target_settings_valid;
		}
		$safety_revision_id = wpagent_elementor_save_revision( $post_id, $current['hash'] );
		if ( is_wp_error( $safety_revision_id ) ) {
			return $safety_revision_id;
		}
		$restored = wpagent_elementor_restore_revision_internal( $post_id, $revision_id, $target['hash'] );
		$fresh_document = \Elementor\Plugin::$instance->documents->get( $post_id, false );
		$after = is_object( $fresh_document ) ? wpagent_elementor_document_state( $post_id, $fresh_document ) : null;
		$verified = $restored && is_array( $after ) && hash_equals( $target['hash'], $after['hash'] );
		$frontend = $verified ? wpagent_elementor_verify_frontend( $post_id, $after['element_count'] ) : false;
		if ( ! $verified || is_wp_error( $frontend ) ) {
			$rolled_back = wpagent_elementor_restore_revision_internal( $post_id, $safety_revision_id, $current['hash'] );
			return new WP_Error(
				'wpagent_elementor_restore_failed',
				__( 'Die Elementor-Revision bestand die Rücklese- oder Frontend-Prüfung nicht.', 'wp-agent-companion' ),
				array( 'status' => 500, 'rolled_back' => $rolled_back, 'safety_revision_id' => $safety_revision_id )
			);
		}
		$after['verified'] = true;
		$after['frontend_verified'] = true;
		$after['previous_hash'] = $current['hash'];
		$after['revision_id'] = $revision_id;
		$after['safety_revision_id'] = $safety_revision_id;
		return $after;
	} finally {
		wpagent_elementor_release_lock( $post_id, $lock );
	}
}
