<?php
/** Read-only Beaver Builder document, module catalog and schema abilities. */

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

/** @return array<string,mixed> */
function wpagent_beaver_node_output_schema(): array {
	return array(
		'type'                 => 'object',
		'properties' => array(
			'id'          => array( 'type' => 'string', 'maxLength' => 64 ),
			'type'        => array( 'type' => 'string', 'maxLength' => 32 ),
			'module_type' => array( 'type' => 'string', 'maxLength' => 64 ),
			'parent'      => array( 'type' => 'string', 'maxLength' => 64 ),
			'position'    => array( 'type' => 'integer', 'minimum' => 0, 'maximum' => WPAGENT_BEAVER_MAX_NODES ),
			'writable'    => array( 'type' => 'boolean' ),
			'settings'    => wpagent_beaver_settings_document_schema(),
		),
		'required'             => array( 'id', 'type', 'module_type', 'parent', 'position', 'writable', 'settings' ),
		'additionalProperties' => false,
	);
}

/** @return array<string,mixed> */
function wpagent_beaver_document_output_schema(): array {
	return array(
		'type'                 => 'object',
		'properties' => array(
			'post_id'         => array( 'type' => 'integer', 'minimum' => 1 ),
			'title'           => array( 'type' => 'string', 'maxLength' => 500 ),
			'status'          => array( 'type' => 'string', 'maxLength' => 32 ),
			'version'         => array( 'type' => 'string', 'maxLength' => 64 ),
			'builder_enabled' => array( 'type' => 'boolean' ),
			'hash'            => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
			'node_count'      => array( 'type' => 'integer', 'minimum' => 0, 'maximum' => WPAGENT_BEAVER_MAX_NODES ),
			'nodes'           => array( 'type' => 'array', 'maxItems' => WPAGENT_BEAVER_MAX_NODES, 'items' => wpagent_beaver_node_output_schema() ),
		),
		'required'             => array( 'post_id', 'title', 'status', 'version', 'builder_enabled', 'hash', 'node_count', 'nodes' ),
		'additionalProperties' => false,
	);
}

function wpagent_ability_get_beaver_document(): array {
	return array(
		'label'               => __( 'Beaver-Builder-Dokument lesen', 'wp-agent-companion' ),
		'description'         => __( 'Liest ein aktives Beaver-Builder-Layout als begrenzte flache Knotenliste und liefert eine Konflikt-Prüfsumme.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array(
			'type'                 => 'object',
			'properties' => array( 'post_id' => array( 'type' => 'integer', 'minimum' => 1 ) ),
			'required'             => array( 'post_id' ),
			'additionalProperties' => false,
		),
		'output_schema'       => wpagent_beaver_document_output_schema(),
		'execute_callback'    => 'wpagent_exec_get_beaver_document',
		'permission_callback' => 'wpagent_perm_edit_posts',
		'meta'                => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => true, 'destructive' => false, 'idempotent' => true ) ),
	);
}

/** @return array<string,mixed>|WP_Error */
function wpagent_exec_get_beaver_document( $input ) {
	$input   = is_array( $input ) ? $input : array();
	$post_id = absint( $input['post_id'] ?? 0 );
	return wpagent_beaver_document_state( $post_id );
}

function wpagent_ability_list_beaver_modules(): array {
	return array(
		'label'               => __( 'Beaver-Builder-Module auflisten', 'wp-agent-companion' ),
		'description'         => __( 'Listet installierte, im sicheren Schreibpfad zulässige Beaver-Builder-Module ohne ausführbare Rohmodule.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array(
			'type'                 => 'object',
			'properties' => array(
				'search'   => array( 'type' => 'string', 'maxLength' => 200 ),
				'page'     => array( 'type' => 'integer', 'minimum' => 1 ),
				'per_page' => array( 'type' => 'integer', 'minimum' => 1, 'maximum' => 100 ),
			),
			'additionalProperties' => false,
		),
		'output_schema'       => array(
			'type'                 => 'object',
			'properties' => array(
				'modules'     => array(
					'type'  => 'array',
					'maxItems' => 100,
					'items' => array(
						'type'                 => 'object',
						'properties' => array(
							'type'             => array( 'type' => 'string', 'maxLength' => 64 ),
							'name'             => array( 'type' => 'string', 'maxLength' => 200 ),
							'description'      => array( 'type' => 'string', 'maxLength' => 500 ),
							'category'         => array( 'type' => 'string', 'maxLength' => 200 ),
							'accepts_children' => array( 'type' => 'boolean' ),
						),
						'required'             => array( 'type', 'name', 'description', 'category', 'accepts_children' ),
						'additionalProperties' => false,
					),
				),
				'total'       => array( 'type' => 'integer' ),
				'page'        => array( 'type' => 'integer' ),
				'per_page'    => array( 'type' => 'integer' ),
				'total_pages' => array( 'type' => 'integer' ),
			),
			'required'             => array( 'modules', 'total', 'page', 'per_page', 'total_pages' ),
			'additionalProperties' => false,
		),
		'execute_callback'    => 'wpagent_exec_list_beaver_modules',
		'permission_callback' => 'wpagent_perm_edit_posts',
		'meta'                => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => true, 'destructive' => false, 'idempotent' => true ) ),
	);
}

