<?php
/**
 * Ability: wp-agent/create-menu
 *
 * Legt ein neues WordPress-Navigationsmenü an. Ein nav_menu ist technisch eine
 * Taxonomie (Terms in der Taxonomie 'nav_menu'), deshalb landet das Ergebnis von
 * wp_create_nav_menu() als term_id in menu_id. WordPress selbst verhindert über
 * wp_update_nav_menu_object() bereits doppelte Menünamen (Fehlercode
 * 'menu_exists'); dieser Fall wird hier als 400 gemeldet, nicht als 500.
 *
 * @package WPAgentCompanion
 */

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

/**
 * Permission callback: der Aufrufer muss Theme-Optionen bearbeiten dürfen.
 *
 * Gemeinsame Capability für die gesamte Phase-E-Menü-Ability-Gruppe (create-menu,
 * add-menu-item, list-menus, assign-menu-location, delete-menu). Sie lebt bewusst
 * HIER und nicht in includes/helpers.php, weil helpers.php eine geteilte Datei
 * ist, die in dieser Phase nicht angefasst werden darf (das übernimmt die
 * Integrationsphase). Die Funktion wird nur einmal definiert; die anderen vier
 * Menü-Ability-Dateien referenzieren sie per String, ohne sie erneut zu
 * deklarieren. Voraussetzung: create-menu.php muss zusammen mit den anderen vier
 * Dateien geladen werden (oder die Funktion wird bei der Integration nach
 * helpers.php verschoben).
 *
 * Wichtig für den Bot-Betrieb: edit_theme_options ist in WordPress' Kern-Rollen
 * ausschließlich der Administrator-Rolle zugewiesen, der Editor-Rolle NICHT
 * (siehe wp-admin/includes/schema.php, populate_roles_300()). Der sonst überall
 * geltende Grundsatz "Bot-User ist Editor, nie Admin" gilt für die Menü-Gruppe
 * also nicht: Menüverwaltung ist in WordPress selbst Admin-Territorium (genau wie
 * write-theme-file, das ebenfalls eine Theme-Capability voraussetzt). Ein
 * Editor-Bot bekommt hier von JEDER Ability dieser Gruppe ein 403.
 *
 * @param mixed $input Unused ability input.
 * @return bool
 */
function wpagent_perm_edit_theme_options( $input = null ): bool {
	return current_user_can( 'edit_theme_options' );
}

function wpagent_ability_create_menu(): array {
	return array(
		'label'               => __( 'Menü erstellen', 'wp-agent-companion' ),
		'description'         => __( 'Legt ein neues Navigationsmenü mit dem angegebenen Namen an. Der Schreibvorgang besitzt eine kurzlebige Intent-Sperre, prüft den exakt frisch angelegten Menüzustand und kompensiert nur diesen unveränderten eigenen Kandidaten.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array(
			'type'       => 'object',
			'properties' => array(
				'name' => array(
					'type'        => 'string',
					'minLength'   => 1,
					'maxLength'   => 150,
					'description' => __( 'Name des neuen Menüs. Muss innerhalb der Site eindeutig sein.', 'wp-agent-companion' ),
				),
			),
			'required'              => array( 'name' ),
			'additionalProperties'  => false,
		),
		'output_schema'       => array(
			'type'       => 'object',
			'properties' => array(
				'menu_id'  => array( 'type' => 'integer' ),
				'name'     => array( 'type' => 'string' ),
				'verified' => array( 'type' => 'boolean' ),
			),
			'required'              => array( 'menu_id', 'name', 'verified' ),
			'additionalProperties'  => false,
		),
		'execute_callback'    => 'wpagent_exec_create_menu',
		'permission_callback' => 'wpagent_perm_edit_theme_options',
		'meta'                => array(
			'show_in_rest' => true,
			'annotations'  => array(
				'readonly'    => false,
				'destructive' => false,
				// Namenskonflikte werden serverseitig kontrolliert abgewiesen.
				// Das ersetzt jedoch keinen verifizierten Replay-Vertrag.
				// Nach einem unklaren Ergebnis kann eine Neuanlage bestehen.
				// Ihr Zustand muss vor einer Wiederholung geprüft werden.
				// Deshalb sind automatische Wiederholungen nicht freigegeben.
				'idempotent'  => false,
			),
		),
	);
}

