<?php
/**
 * Ability: wp-agent/activate-plugin
 *
 * Aktiviert ein installiertes Plugin. activate_plugin() im WordPress-Kern
 * bindet die Plugin-Hauptdatei bei einer Aktivierung, die noch nicht aktiv
 * war, direkt per include_once ein und feuert die
 * activate_plugin/activate_{plugin}-Hooks; ein fehlerhaftes Plugin kann dabei
 * einen fatalen Fehler auslösen. Seit PHP 7 sind die meisten früheren
 * "Fatal error"-Fälle (Klasse nicht gefunden, Typfehler, Parse-Fehler bei
 * include) als Throwable katchbar, deshalb fängt diese Ability sie explizit
 * ab, statt den ganzen REST-Request mitzureißen. Echte, nicht abfangbare
 * PHP-Fatals (Speicherlimit, Timeout) bleiben ein WordPress-Kern-Grenzfall,
 * den keine Ability-Ebene lösen kann.
 *
 * Der von der wp-admin-UI genutzte Redirect-Trick (activate_plugin() setzt
 * bei einem nicht-leeren $redirect-Parameter VOR dem riskanten include per
 * wp_redirect() bereits einen Location-Header, damit der Browser bei einem
 * echten Fatal wenigstens auf eine Fehler-Anzeige-Seite umgeleitet wird) ist
 * für diesen JSON-REST-Kontext wirkungslos: es gibt hier keinen Browser, der
 * einem Location-Header folgt. Der Parameter bleibt deshalb bewusst leer;
 * der Throwable-Fang und die explizite WP_Error-Prüfung sind der eigentliche
 * Schutz.
 *
 * wp-agent-companion und wp-agent-power sind von dieser Ability
 * ausgeschlossen: das (De-)Aktivieren dieser beiden Plugins bleibt
 * ausschließlich manuellem Betreiber-Zugriff vorbehalten, damit sich der
 * Agent nicht selbst die eigene Grundlage entziehen oder umkonfigurieren
 * kann.
 *
 * @package WPAgentCompanion
 */

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

function wpagent_ability_activate_plugin(): array {
	return array(
		'label'               => __( 'Plugin aktivieren', 'wp-agent-companion' ),
		'description'         => __( 'Aktiviert ein installiertes Plugin und verifiziert per Re-Read (is_plugin_active), dass es aktiv ist. Fängt fatale Fehler aus einem fehlerhaften Plugin ab, statt den Request abstürzen zu lassen. wp-agent-companion und wp-agent-power sind ausgenommen.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array(
			'type'       => 'object',
			'properties' => array(
				'plugin_file' => array(
					'type'        => 'string',
					'description' => __( 'Relativer Plugin-Pfad wie von get_plugins() geliefert, z. B. "akismet/akismet.php".', 'wp-agent-companion' ),
				),
			),
			'required'   => array( 'plugin_file' ),
		),
		'output_schema'       => array(
			'type'       => 'object',
			'properties' => array(
				'plugin_file' => array( 'type' => 'string' ),
				'active'      => array( 'type' => 'boolean' ),
				'verified'    => array( 'type' => 'boolean' ),
			),
		),
		'execute_callback'    => 'wpagent_exec_activate_plugin',
		'permission_callback' => 'wpagent_perm_activate_plugins',
		'meta'                => array(
			'show_in_rest' => true,
			'annotations'  => array(
				'readonly'    => false,
				'destructive' => false,
				'idempotent'  => true,
			),
		),
	);
}

/**
 * @param mixed $input
 * @return array|WP_Error
 */
function wpagent_exec_activate_plugin( $input ) {
	$input       = is_array( $input ) ? $input : array();
	$plugin_file = (string) ( $input['plugin_file'] ?? '' );

	if ( '' === trim( $plugin_file ) ) {
		return new WP_Error( 'wpagent_missing_plugin', __( 'plugin_file fehlt.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}

	if ( ! function_exists( 'get_plugins' ) ) {
		require_once ABSPATH . 'wp-admin/includes/plugin.php';
	}

	$installed = get_plugins();
	if ( ! isset( $installed[ $plugin_file ] ) ) {
		return new WP_Error( 'wpagent_no_plugin', __( 'Plugin nicht gefunden.', 'wp-agent-companion' ), array( 'status' => 404 ) );
	}

	// Siehe Datei-Kommentar: wp-agent-companion und wp-agent-power verwalten
	// sich nicht über diese Ability selbst, in keine der beiden Richtungen.
	$protected = array( 'wp-agent-companion/wp-agent-companion.php', 'wp-agent-power/wp-agent-power.php' );
	if ( in_array( $plugin_file, $protected, true ) ) {
		return new WP_Error(
			'wpagent_protected_plugin',
			__( 'wp-agent-companion und wp-agent-power können über diese Ability nicht (de-)aktiviert werden.', 'wp-agent-companion' ),
			array( 'status' => 400 )
		);
	}

	try {
		$result = activate_plugin( $plugin_file );
	} catch ( \Throwable $e ) {
		return new WP_Error(
			'wpagent_activation_fatal',
			sprintf(
				/* translators: 1: Plugin-Pfad, 2: Fehlermeldung. */
				__( 'Aktivierung von "%1$s" hat einen fatalen Fehler ausgelöst: %2$s', 'wp-agent-companion' ),
				$plugin_file,
				$e->getMessage()
			),
			array( 'status' => 500 )
		);
	}

	if ( is_wp_error( $result ) ) {
		return new WP_Error(
			'wpagent_activation_failed',
			sprintf(
				/* translators: 1: Plugin-Pfad, 2: Fehlermeldung. */
				__( 'Aktivierung von "%1$s" fehlgeschlagen: %2$s', 'wp-agent-companion' ),
				$plugin_file,
				$result->get_error_message()
			),
			array( 'status' => 500 )
		);
	}

	$active = is_plugin_active( $plugin_file );

	return array(
		'plugin_file' => $plugin_file,
		'active'      => $active,
		'verified'    => $active,
	);
}