/** @return array<string,mixed>|WP_Error */
function wpagent_exec_list_beaver_modules( $input = array() ) {
	if ( ! wpagent_beaver_available() ) {
		return wpagent_beaver_unavailable_error();
	}
	$input    = is_array( $input ) ? $input : array();
	$search   = trim( sanitize_text_field( is_string( $input['search'] ?? null ) ? $input['search'] : '' ) );
	$page     = max( 1, min( PHP_INT_MAX, absint( $input['page'] ?? 1 ) ) );
	$per_page = max( 1, min( 100, absint( $input['per_page'] ?? 50 ) ) );
	$modules  = array();
	foreach ( FLBuilderModel::$modules as $type => $module ) {
		$type = sanitize_key( (string) $type );
		if ( '' === $type || in_array( $type, wpagent_beaver_unsafe_module_types(), true ) || ! is_object( $module ) ) {
			continue;
		}
		try {
			$name        = sanitize_text_field( is_string( $module->name ?? null ) ? $module->name : $type );
			$description = wp_html_excerpt( sanitize_text_field( is_string( $module->description ?? null ) ? $module->description : '' ), 500, '' );
			$category    = sanitize_text_field( is_string( $module->category ?? null ) ? $module->category : '' );
			$haystack    = strtolower( $type . ' ' . $name . ' ' . $description . ' ' . $category );
			if ( '' !== $search && ! str_contains( $haystack, strtolower( $search ) ) ) {
				continue;
			}
			$modules[] = array(
				'type'             => $type,
				'name'             => wp_html_excerpt( $name, 200, '' ),
				'description'      => $description,
				'category'         => wp_html_excerpt( $category, 200, '' ),
				'accepts_children' => method_exists( $module, 'accepts_children' ) && (bool) $module->accepts_children(),
			);
		} catch ( Throwable $error ) {
			continue;
		}
	}
	usort( $modules, static fn( array $left, array $right ): int => strcmp( $left['type'], $right['type'] ) );
	$total       = count( $modules );
	$total_pages = $total > 0 ? (int) ceil( $total / $per_page ) : 0;
	$offset      = $page > intdiv( PHP_INT_MAX, $per_page ) ? PHP_INT_MAX : ( $page - 1 ) * $per_page;
	return array(
		'modules'     => $offset >= $total ? array() : array_slice( $modules, $offset, $per_page ),
		'total'       => $total,
		'page'        => $page,
		'per_page'    => $per_page,
		'total_pages' => $total_pages,
	);
}

/** @param mixed $value */
function wpagent_beaver_bounded_schema_value( $value ) {
	if ( is_null( $value ) ) {
		return '';
	}
	if ( is_bool( $value ) ) {
		return $value ? 'true' : 'false';
	}
	if ( is_int( $value ) || is_float( $value ) ) {
		return (string) $value;
	}
	if ( is_string( $value ) ) {
		return wp_html_excerpt( wp_strip_all_tags( $value ), 500, '' );
	}
	if ( is_array( $value ) && count( $value ) <= 100 ) {
		$result = array();
		foreach ( $value as $key => $item ) {
			if ( ! is_scalar( $item ) && ! is_null( $item ) ) {
				continue;
			}
			$result[ is_scalar( $key ) ? (string) $key : '' ] = wpagent_beaver_bounded_schema_value( $item );
		}
		$encoded = wp_json_encode( $result, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );
		return is_string( $encoded ) ? wp_html_excerpt( $encoded, 2000, '' ) : '';
	}
	return '';
}

