<?php
/**
 * Ability: wp-agent/deactivate-plugin
 *
 * Deaktiviert ein installiertes Plugin über deactivate_plugins(). Die
 * Kernfunktion ist von sich aus idempotent (ein bereits inaktives Plugin wird
 * pro Schleifendurchlauf einfach übersprungen) und feuert die
 * deactivate_plugin/deactivate_{plugin}-Hooks nur für tatsächlich aktive
 * Plugins; ein fehlerhafter Deaktivierungs-Hook eines Fremd-Plugins wird
 * trotzdem per Throwable-Fang abgefangen (siehe activate-plugin.php für die
 * ausführliche Begründung, warum das kein vollständiger Fatal-Schutz sein
 * kann und wo die Grenze liegt).
 *
 * HARTER Schutz: wp-agent-companion und wp-agent-power können über diese
 * Ability NIEMALS deaktiviert werden. Ein Deaktivieren von wp-agent-companion
 * würde die eigene Ability-Registrierung (inklusive dieser Ability selbst)
 * beim nächsten Request entfernen; ein Deaktivieren von wp-agent-power
 * gehört ausschließlich zum dedizierten Panik-Schalter
 * wp-agent/disable-power, der bewusst unabhängig von dieser generischen
 * Ability existiert. Der Schutz greift unabhängig vom aktuellen
 * Aktiv-Status der beiden Plugins.
 *
 * @package WPAgentCompanion
 */

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

function wpagent_ability_deactivate_plugin(): array {
	return array(
		'label'               => __( 'Plugin deaktivieren', 'wp-agent-companion' ),
		'description'         => __( 'Deaktiviert ein installiertes Plugin und verifiziert per Re-Read (is_plugin_active), dass es inaktiv ist. wp-agent-companion und wp-agent-power sind hart ausgenommen (Selbstschutz).', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array(
			'type'                 => 'object',
			'properties'           => array(
				'plugin_file' => array(
					'type'        => 'string',
					'maxLength'   => 255,
					'description' => __( 'Relativer Plugin-Pfad wie von get_plugins() geliefert, z. B. "akismet/akismet.php".', 'wp-agent-companion' ),
				),
				'expected_active'  => array( 'type' => 'boolean' ),
				'expected_version' => array( 'type' => 'string', 'maxLength' => 255 ),
			),
			'required'             => array( 'plugin_file', 'expected_active', 'expected_version' ),
			'additionalProperties' => false,
		),
		'output_schema'       => array(
			'type'       => 'object',
			'properties' => array(
				'plugin_file' => array( 'type' => 'string' ),
				'active'      => array( 'type' => 'boolean' ),
				'version'     => array( 'type' => 'string' ),
				'verified'    => array( 'type' => 'boolean' ),
			),
			'required'             => array( 'plugin_file', 'active', 'version', 'verified' ),
			'additionalProperties' => false,
		),
		'execute_callback'    => 'wpagent_exec_deactivate_plugin',
		'permission_callback' => 'wpagent_perm_activate_plugins',
		'meta'                => array(
			'show_in_rest' => true,
			'annotations'  => array(
				'readonly'    => false,
				// Wie wp-agent/disable-power: eine Deaktivierung ist folgenreich,
				// aber kein Datenverlust und jederzeit über wp-agent/activate-plugin
				// umkehrbar. Deshalb destructive:false, analog zum bestehenden
				// Companion-Präzedenzfall.
				'destructive' => false,
				'idempotent'  => false,
			),
		),
	);
}

/**
 * @param mixed $input
 * @return array|WP_Error
 */
function wpagent_exec_deactivate_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 ( ! is_array( wpagent_plugin_mutator_state( $plugin_file ) ) ) {
		return new WP_Error( 'wpagent_no_plugin', __( 'Plugin nicht gefunden.', 'wp-agent-companion' ), array( 'status' => 404 ) );
	}

	// Siehe Datei-Kommentar: harter, unbedingter Selbstschutz.
	$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 deaktiviert werden. Für den Power-Modus gezielt wp-agent/disable-power verwenden.', 'wp-agent-companion' ),
			array( 'status' => 400 )
		);
	}

	$lock = wpagent_core_mutator_acquire_lock( 'plugin', $plugin_file );
	if ( is_wp_error( $lock ) ) {
		return $lock;
	}
	try {
		$current = wpagent_plugin_mutator_state( $plugin_file );
		if ( ! is_array( $current ) ) {
			return new WP_Error( 'wpagent_no_plugin', __( 'Plugin wurde während der Sperrübernahme entfernt.', 'wp-agent-companion' ), array( 'status' => 404 ) );
		}
		if ( ! current_user_can( 'activate_plugins' ) ) {
			return new WP_Error( 'wpagent_forbidden', __( 'Die Berechtigung änderte sich während der Sperrübernahme.', 'wp-agent-companion' ), array( 'status' => 403 ) );
		}
		if ( ! wpagent_plugin_mutator_matches_expected( $input, $current ) ) {
			return new WP_Error( 'wpagent_plugin_conflict', __( 'Das Plugin wurde seit dem Lesen verändert. Lies die Plugin-Liste neu.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		if ( ! $current['active'] ) {
			if ( ! wpagent_core_mutator_lock_is_owned( 'plugin', $plugin_file, $lock ) ) {
				return wpagent_plugin_mutator_recovery_required( 'deactivation', $plugin_file, $current );
			}
			return array( 'plugin_file' => $plugin_file, 'active' => false, 'version' => $current['version'], 'verified' => true );
		}
		if ( ! wpagent_core_mutator_refresh_lock( 'plugin', $plugin_file, $lock ) ) {
			return new WP_Error( 'wpagent_plugin_busy', __( 'Die Plugin-Sperre ging vor der Deaktivierung verloren.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		if ( ! current_user_can( 'activate_plugins' ) ) {
			return new WP_Error( 'wpagent_forbidden', __( 'Die Berechtigung ging unmittelbar vor der Deaktivierung verloren.', 'wp-agent-companion' ), array( 'status' => 403 ) );
		}
		try {
			deactivate_plugins( $plugin_file );
		} catch ( \Throwable ) {
			return wpagent_plugin_mutator_recovery_required( 'deactivation', $plugin_file, wpagent_plugin_mutator_state( $plugin_file ) );
		}
		$fresh = wpagent_plugin_mutator_state( $plugin_file );
		if ( ! is_array( $fresh ) || $fresh['active'] || ! hash_equals( $current['version'], $fresh['version'] ) || ! wpagent_core_mutator_lock_is_owned( 'plugin', $plugin_file, $lock ) ) {
			return wpagent_plugin_mutator_recovery_required( 'deactivation', $plugin_file, $fresh );
		}
		return array( 'plugin_file' => $plugin_file, 'active' => false, 'version' => $fresh['version'], 'verified' => true );
	} finally {
		wpagent_core_mutator_release_lock( 'plugin', $plugin_file, $lock );
	}
}
