<?php
/** Agententaugliche Systemdiagnose ohne Zugangsdaten oder Nutzerdaten. */

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

/** @return array<string,mixed> */
function wpagent_ability_get_system_diagnostics(): array {
	$check_schema = array(
		'type'       => 'object',
		'properties' => array(
			'name'   => array( 'type' => 'string' ),
			'ok'     => array( 'type' => 'boolean' ),
			'detail' => array( 'type' => 'string' ),
		),
		'required'   => array( 'name', 'ok', 'detail' ),
	);
	$connection_check_schema = array(
		'type'       => 'object',
		'properties' => array(
			'name'        => array( 'type' => 'string' ),
			'ok'          => array( 'type' => 'boolean' ),
			'status'      => array( 'type' => 'integer' ),
			'duration_ms' => array( 'type' => 'integer' ),
			'detail'      => array( 'type' => 'string' ),
		),
		'required'   => array( 'name', 'ok', 'status', 'duration_ms', 'detail' ),
	);
	$warning_schema = array(
		'type'       => 'object',
		'properties' => array(
			'code'   => array( 'type' => 'string' ),
			'detail' => array( 'type' => 'string' ),
		),
		'required'   => array( 'code', 'detail' ),
	);
	$hosting_hint_schema = array(
		'type'       => 'object',
		'properties' => array(
			'provider'   => array( 'type' => 'string', 'enum' => array( 'Cloudflare', 'Kinsta', 'WP Engine', 'Hostinger', 'SiteGround', 'Pantheon' ) ),
			'confidence' => array( 'type' => 'string', 'enum' => array( 'possible', 'observed', 'likely' ) ),
		),
		'required'   => array( 'provider', 'confidence' ),
	);
	$bot_protection_hint_schema = array(
		'type'       => 'object',
		'properties' => array(
			'kind'       => array( 'type' => 'string', 'enum' => array( 'cloudflare-challenge', 'public-endpoint-blocked', 'security-plugin-present' ) ),
			'confidence' => array( 'type' => 'string', 'enum' => array( 'possible', 'observed' ) ),
		),
		'required'   => array( 'kind', 'confidence' ),
	);
	$auth_recommendation_schema = array(
		'type'       => 'object',
		'properties' => array(
			'client'           => array( 'type' => 'string' ),
			'recommended_auth' => array( 'type' => 'string', 'enum' => array( 'oauth', 'application-password' ) ),
			'fallback_auth'    => array( 'type' => 'string', 'enum' => array( '', 'application-password' ) ),
			'auth_basis'       => array( 'type' => 'string', 'enum' => array( 'oauth-browser-flow', 'static-authorization-header' ) ),
			'environment'      => array( 'type' => 'string', 'enum' => array( 'ready', 'blocked', 'unknown' ) ),
			'reason'           => array( 'type' => 'string', 'enum' => array( 'oauth-supported', 'client-uses-static-auth-header', 'bot-protection-blocks-public-route', 'public-route-unavailable', 'external-diagnosis-not-run', 'external-diagnosis-incomplete' ) ),
		),
		'required'   => array( 'client', 'recommended_auth', 'fallback_auth', 'auth_basis', 'environment', 'reason' ),
	);

	return array(
		'label'               => __( 'Systemdiagnose lesen', 'wp-agent-companion' ),
		'description'         => __( 'Liefert einen redigierten Diagnosebericht für die Fehleranalyse. Zugangsdaten, Nutzer, Inhalte, vollständige URLs und Pluginpfade werden nie ausgegeben oder automatisch übertragen.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array( 'type' => 'object', 'properties' => array(), 'default' => array() ),
		'output_schema'       => array(
			'type'       => 'object',
			'properties' => array(
				'generated_at' => array( 'type' => 'string' ),
				'versions'     => array(
					'type'       => 'object',
					'properties' => array(
						'companion' => array( 'type' => 'string' ),
						'wordpress' => array( 'type' => 'string' ),
						'php'       => array( 'type' => 'string' ),
					),
					'required'   => array( 'companion', 'wordpress', 'php' ),
				),
				'environment'  => array(
					'type'       => 'object',
					'properties' => array(
						'type'      => array( 'type' => 'string' ),
						'multisite' => array( 'type' => 'boolean' ),
						'locale'    => array( 'type' => 'string' ),
					),
					'required'   => array( 'type', 'multisite', 'locale' ),
				),
				'database'     => array(
					'type'       => 'object',
					'properties' => array(
						'driver'  => array( 'type' => 'string', 'enum' => array( 'mysql', 'mariadb', 'sqlite', 'unknown' ) ),
						'version' => array( 'type' => 'string' ),
					),
					'required'   => array( 'driver', 'version' ),
				),
				'control'      => array(
					'type'       => 'object',
					'properties' => array(
						'gate_open'             => array( 'type' => 'boolean' ),
						'master_enabled'        => array( 'type' => 'boolean' ),
						'domain_match'          => array( 'type' => 'boolean' ),
						'profile'               => array( 'type' => 'string' ),
						'enabled_ability_count' => array( 'type' => 'integer' ),
						'endpoint_registered'   => array( 'type' => 'boolean' ),
						'checks'                 => array( 'type' => 'array', 'items' => $check_schema ),
					),
					'required'   => array( 'gate_open', 'master_enabled', 'domain_match', 'profile', 'enabled_ability_count', 'endpoint_registered', 'checks' ),
				),
				'connection_warnings'    => array( 'type' => 'array', 'items' => $warning_schema ),
				'hosting_hints'          => array( 'type' => 'array', 'items' => $hosting_hint_schema ),
				'bot_protection_hints'   => array( 'type' => 'array', 'items' => $bot_protection_hint_schema ),
				'auth_recommendations'   => array( 'type' => 'array', 'items' => $auth_recommendation_schema ),
				'connection_diagnostics' => array(
					'type'       => 'object',
					'properties' => array(
						'generated_at'     => array( 'type' => 'string' ),
						'checks'           => array( 'type' => 'array', 'items' => $connection_check_schema ),
						'intermediaries'   => array( 'type' => 'array', 'items' => array( 'type' => 'string' ) ),
						'security_plugins' => array( 'type' => 'array', 'items' => array( 'type' => 'string' ) ),
						'hosting_hints'    => array( 'type' => 'array', 'items' => $hosting_hint_schema ),
						'bot_protection_hints' => array( 'type' => 'array', 'items' => $bot_protection_hint_schema ),
						'auth_recommendations' => array( 'type' => 'array', 'items' => $auth_recommendation_schema ),
					),
					'required'   => array( 'generated_at', 'checks', 'intermediaries', 'security_plugins', 'hosting_hints', 'bot_protection_hints', 'auth_recommendations' ),
				),
				'privacy'      => array(
					'type'       => 'object',
					'properties' => array(
						'credentials_included'    => array( 'type' => 'boolean' ),
						'user_data_included'      => array( 'type' => 'boolean' ),
						'site_content_included'   => array( 'type' => 'boolean' ),
						'automatic_transmission'  => array( 'type' => 'boolean' ),
					),
					'required'   => array( 'credentials_included', 'user_data_included', 'site_content_included', 'automatic_transmission' ),
				),
			),
			'required'   => array( 'generated_at', 'versions', 'environment', 'database', 'control', 'connection_warnings', 'hosting_hints', 'bot_protection_hints', 'auth_recommendations', 'connection_diagnostics', 'privacy' ),
		),
		'execute_callback'    => 'wpagent_exec_get_system_diagnostics',
		'permission_callback' => 'wpagent_perm_edit_posts',
		'meta'                => array(
			'show_in_rest' => true,
			'annotations'  => array( 'readonly' => true, 'destructive' => false, 'idempotent' => true ),
			'mcp'          => array(
				'uri'         => 'wpagently://site/diagnostics',
				'annotations' => array( 'audience' => array( 'assistant' ) ),
			),
		),
	);
}

/** @return array{driver:string,version:string} */
function wpagent_companion_database_diagnostics(): array {
	global $wpdb;
	$class   = is_object( $wpdb ) ? strtolower( get_class( $wpdb ) ) : '';
	$version = '';
	if ( is_object( $wpdb ) && method_exists( $wpdb, 'db_server_info' ) ) {
		$version = (string) $wpdb->db_server_info();
	} elseif ( is_object( $wpdb ) && method_exists( $wpdb, 'db_version' ) ) {
		$version = (string) $wpdb->db_version();
	}
	$signature = strtolower( trim( $class . ' ' . $version ) );
	$driver    = str_contains( $signature, 'sqlite' )
		? 'sqlite'
		: ( str_contains( $signature, 'mariadb' ) ? 'mariadb' : ( '' !== $signature ? 'mysql' : 'unknown' ) );
	$version = preg_replace( '#(?:https?|ftp)://\S+#i', '', sanitize_text_field( $version ) );
	$version = is_string( $version ) ? preg_replace( '/[^A-Za-z0-9._+(): -]/', '', $version ) : '';

	return array(
		'driver'  => $driver,
		'version' => wp_html_excerpt( trim( (string) $version ), 80, '' ),
	);
}

/** @return int Ein begrenzter, nicht negativer Ganzzahlwert. */
function wpagent_companion_diagnostic_int( $value, int $maximum ): int {
	if ( ! is_int( $value ) && ! ( is_string( $value ) && ctype_digit( $value ) ) ) {
		return 0;
	}
	return min( $maximum, max( 0, (int) $value ) );
}

/**
 * Begrenzt die gespeicherte externe Diagnose erneut für die Agent-Ausgabe.
 * Die Option ist Administratorzustand und darf deshalb nicht ungeprüft an
 * einen Redakteur weitergereicht werden. Freitext wird aus den strukturierten
 * Statuswerten neu erzeugt, damit auch manipulierte oder alte Optionen keine
 * URLs, Pfade oder Geheimnisse offenlegen können.
 *
 * @param array<string,mixed> $stored Gespeicherte Verbindungsdiagnose.
 * @return array{generated_at:string,checks:array<int,array{name:string,ok:bool,status:int,duration_ms:int,detail:string}>,intermediaries:string[],security_plugins:string[],hosting_hints:array<int,array{provider:string,confidence:string}>,bot_protection_hints:array<int,array{kind:string,confidence:string}>,auth_recommendations:array<int,array{client:string,recommended_auth:string,fallback_auth:string,auth_basis:string,environment:string,reason:string}>}
 */
function wpagent_companion_redacted_connection_diagnostics( array $stored ): array {
	$allowed_names = array( 'rest-index', 'mcp-endpoint', 'oauth-metadata' );
	$checks        = array();
	$seen_names    = array();
	$stored_checks = is_array( $stored['checks'] ?? null ) ? array_slice( $stored['checks'], 0, 20 ) : array();
	foreach ( $stored_checks as $check ) {
		if ( ! is_array( $check ) ) {
			continue;
		}
		$name = sanitize_key( (string) ( $check['name'] ?? '' ) );
		if ( ! in_array( $name, $allowed_names, true ) || isset( $seen_names[ $name ] ) ) {
			continue;
		}
		$seen_names[ $name ] = true;
		$ok     = true === ( $check['ok'] ?? false );
		$status = wpagent_companion_diagnostic_int( $check['status'] ?? 0, 999 );
		$detail = $ok
			? __( 'Extern erreichbar und erwartungsgemäß beantwortet.', 'wp-agent-companion' )
			: ( $status > 0
				? sprintf( /* translators: %d: HTTP status code. */ __( 'Externer Aufruf liefert HTTP %d.', 'wp-agent-companion' ), $status )
				: __( 'Externer Aufruf ist fehlgeschlagen.', 'wp-agent-companion' ) );
		$checks[] = array(
			'name'        => $name,
			'ok'          => $ok,
			'status'      => $status,
			'duration_ms' => wpagent_companion_diagnostic_int( $check['duration_ms'] ?? 0, 600000 ),
			'detail'      => $detail,
		);
		if ( count( $seen_names ) === count( $allowed_names ) ) {
			break;
		}
	}

	$generated_at = sanitize_text_field( (string) ( $stored['generated_at'] ?? '' ) );
	if ( ! preg_match( '/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:Z|[+-]\d{2}:\d{2})$/', $generated_at ) ) {
		$generated_at = '';
	}
	$known_intermediaries = array( 'Cloudflare', 'Sucuri', 'LiteSpeed', __( 'Cache oder Proxy', 'wp-agent-companion' ) );
	$intermediaries       = array_values(
		array_intersect(
			$known_intermediaries,
			array_filter( (array) ( $stored['intermediaries'] ?? array() ), 'is_string' )
		)
	);
	$hosting_hints = function_exists( 'wpagent_companion_connection_normalize_hosting_hints' )
		? wpagent_companion_connection_normalize_hosting_hints( is_array( $stored['hosting_hints'] ?? null ) ? $stored['hosting_hints'] : array() )
		: array();
	$bot_protection_hints = function_exists( 'wpagent_companion_connection_normalize_bot_protection_hints' )
		? wpagent_companion_connection_normalize_bot_protection_hints( is_array( $stored['bot_protection_hints'] ?? null ) ? $stored['bot_protection_hints'] : array() )
		: array();
	$result = array(
		'generated_at'     => $generated_at,
		'checks'           => array_slice( $checks, 0, count( $allowed_names ) ),
		'intermediaries'   => $intermediaries,
		'security_plugins' => function_exists( 'wpagent_companion_active_security_plugins' ) ? wpagent_companion_active_security_plugins() : array(),
		'hosting_hints'    => $hosting_hints,
		'bot_protection_hints' => $bot_protection_hints,
	);
	$result['auth_recommendations'] = function_exists( 'wpagent_companion_connection_auth_recommendations' )
		? wpagent_companion_connection_auth_recommendations( $result )
		: array();
	return $result;
}

/** @return array<string,mixed> */
function wpagent_exec_get_system_diagnostics( $input = array() ): array {
	$routes = function_exists( 'rest_get_server' ) ? rest_get_server()->get_routes() : array();
	$latest = defined( 'WPAGENT_COMPANION_OPT_CONNECTION_DIAGNOSTICS' )
		? get_option( WPAGENT_COMPANION_OPT_CONNECTION_DIAGNOSTICS, array() )
		: array();
	$latest = wpagent_companion_redacted_connection_diagnostics( is_array( $latest ) ? $latest : array() );

	return array(
		'generated_at' => gmdate( 'c' ),
		'versions'     => array(
			'companion' => defined( 'WPAGENT_COMPANION_VERSION' ) ? WPAGENT_COMPANION_VERSION : '',
			'wordpress' => (string) get_bloginfo( 'version' ),
			'php'       => PHP_VERSION,
		),
		'environment'  => array(
			'type'      => wp_get_environment_type(),
			'multisite' => is_multisite(),
			'locale'    => get_locale(),
		),
		'database'     => wpagent_companion_database_diagnostics(),
		'control'      => array(
			'gate_open'             => wpagent_companion_gate_open(),
			'master_enabled'        => wpagent_companion_enabled(),
			'domain_match'          => wpagent_companion_domain_matches(),
			'profile'               => wpagent_companion_profile(),
			'enabled_ability_count' => count( wpagent_companion_enabled_ability_names() ),
			'endpoint_registered'   => isset( $routes['/wp-agent/mcp'] ),
			'checks'                 => wpagent_companion_diagnostics(),
		),
		'connection_warnings'    => function_exists( 'wpagent_companion_connection_warnings' ) ? wpagent_companion_connection_warnings() : array(),
		'hosting_hints'          => $latest['hosting_hints'],
		'bot_protection_hints'   => $latest['bot_protection_hints'],
		'auth_recommendations'   => $latest['auth_recommendations'],
		'connection_diagnostics' => $latest,
		'privacy'                => array(
			'credentials_included'   => false,
			'user_data_included'     => false,
			'site_content_included'  => false,
			'automatic_transmission' => false,
		),
	);
}