/** @return array<string,mixed> */
function wpagent_beaver_field_summary( string $name, array $field ): array {
	$options = array();
	foreach ( is_array( $field['options'] ?? null ) ? array_slice( $field['options'], 0, 100, true ) : array() as $value => $label ) {
		if ( ! is_scalar( $value ) || ! is_scalar( $label ) ) {
			continue;
		}
		$options[] = array( 'value' => wp_html_excerpt( (string) $value, 500, '' ), 'label' => wp_html_excerpt( wp_strip_all_tags( (string) $label ), 500, '' ) );
	}
	return array(
		'name'       => $name,
		'type'       => sanitize_key( is_string( $field['type'] ?? null ) ? $field['type'] : 'text' ),
		'label'      => wp_html_excerpt( wp_strip_all_tags( is_string( $field['label'] ?? null ) ? $field['label'] : $name ), 500, '' ),
		'default'    => wpagent_beaver_bounded_schema_value( $field['default'] ?? null ),
		'options'    => $options,
		'responsive' => ! empty( $field['responsive'] ),
	);
}

function wpagent_ability_get_beaver_module_schema(): array {
	return array(
		'label'               => __( 'Beaver-Builder-Modulschema lesen', 'wp-agent-companion' ),
		'description'         => __( 'Liest die begrenzten, schreibbaren Einstellungsfelder eines installierten sicheren Beaver-Builder-Moduls.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array(
			'type'                 => 'object',
			'properties'           => array( 'module_type' => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 64, 'pattern' => '^[a-z0-9_-]+$' ) ),
			'required'             => array( 'module_type' ),
			'additionalProperties' => false,
		),
		'output_schema'       => array(
			'type'                 => 'object',
			'properties' => array(
				'module_type' => array( 'type' => 'string', 'maxLength' => 64 ),
				'fields'      => array(
					'type'  => 'array',
					'maxItems' => WPAGENT_BEAVER_MAX_FIELDS,
					'items' => array(
						'type'                 => 'object',
						'properties' => array(
							'name'       => array( 'type' => 'string', 'maxLength' => 128 ),
							'type'       => array( 'type' => 'string', 'maxLength' => 64 ),
							'label'      => array( 'type' => 'string', 'maxLength' => 500 ),
							'default'    => array( 'type' => 'string', 'maxLength' => 2000 ),
							'options'    => array( 'type' => 'array', 'maxItems' => 100, 'items' => array( 'type' => 'object', 'properties' => array( 'value' => array( 'type' => 'string', 'maxLength' => 500 ), 'label' => array( 'type' => 'string', 'maxLength' => 500 ) ), 'required' => array( 'value', 'label' ), 'additionalProperties' => false ) ),
							'responsive' => array( 'type' => 'boolean' ),
						),
						'required'             => array( 'name', 'type', 'label', 'default', 'options', 'responsive' ),
						'additionalProperties' => false,
					),
				),
				'field_count' => array( 'type' => 'integer', 'minimum' => 0, 'maximum' => WPAGENT_BEAVER_MAX_FIELDS ),
			),
			'required'             => array( 'module_type', 'fields', 'field_count' ),
			'additionalProperties' => false,
		),
		'execute_callback'    => 'wpagent_exec_get_beaver_module_schema',
		'permission_callback' => 'wpagent_perm_edit_posts',
		'meta'                => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => true, 'destructive' => false, 'idempotent' => true ) ),
	);
}

/** @return array<string,mixed>|WP_Error */
function wpagent_exec_get_beaver_module_schema( $input ) {
	if ( ! wpagent_beaver_available() ) {
		return wpagent_beaver_unavailable_error();
	}
	$input       = is_array( $input ) ? $input : array();
	$module_type = sanitize_key( is_string( $input['module_type'] ?? null ) ? $input['module_type'] : '' );
	$module      = wpagent_beaver_module( $module_type );
	if ( is_wp_error( $module ) ) {
		return $module;
	}
	$fields = FLBuilderModel::get_settings_form_fields( $module->form );
	if ( ! is_array( $fields ) || count( $fields ) > WPAGENT_BEAVER_MAX_FIELDS ) {
		return new WP_Error( 'wpagent_beaver_schema_limit', __( 'Das Beaver-Builder-Modulschema ist nicht verfügbar oder zu groß.', 'wp-agent-companion' ), array( 'status' => 413 ) );
	}
	$output = array();
	foreach ( $fields as $name => $field ) {
		if ( ! is_string( $name ) || ! is_array( $field ) || ! wpagent_beaver_field_is_writable( $name, $field ) ) {
			continue;
		}
		$output[] = wpagent_beaver_field_summary( $name, $field );
	}
	return array( 'module_type' => $module_type, 'fields' => $output, 'field_count' => count( $output ) );
}
