<?php
/** Read-only Astra design inventory with provider-backed current values. */

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

/** @return array<string,mixed> */
function wpagent_astra_bounded_scalar_schema(): array {
	return array(
		'anyOf' => array(
		array( 'type' => 'string', 'maxLength' => 8192 ),
		array( 'type' => 'integer', 'minimum' => -2147483648, 'maximum' => 2147483647 ),
		array( 'type' => 'number', 'minimum' => -1000000000, 'maximum' => 1000000000 ),
		array( 'type' => 'boolean' ),
		array( 'type' => 'null' ),
		),
	);
}

/**
 * Astra publishes provider schemas as data. Keep that data structurally finite
 * without pretending that the provider's 21 read payloads share one shape.
 *
 * @return array<string,mixed>
 */
function wpagent_astra_bounded_value_schema( int $depth = 0 ): array {
	$variants = wpagent_astra_bounded_scalar_schema()['anyOf'];
	// Astra's curated payloads reach a component list at four levels. Keeping
	// the representation unrolled only to that proven depth avoids a recursive
	// MCP schema expansion while retaining every provider value we return.
	if ( $depth >= 4 ) {
		return array( 'anyOf' => $variants );
	}
	$child      = wpagent_astra_bounded_value_schema( $depth + 1 );
	$variants[] = array(
		'type'                 => 'object',
		'minProperties'        => 0,
		'maxProperties'        => 64,
		'propertyNames'        => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 128, 'pattern' => '^[A-Za-z0-9][A-Za-z0-9_.:-]{0,127}$' ),
		'additionalProperties' => $child,
	);
	$variants[] = array(
		'type'     => 'array',
		'maxItems' => 64,
		'items'    => $child,
	);
	return array( 'anyOf' => $variants );
}

/** @return array<string,mixed> */
function wpagent_astra_bounded_object_schema(): array {
	return array(
		'type'                 => 'object',
		'minProperties'        => 0,
		'maxProperties'        => 64,
		'propertyNames'        => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 128, 'pattern' => '^[A-Za-z0-9][A-Za-z0-9_.:-]{0,127}$' ),
		'additionalProperties' => wpagent_astra_bounded_value_schema(),
	);
}

/** @return array<string,mixed> */
function wpagent_astra_catalog_schema_leaf(): array {
	return array(
		'type'                 => 'object',
		'minProperties'        => 1,
		'maxProperties'        => 8,
		'properties'           => array(
			'type' => array(
				'anyOf' => array(
					array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 16 ),
					array( 'type' => 'array', 'minItems' => 1, 'maxItems' => 2, 'items' => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 16 ) ),
				),
			),
			'enum' => array( 'type' => 'array', 'maxItems' => 64, 'items' => wpagent_astra_bounded_scalar_schema() ),
		),
		'additionalProperties' => false,
	);
}

/**
 * Bounded representation of a curated JSON Schema document. The document
 * shape is intentionally not recursive: Astra's catalog reaches at most four
 * nested property maps, while list items are scalar schema leaves.
 *
 * @return array<string,mixed>
 */
function wpagent_astra_catalog_schema_document( int $depth = 0 ): array {
	$leaf = wpagent_astra_catalog_schema_leaf();
	$next = $depth >= 4 ? $leaf : wpagent_astra_catalog_schema_document( $depth + 1 );
	return array(
		'type'                 => 'object',
		'minProperties'        => 1,
		'maxProperties'        => 16,
		'properties'           => array(
			'type'                 => $leaf['properties']['type'],
			'properties'           => array( 'type' => 'object', 'maxProperties' => 64, 'propertyNames' => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 128, 'pattern' => '^[A-Za-z0-9][A-Za-z0-9_.:-]{0,127}$' ), 'additionalProperties' => $next ),
			'required'             => array( 'type' => 'array', 'maxItems' => 64, 'items' => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 128 ) ),
			'minProperties'        => array( 'type' => 'integer', 'minimum' => 0, 'maximum' => 64 ),
			'maxProperties'        => array( 'type' => 'integer', 'minimum' => 0, 'maximum' => 64 ),
			'additionalProperties' => array( 'type' => 'boolean' ),
			'items'                => $leaf,
			'enum'                 => $leaf['properties']['enum'],
			'uniqueItems'          => array( 'type' => 'boolean' ),
			'pattern'              => array( 'type' => 'string', 'maxLength' => 512 ),
			'minimum'              => array( 'type' => 'number', 'minimum' => -1000000000, 'maximum' => 1000000000 ),
			'maximum'              => array( 'type' => 'number', 'minimum' => -1000000000, 'maximum' => 1000000000 ),
			'minLength'            => array( 'type' => 'integer', 'minimum' => 0, 'maximum' => 8192 ),
			'maxLength'            => array( 'type' => 'integer', 'minimum' => 0, 'maximum' => 8192 ),
			'maxItems'             => array( 'type' => 'integer', 'minimum' => 0, 'maximum' => 64 ),
			'default'              => wpagent_astra_bounded_scalar_schema(),
		),
		'additionalProperties' => false,
	);
}