/** @return WP_Error */
function wpagent_menu_create_recovery_required( int $menu_id = 0 ): WP_Error {
	$data = array( 'status' => 409, 'recovery_required' => true, 'rollback_verified' => false );
	if ( $menu_id > 0 ) {
		$data['menu_id'] = $menu_id;
	}
	return new WP_Error( 'wpagent_menu_create_recovery_required', __( 'Das neue Menü konnte nicht vollständig eigentumsgeprüft verifiziert oder entfernt werden. Wiederhole den Vorgang nicht automatisch und prüfe den aktuellen Zustand manuell.', 'wp-agent-companion' ), $data );
}

/** @return WP_Error */
function wpagent_menu_create_unverified(): WP_Error {
	return new WP_Error( 'wpagent_menu_create_unverified', __( 'Das neue Menü wich nach dem Speichern vom erwarteten Zustand ab und wurde wieder entfernt.', 'wp-agent-companion' ), array( 'status' => 500, 'rollback_verified' => true, 'recovery_required' => false ) );
}

/**
 * @param mixed $input
 * @return array|WP_Error
 */
function wpagent_exec_create_menu( $input ) {
	$input = is_array( $input ) ? $input : array();
	$name  = wpagent_core_mutator_bounded_text( $input['name'] ?? null, 150 );
	if ( is_wp_error( $name ) ) {
		return new WP_Error( 'wpagent_missing_name', __( 'name fehlt oder ist ungültig.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$name = trim( $name );
	if ( '' === $name ) {
		return new WP_Error( 'wpagent_missing_name', __( 'name fehlt.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$lock_identity = hash( 'sha256', "create-menu\0" . $name );
	$lock          = wpagent_core_mutator_acquire_lock( 'menu-create', $lock_identity );
	if ( is_wp_error( $lock ) ) {
		return $lock;
	}

	try {
		if ( ! current_user_can( 'edit_theme_options' ) ) {
			return new WP_Error( 'wpagent_forbidden', __( 'Keine Berechtigung.', 'wp-agent-companion' ), array( 'status' => 403 ) );
		}
		if ( ! wpagent_core_mutator_refresh_lock( 'menu-create', $lock_identity, $lock ) || ! wpagent_core_mutator_lock_is_owned( 'menu-create', $lock_identity, $lock ) || ! current_user_can( 'edit_theme_options' ) ) {
			return new WP_Error( 'wpagent_menu_create_locked', __( 'Die Erstellungs-Sperre oder Berechtigung ging vor dem Anlegen verloren.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$result = wp_create_nav_menu( $name );
		if ( is_wp_error( $result ) ) {
			// wp_create_nav_menu() liefert bei Namenskonflikten den Fehlercode
			// 'menu_exists' OHNE eigene 'status'-Angabe; ohne dieses Re-Wrapping
			// würde die Abilities-API mangels 'status' auf 500 zurückfallen, obwohl
			// es sich um einen klaren Eingabefehler handelt.
			return new WP_Error( 'wpagent_menu_create_failed', $result->get_error_message(), array( 'status' => 400 ) );
		}
		$menu_id   = (int) $result;
		$candidate = $menu_id > 0 ? wpagent_core_mutator_created_menu_candidate( $menu_id ) : null;
		$menu      = $menu_id > 0 ? wp_get_nav_menu_object( $menu_id ) : null;
		$verified  = $candidate && $menu instanceof WP_Term && $name === $menu->name
			&& wpagent_core_mutator_refresh_lock( 'menu-create', $lock_identity, $lock )
			&& wpagent_core_mutator_lock_is_owned( 'menu-create', $lock_identity, $lock )
			&& current_user_can( 'edit_theme_options' );
		if ( ! $verified ) {
			if ( wpagent_core_mutator_delete_created_menu_if_current( $candidate ) ) {
				return wpagent_menu_create_unverified();
			}
			return wpagent_menu_create_recovery_required( $menu_id );
		}
		return array(
			'menu_id'  => $menu_id,
			'name'     => $menu->name,
			'verified' => true,
		);
	} finally {
		wpagent_core_mutator_release_lock( 'menu-create', $lock_identity, $lock );
	}
}
