<?php
/**
 * Ability: wp-agent/refresh-hooks
 *
 * Feuert die Admin-/Save-only-Nacharbeiten für AT-4 (Hook-Gap): Wenn Inhalte
 * über die REST-/Abilities-Schicht statt über den Editor geschrieben werden,
 * bleiben einige der Nacharbeiten aus, die WordPress sonst beim Speichern im
 * Admin auslöst. Diese Ability holt sie explizit nach:
 *
 * 1. Optional flush_rewrite_rules(false), nur bei ausdrücklichem
 *    rebuild_rewrite_rules=true
 * 2. clean_post_cache für die zuletzt geänderten Posts
 * 3. Falls Rank Math aktiv ist: Sitemap-Cache invalidieren
 *
 * @package WPAgentCompanion
 */

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

function wpagent_ability_refresh_hooks(): array {
	return array(
		'label'               => __( 'Save-Nacharbeiten nachholen (Hook-Gap AT-4)', 'wp-agent-companion' ),
		'description'         => __( 'Holt Save-Nacharbeiten nach: Post-Cache leeren, Rank-Math-Sitemap-Cache invalidieren und optional Rewrite-Regeln ausdrücklich neu aufbauen.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array(
			'type'       => 'object',
			'properties' => array(
				'limit'    => array(
					'type'        => 'integer',
					'description' => __( 'Anzahl der zuletzt geänderten Posts, deren Cache geleert wird (1-100, Default 20).', 'wp-agent-companion' ),
					'default'     => 20,
				),
				'post_ids' => array(
					'type'        => 'array',
					'description' => __( 'Optionale explizite Post-IDs; wenn gesetzt, wird statt der zuletzt geänderten Posts genau diese Liste geleert.', 'wp-agent-companion' ),
					'items'       => array( 'type' => 'integer' ),
				),
				'rebuild_rewrite_rules' => array(
					'type'        => 'boolean',
					'description' => __( 'Rewrite-Regeln ausdrücklich neu aufbauen. Für normale Beitrags-Saves nicht erforderlich und deshalb standardmäßig aus.', 'wp-agent-companion' ),
					'default'     => false,
				),
			),
		),
		'output_schema'       => array(
			'type'       => 'object',
			'properties' => array(
				'actions'          => array(
					'type'  => 'array',
					'items' => array( 'type' => 'string' ),
				),
				'cleaned_post_ids' => array(
					'type'  => 'array',
					'items' => array( 'type' => 'integer' ),
				),
				'rankmath'         => array( 'type' => 'object' ),
			),
		),
		'execute_callback'    => 'wpagent_exec_refresh_hooks',
		'permission_callback' => 'wpagent_perm_edit_posts',
		'meta'                => array(
			'show_in_rest' => true,
			'annotations'  => array(
				'readonly'    => false,
				'destructive' => false,
				'idempotent'  => true,
			),
		),
	);
}

/**
 * @param mixed $input
 * @return array
 */
function wpagent_exec_refresh_hooks( $input ) {
	$input   = is_array( $input ) ? $input : array();
	$actions = array();

	// Rewrite-Regeln sind global und ändern sich bei normalen Beitrags-Saves
	// nicht. Der teure Rebuild läuft deshalb nur bei ausdrücklicher Anforderung.
	if ( ! empty( $input['rebuild_rewrite_rules'] ) ) {
		flush_rewrite_rules( false );
		$actions[] = 'flush_rewrite_rules(false)';
	}

	// 2. Post-Cache leeren: entweder die explizit übergebenen IDs oder die
	//    zuletzt geänderten Posts.
	$post_ids = array();
	if ( isset( $input['post_ids'] ) && is_array( $input['post_ids'] ) ) {
		foreach ( $input['post_ids'] as $pid ) {
			$pid = (int) $pid;
			if ( $pid > 0 ) {
				$post_ids[] = $pid;
			}
		}
	}

	if ( array() === $post_ids ) {
		$limit    = isset( $input['limit'] ) ? (int) $input['limit'] : 20;
		$limit    = max( 1, min( 100, $limit ) );
		$post_ids = get_posts(
			array(
				'post_type'        => 'any',
				'post_status'      => 'any',
				'orderby'          => 'modified',
				'order'            => 'DESC',
				'numberposts'      => $limit,
				'fields'           => 'ids',
				'suppress_filters' => true,
			)
		);
		$post_ids = array_map( 'intval', $post_ids );
	}

	foreach ( $post_ids as $pid ) {
		clean_post_cache( $pid );
	}
	$actions[] = 'clean_post_cache x' . count( $post_ids );

	// 3. Rank-Math-Sitemap-Cache invalidieren, falls Rank Math aktiv ist.
	$rankmath = wpagent_refresh_rankmath_sitemap( $actions );

	return array(
		'actions'          => $actions,
		'cleaned_post_ids' => $post_ids,
		'rankmath'         => $rankmath,
	);
}

/**
 * Invalidiert den Rank-Math-Sitemap-Cache, sofern Rank Math aktiv ist.
 *
 * Bevorzugt die statische Methode RankMath\Sitemap\Cache::invalidate_storage(),
 * fällt sonst auf RankMath\Sitemap\Cache_Watcher::clear() zurück. Wenn keine
 * der Methoden vorhanden ist, bleibt der dokumentierte WP-CLI-Fallback
 * `wp rankmath sitemap generate`.
 *
 * @param array $actions Referenz auf die Aktionsliste (wird ergänzt).
 * @return array{active:bool,method:?string,cli_fallback:string}
 */
function wpagent_refresh_rankmath_sitemap( array &$actions ): array {
	$active = ( defined( 'RANK_MATH_VERSION' ) || function_exists( 'rank_math' ) || class_exists( 'RankMath\\Helper' ) );
	$result = array(
		'active'       => $active,
		'method'       => null,
		'cli_fallback' => 'wp rankmath sitemap generate',
	);

	if ( ! $active ) {
		return $result;
	}

	if ( is_callable( array( 'RankMath\\Sitemap\\Cache', 'invalidate_storage' ) ) ) {
		call_user_func( array( 'RankMath\\Sitemap\\Cache', 'invalidate_storage' ) );
		$result['method'] = 'RankMath\\Sitemap\\Cache::invalidate_storage()';
	} elseif ( is_callable( array( 'RankMath\\Sitemap\\Cache_Watcher', 'clear' ) ) ) {
		call_user_func( array( 'RankMath\\Sitemap\\Cache_Watcher', 'clear' ) );
		$result['method'] = 'RankMath\\Sitemap\\Cache_Watcher::clear()';
	}

	$actions[] = null !== $result['method']
		? 'rankmath_sitemap: ' . $result['method']
		: 'rankmath_sitemap: keine Cache-Methode gefunden, WP-CLI-Fallback `wp rankmath sitemap generate`';

	return $result;
}