/** @param array<string,mixed> $schema @return array<string,mixed> */
function wpagent_astra_bound_catalog_schema( array $schema ): array {
	foreach ( array( 'properties' ) as $keyword ) {
		if ( isset( $schema[ $keyword ] ) && is_array( $schema[ $keyword ] ) ) {
			foreach ( $schema[ $keyword ] as $key => $child ) {
				if ( is_array( $child ) ) {
					$schema[ $keyword ][ $key ] = wpagent_astra_bound_catalog_schema( $child );
				}
			}
		}
	}
	if ( isset( $schema['items'] ) && is_array( $schema['items'] ) ) {
		$schema['items'] = wpagent_astra_bound_catalog_schema( $schema['items'] );
	}
	foreach ( array( 'anyOf', 'oneOf', 'allOf' ) as $keyword ) {
		if ( isset( $schema[ $keyword ] ) && is_array( $schema[ $keyword ] ) ) {
			foreach ( $schema[ $keyword ] as $key => $child ) {
				if ( is_array( $child ) ) {
					$schema[ $keyword ][ $key ] = wpagent_astra_bound_catalog_schema( $child );
				}
			}
		}
	}
	$type = $schema['type'] ?? null;
	if ( 'object' === $type && isset( $schema['properties'] ) && is_array( $schema['properties'] ) ) {
		$schema['maxProperties'] = count( $schema['properties'] );
	}
	if ( 'array' === $type && ! isset( $schema['maxItems'] ) ) {
		$schema['maxItems'] = 64;
	}
	return $schema;
}

function wpagent_ability_get_astra_design(): array {
	return array(
		'label'               => __( 'Astra-Design lesen', 'wp-agent-companion' ),
		'description'         => __( 'Liest 21 sichere Astra-Designbereiche samt strikten Eingabeschemata und Zustands-Hash.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array( 'type' => 'object', 'properties' => array(), 'maxProperties' => 0, 'additionalProperties' => false, 'default' => array() ),
		'output_schema'       => array(
			'type'                 => 'object',
			'properties'           => array(
				'active'            => array( 'type' => 'boolean' ),
				'version'           => array( 'type' => 'string', 'maxLength' => 64 ),
				'abilities_enabled' => array( 'type' => 'boolean' ),
				'operations'        => array(
					'type'     => 'array',
					'maxItems' => count( wpagent_astra_operation_catalog() ),
					'items'    => array(
						'type'                 => 'object',
						'properties'           => array(
							'id'           => array( 'type' => 'string', 'enum' => array_keys( wpagent_astra_operation_catalog() ) ),
							'label'        => array( 'type' => 'string', 'maxLength' => 200 ),
							'input_schema' => wpagent_astra_catalog_schema_document(),
							'current'      => wpagent_astra_bounded_object_schema(),
						),
						'required'             => array( 'id', 'label', 'input_schema', 'current' ),
						'maxProperties'        => 4,
						'additionalProperties' => false,
					),
				),
				'state_hash'        => array( 'type' => array( 'string', 'null' ), 'pattern' => '^[a-f0-9]{64}$' ),
			),
			'required'             => array( 'active', 'version', 'abilities_enabled', 'operations', 'state_hash' ),
			'maxProperties'        => 5,
			'additionalProperties' => false,
		),
		'execute_callback'    => 'wpagent_exec_get_astra_design',
		'permission_callback' => 'wpagent_perm_manage_options',
		'meta'                => array(
			'show_in_rest' => true,
			'annotations'  => array( 'readonly' => true, 'destructive' => false, 'idempotent' => true ),
			'mcp'          => array(
				'uri'         => 'wpagently://integrations/astra',
				'annotations' => array( 'audience' => array( 'assistant' ) ),
			),
		),
	);
}

/** @return array<string,mixed>|WP_Error */
function wpagent_exec_get_astra_design( $input = array() ) {
	$active  = wpagent_astra_is_active();
	$version = wpagent_astra_version();
	if ( ! $active ) {
		return array( 'active' => false, 'version' => $version, 'abilities_enabled' => false, 'operations' => array(), 'state_hash' => null );
	}

	$snapshot = wpagent_astra_snapshot();
	if ( is_wp_error( $snapshot ) ) {
		return $snapshot;
	}
	$enabled    = wpagent_astra_abilities_enabled();
	$operations = array();
	foreach ( wpagent_astra_available_operations() as $id => $definition ) {
		$current = wpagent_astra_provider_data( $definition['read'] );
		if ( is_wp_error( $current ) ) {
			return $current;
		}
		$operations[] = array(
			'id'           => $id,
			'label'        => $definition['label'],
			'input_schema' => wpagent_astra_bound_catalog_schema( $definition['input_schema'] ),
			'current'      => $current,
		);
	}
	return array(
		'active'            => true,
		'version'           => $version,
		'abilities_enabled' => $enabled,
		'operations'        => $operations,
		'state_hash'        => wpagent_astra_state_hash( $snapshot ),
	);
}
