<?php
/**
 * Ability: wp-agent/delete-user
 *
 * Löscht einen Nutzer endgültig über wp_delete_user(). Anders als bei
 * Beiträgen kennt WordPress für Nutzer keinen Papierkorb: das ist der
 * zentrale Fallstrick dieser Ability. wp_delete_user( $id, $reassign )
 * löscht bei $reassign === null ALLE Inhalte des Nutzers (Beiträge,
 * Links) unwiderruflich mit. Diese Ability erzwingt deshalb eine explizite
 * Entscheidung: entweder reassign_to (Inhalte werden auf diesen Nutzer
 * umgehängt) oder das Flag delete_content=true (Inhalte werden bewusst
 * mitgelöscht). Fehlen beide, bricht die Ability mit 400 ab, statt WordPress'
 * eigenem Stillschweigen (Datenverlust ohne Rückfrage) zu folgen.
 *
 * wp_delete_user() lebt in wp-admin/includes/user.php und ist außerhalb des
 * wp-admin-Kontexts (also in jedem normalen REST-Request) nicht automatisch
 * geladen; die Datei wird deshalb bei Bedarf explizit nachgeladen, analog zu
 * is_plugin_active() in disable-power.php.
 *
 * Zwei harte, nicht per Flag umgehbare Schutzmechanismen: User-ID 1 wird nie
 * gelöscht, und der aufrufende Account (get_current_user_id()) darf sich
 * nie selbst löschen. Da die Abilities API immer im Kontext des per
 * Application Password authentifizierten Nutzers läuft, IST dieser Nutzer
 * im produktiven Einsatz der Companion-Bot; die Selbst-Sperre deckt also
 * genau den geforderten "Companion-Bot darf sich nicht selbst löschen"-Fall
 * ab, ohne einen fest einprogrammierten Benutzernamen vorauszusetzen.
 *
 * @package WPAgentCompanion
 */

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

function wpagent_ability_delete_user(): array {
	return array(
		'label'               => __( 'Nutzer löschen', 'wp-agent-companion' ),
		'description'         => __( 'Löscht einen Nutzer endgültig (WordPress kennt für Nutzer keinen Papierkorb). Erfordert entweder reassign_to (Inhalte werden übernommen) oder delete_content=true (Inhalte werden bewusst mitgelöscht), sonst 400. User-ID 1 und der aufrufende Account selbst dürfen nie gelöscht werden. Re-Read-verifiziert.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array(
			'type'       => 'object',
			'properties' => array(
				'user_id'        => array( 'type' => 'integer' ),
				'reassign_to'    => array(
					'type'        => 'integer',
					'description' => __( 'Ziel-Nutzer-ID, auf die die Inhalte des gelöschten Nutzers umgehängt werden.', 'wp-agent-companion' ),
				),
				'delete_content' => array(
					'type'        => 'boolean',
					'default'     => false,
					'description' => __( 'Muss true sein, wenn statt reassign_to bewusst auch die Inhalte des Nutzers gelöscht werden sollen.', 'wp-agent-companion' ),
				),
			),
			'required'   => array( 'user_id' ),
		),
		'output_schema'       => array(
			'type'       => 'object',
			'properties' => array(
				'user_id'         => array( 'type' => 'integer' ),
				'reassigned_to'   => array(
					'type'        => 'integer',
					'description' => __( '0, wenn nicht umgehängt (delete_content=true) wurde.', 'wp-agent-companion' ),
				),
				'content_deleted' => array( 'type' => 'boolean' ),
				'deleted'         => array( 'type' => 'boolean' ),
				'verified'        => array( 'type' => 'boolean' ),
			),
		),
		'execute_callback'    => 'wpagent_exec_delete_user',
		'permission_callback' => 'wpagent_perm_delete_users',
		'meta'                => array(
			'show_in_rest' => true,
			'annotations'  => array(
				'readonly'    => false,
				// Endgültig und unumkehrbar, analog zu wp-agent/delete-post mit
				// force=true: der einzige echte Datenverlust-Fall dieser Gruppe.
				'destructive' => true,
				'idempotent'  => true,
			),
		),
	);
}

/**
 * Permission callback: der Aufrufer muss delete_users besitzen. Diese
 * Capability ist in einer Standardinstallation Administratoren vorbehalten;
 * der als Editor eingerichtete Companion-Bot besitzt sie nie.
 *
 * @param mixed $input Unused ability input.
 * @return bool
 */
function wpagent_perm_delete_users( $input = null ): bool {
	return current_user_can( 'delete_users' );
}

/**
 * @param mixed $input
 * @return array|WP_Error
 */
function wpagent_exec_delete_user( $input ) {
	$input   = is_array( $input ) ? $input : array();
	$user_id = (int) ( $input['user_id'] ?? 0 );
	$user    = get_userdata( $user_id );

	if ( ! $user ) {
		return new WP_Error( 'wpagent_no_user', __( 'Nutzer nicht gefunden.', 'wp-agent-companion' ), array( 'status' => 404 ) );
	}
	if ( ! current_user_can( 'delete_users' ) ) {
		return new WP_Error( 'wpagent_forbidden', __( 'Keine Berechtigung.', 'wp-agent-companion' ), array( 'status' => 403 ) );
	}

	if ( 1 === $user_id ) {
		return new WP_Error(
			'wpagent_protected_user',
			__( 'User-ID 1 ist geschützt und darf nicht gelöscht werden.', 'wp-agent-companion' ),
			array( 'status' => 400 )
		);
	}
	if ( get_current_user_id() === $user_id ) {
		return new WP_Error(
			'wpagent_protected_user',
			__( 'Der aufrufende Account darf sich nicht selbst löschen.', 'wp-agent-companion' ),
			array( 'status' => 400 )
		);
	}

	$reassign_to = null;
	if ( isset( $input['reassign_to'] ) && '' !== $input['reassign_to'] ) {
		$reassign_to = (int) $input['reassign_to'];
		if ( $reassign_to === $user_id ) {
			return new WP_Error(
				'wpagent_bad_reassign',
				__( 'reassign_to darf nicht der zu löschende Nutzer selbst sein.', 'wp-agent-companion' ),
				array( 'status' => 400 )
			);
		}
		if ( ! get_userdata( $reassign_to ) ) {
			return new WP_Error(
				'wpagent_bad_reassign',
				__( 'reassign_to-Nutzer nicht gefunden.', 'wp-agent-companion' ),
				array( 'status' => 400 )
			);
		}
	}

	$delete_content = rest_sanitize_boolean( $input['delete_content'] ?? false ); // DELETE liefert Booleans als Query-String; !empty("false") wäre fälschlich true.
	if ( null === $reassign_to && ! $delete_content ) {
		return new WP_Error(
			'wpagent_reassign_required',
			__( 'Entweder reassign_to angeben (Inhalte werden übernommen) oder delete_content=true explizit setzen (Inhalte werden mitgelöscht).', 'wp-agent-companion' ),
			array( 'status' => 400 )
		);
	}

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

	$res = wp_delete_user( $user_id, $reassign_to );
	if ( ! $res ) {
		return new WP_Error( 'wpagent_delete_user_failed', __( 'Löschen fehlgeschlagen.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}

	$still_exists = (bool) get_userdata( $user_id );

	return array(
		'user_id'         => $user_id,
		'reassigned_to'   => null === $reassign_to ? 0 : $reassign_to,
		'content_deleted' => null === $reassign_to,
		'deleted'         => ! $still_exists,
		'verified'        => ! $still_exists,
	);
}
