<?php

namespace AtlasAiDev\Awfah\Abilities;

use WP_Error;
use WP_REST_Request;

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

/**
 * Registers WordPress post, category, and tag CRUD abilities
 * using the Abilities API.
 *
 * Mirrors the functionality previously provided by the wordpress-mcp
 * plugin's McpPostsTools via the Feature API / REST-alias pattern.
 *
 * @package AtlasAiDev\Awfah\Abilities
 */
class Posts_Abilities {

	/**
	 * REST route definitions for each ability.
	 *
	 * @var array<string, array{route: string, method: string}>
	 */
	private static array $rest_routes = [
		'awfah-posts/wp-posts-search'   => [ 'route' => '/wp/v2/posts',            'method' => 'GET' ],
		'awfah-posts/wp-get-post'       => [ 'route' => '/wp/v2/posts/%d',         'method' => 'GET' ],
		'awfah-posts/wp-add-post'       => [ 'route' => '/wp/v2/posts',            'method' => 'POST' ],
		'awfah-posts/wp-update-post'    => [ 'route' => '/wp/v2/posts/%d',         'method' => 'POST' ], // WP REST uses POST for updates too.
		'awfah-posts/wp-delete-post'    => [ 'route' => '/wp/v2/posts/%d',         'method' => 'DELETE' ],
		'awfah-posts/wp-list-categories' => [ 'route' => '/wp/v2/categories',      'method' => 'GET' ],
		'awfah-posts/wp-add-category'   => [ 'route' => '/wp/v2/categories',       'method' => 'POST' ],
		'awfah-posts/wp-update-category' => [ 'route' => '/wp/v2/categories/%d',   'method' => 'POST' ],
		'awfah-posts/wp-delete-category' => [ 'route' => '/wp/v2/categories/%d',   'method' => 'DELETE' ],
		'awfah-posts/wp-list-tags'      => [ 'route' => '/wp/v2/tags',             'method' => 'GET' ],
		'awfah-posts/wp-add-tag'        => [ 'route' => '/wp/v2/tags',             'method' => 'POST' ],
		'awfah-posts/wp-update-tag'     => [ 'route' => '/wp/v2/tags/%d',          'method' => 'POST' ],
		'awfah-posts/wp-delete-tag'     => [ 'route' => '/wp/v2/tags/%d',          'method' => 'DELETE' ],
	];

	/**
	 * Return the full list of ability definitions.
	 *
	 * @return array[]
	 */
	public static function get_abilities(): array {
		return [
			// ── Posts ────────────────────────────────────────────────
			[
				'id'          => 'awfah-posts/wp-posts-search',
				'module'      => 'content_steward',
				'label'       => __( 'Search Posts', 'ai-workflow-automation-ai-agent-hub' ),
				'description' => __( 'Search and filter WordPress posts with pagination.', 'ai-workflow-automation-ai-agent-hub' ),
				'category'    => 'awfah-posts',
				'input_schema' => [
					'type'       => 'object',
					'properties' => [
						'search'   => [
							'type'        => 'string',
							'description' => __( 'Limit results to those matching a string.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'page'     => [
							'type'        => 'integer',
							'description' => __( 'Current page of the collection.', 'ai-workflow-automation-ai-agent-hub' ),
							'default'     => 1,
							'minimum'     => 1,
						],
						'per_page' => [
							'type'        => 'integer',
							'description' => __( 'Maximum number of items to be returned in result set.', 'ai-workflow-automation-ai-agent-hub' ),
							'default'     => 10,
							'minimum'     => 1,
							'maximum'     => 100,
						],
						'status'   => [
							'type'        => 'string',
							'description' => __( 'Limit result set to posts assigned one or more statuses.', 'ai-workflow-automation-ai-agent-hub' ),
							'default'     => 'publish',
						],
						'categories' => [
							'type'        => 'array',
							'description' => __( 'Limit result set to items with specific terms assigned in the categories taxonomy.', 'ai-workflow-automation-ai-agent-hub' ),
							'items'       => [ 'type' => 'integer' ],
						],
						'tags'     => [
							'type'        => 'array',
							'description' => __( 'Limit result set to items with specific terms assigned in the tags taxonomy.', 'ai-workflow-automation-ai-agent-hub' ),
							'items'       => [ 'type' => 'integer' ],
						],
						'orderby'  => [
							'type'        => 'string',
							'description' => __( 'Sort collection by post attribute.', 'ai-workflow-automation-ai-agent-hub' ),
							'enum'        => [ 'date', 'relevance', 'id', 'include', 'title', 'slug', 'modified' ],
							'default'     => 'date',
						],
						'order'    => [
							'type'        => 'string',
							'description' => __( 'Order sort attribute ascending or descending.', 'ai-workflow-automation-ai-agent-hub' ),
							'enum'        => [ 'asc', 'desc' ],
							'default'     => 'desc',
						],
					],
				],
				'meta'        => [
					'show_in_rest' => true,
					'mcp'          => [ 'public' => true ],
					'uri'          => 'wordpress://ai-agent-hub/posts',
					'mimeType'     => 'application/json',
					'annotations'  => [
						'readonly'    => true,
						'destructive' => null,
						'idempotent'  => null,
					],
				],
			],
			[
				'id'          => 'awfah-posts/wp-get-post',
				'module'      => 'content_steward',
				'label'       => __( 'Get Post', 'ai-workflow-automation-ai-agent-hub' ),
				'description' => __( 'Get a WordPress post by ID.', 'ai-workflow-automation-ai-agent-hub' ),
				'category'    => 'awfah-posts',
				'input_schema' => [
					'type'       => 'object',
					'required'   => [ 'id' ],
					'properties' => [
						'id' => [
							'type'        => 'integer',
							'description' => __( 'The ID of the post.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'context' => [
							'type'        => 'string',
							'description' => __( 'Scope under which the request is made; determines fields present in response.', 'ai-workflow-automation-ai-agent-hub' ),
							'enum'        => [ 'view', 'embed', 'edit' ],
							'default'     => 'view',
						],
					],
				],
				'meta'        => [
					'show_in_rest' => true,
					'mcp'          => [ 'public' => true ],
					'uri'          => 'wordpress://ai-agent-hub/posts/{id}',
					'mimeType'     => 'application/json',
					'annotations'  => [
						'readonly'    => true,
						'destructive' => null,
						'idempotent'  => null,
					],
				],
			],
			[
				'id'          => 'awfah-posts/wp-add-post',
				'module'      => 'content_steward',
				'label'       => __( 'Add Post', 'ai-workflow-automation-ai-agent-hub' ),
				'description' => __( 'Add a new WordPress post.', 'ai-workflow-automation-ai-agent-hub' ),
				'category'    => 'awfah-posts',
				'input_schema' => [
					'type'       => 'object',
					'required'   => [ 'title', 'content' ],
					'properties' => [
						'title'   => [
							'type'        => 'string',
							'description' => __( 'The title for the post.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'content' => [
							'type'        => 'string',
							'description' => __( 'The content of the post in a valid Gutenberg block format.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'status'  => [
							'type'        => 'string',
							'description' => __( 'A named status for the post.', 'ai-workflow-automation-ai-agent-hub' ),
							'enum'        => [ 'publish', 'future', 'draft', 'pending', 'private' ],
							'default'     => 'draft',
						],
						'excerpt' => [
							'type'        => 'string',
							'description' => __( 'The excerpt for the post.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'author'  => [
							'type'        => 'integer',
							'description' => __( 'The ID for the author of the post.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'categories' => [
							'type'        => 'array',
							'description' => __( 'The terms assigned to the post in the category taxonomy.', 'ai-workflow-automation-ai-agent-hub' ),
							'items'       => [ 'type' => 'integer' ],
						],
						'tags'    => [
							'type'        => 'array',
							'description' => __( 'The terms assigned to the post in the post_tag taxonomy.', 'ai-workflow-automation-ai-agent-hub' ),
							'items'       => [ 'type' => 'integer' ],
						],
						'slug'    => [
							'type'        => 'string',
							'description' => __( 'An alphanumeric identifier for the post unique to its type.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'featured_media' => [
							'type'        => 'integer',
							'description' => __( 'The ID of the featured media for the post.', 'ai-workflow-automation-ai-agent-hub' ),
						],
					],
				],
				'output_schema' => [
					'type'       => 'object',
					'properties' => [
						'id'     => [
							'type'        => 'integer',
							'description' => __( 'The ID of the created post.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'link'   => [
							'type'        => 'string',
							'description' => __( 'URL to the created post.', 'ai-workflow-automation-ai-agent-hub' ),
							'format'      => 'uri',
						],
						'status' => [
							'type'        => 'string',
							'description' => __( 'The status of the created post.', 'ai-workflow-automation-ai-agent-hub' ),
						],
					],
				],
				'meta'        => [
					'show_in_rest' => true,
					'mcp'          => [ 'public' => true ],
					'annotations'  => [
						'readonly'    => false,
						'destructive' => false,
						'idempotent'  => false,
					],
				],
			],
			[
				'id'          => 'awfah-posts/wp-update-post',
				'module'      => 'content_steward',
				'label'       => __( 'Update Post', 'ai-workflow-automation-ai-agent-hub' ),
				'description' => __( 'Update a WordPress post by ID.', 'ai-workflow-automation-ai-agent-hub' ),
				'category'    => 'awfah-posts',
				'input_schema' => [
					'type'       => 'object',
					'required'   => [ 'id' ],
					'properties' => [
						'id'      => [
							'type'        => 'integer',
							'description' => __( 'The ID of the post to update.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'title'   => [
							'type'        => 'string',
							'description' => __( 'The title for the post.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'content' => [
							'type'        => 'string',
							'description' => __( 'The content of the post in a valid Gutenberg block format.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'status'  => [
							'type'        => 'string',
							'description' => __( 'A named status for the post.', 'ai-workflow-automation-ai-agent-hub' ),
							'enum'        => [ 'publish', 'future', 'draft', 'pending', 'private' ],
						],
						'excerpt' => [
							'type'        => 'string',
							'description' => __( 'The excerpt for the post.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'author'  => [
							'type'        => 'integer',
							'description' => __( 'The ID for the author of the post.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'categories' => [
							'type'        => 'array',
							'description' => __( 'The terms assigned to the post in the category taxonomy.', 'ai-workflow-automation-ai-agent-hub' ),
							'items'       => [ 'type' => 'integer' ],
						],
						'tags'    => [
							'type'        => 'array',
							'description' => __( 'The terms assigned to the post in the post_tag taxonomy.', 'ai-workflow-automation-ai-agent-hub' ),
							'items'       => [ 'type' => 'integer' ],
						],
						'slug'    => [
							'type'        => 'string',
							'description' => __( 'An alphanumeric identifier for the post unique to its type.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'featured_media' => [
							'type'        => 'integer',
							'description' => __( 'The ID of the featured media for the post.', 'ai-workflow-automation-ai-agent-hub' ),
						],
					],
				],
				'output_schema' => [
					'type'       => 'object',
					'properties' => [
						'id'     => [
							'type'        => 'integer',
							'description' => __( 'The ID of the updated post.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'link'   => [
							'type'        => 'string',
							'description' => __( 'URL to the updated post.', 'ai-workflow-automation-ai-agent-hub' ),
							'format'      => 'uri',
						],
						'status' => [
							'type'        => 'string',
							'description' => __( 'The status of the updated post.', 'ai-workflow-automation-ai-agent-hub' ),
						],
					],
				],
				'meta'        => [
					'show_in_rest' => true,
					'mcp'          => [ 'public' => true ],
					'annotations'  => [
						'readonly'    => false,
						'destructive' => false,
						'idempotent'  => true,
					],
				],
			],
			[
				'id'          => 'awfah-posts/wp-delete-post',
				'module'      => 'content_steward',
				'label'       => __( 'Delete Post', 'ai-workflow-automation-ai-agent-hub' ),
				'description' => __( 'Delete a WordPress post by ID.', 'ai-workflow-automation-ai-agent-hub' ),
				'category'    => 'awfah-posts',
				'input_schema' => [
					'type'       => 'object',
					'required'   => [ 'id' ],
					'properties' => [
						'id'    => [
							'type'        => 'integer',
							'description' => __( 'The ID of the post to delete.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'force' => [
							'type'        => 'boolean',
							'description' => __( 'Whether to bypass Trash and force deletion.', 'ai-workflow-automation-ai-agent-hub' ),
							'default'     => false,
						],
					],
				],
				'meta'        => [
					'show_in_rest' => true,
					'mcp'          => [ 'public' => true ],
					'annotations'  => [
						'readonly'    => false,
						'destructive' => true,
						'idempotent'  => true,
					],
				],
			],

			// ── Categories ───────────────────────────────────────────
			[
				'id'          => 'awfah-posts/wp-list-categories',
				'module'      => 'content_steward',
				'label'       => __( 'List Categories', 'ai-workflow-automation-ai-agent-hub' ),
				'description' => __( 'List all WordPress post categories.', 'ai-workflow-automation-ai-agent-hub' ),
				'category'    => 'awfah-posts',
				'input_schema' => [
					'type'       => 'object',
					'properties' => [
						'search'   => [
							'type'        => 'string',
							'description' => __( 'Limit results to those matching a string.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'page'     => [
							'type'        => 'integer',
							'description' => __( 'Current page of the collection.', 'ai-workflow-automation-ai-agent-hub' ),
							'default'     => 1,
							'minimum'     => 1,
						],
						'per_page' => [
							'type'        => 'integer',
							'description' => __( 'Maximum number of items to be returned in result set.', 'ai-workflow-automation-ai-agent-hub' ),
							'default'     => 10,
							'minimum'     => 1,
							'maximum'     => 100,
						],
					],
				],
				'meta'        => [
					'show_in_rest' => true,
					'mcp'          => [ 'public' => true ],
					'uri'          => 'wordpress://ai-agent-hub/categories',
					'mimeType'     => 'application/json',
					'annotations'  => [
						'readonly'    => true,
						'destructive' => null,
						'idempotent'  => null,
					],
				],
			],
			[
				'id'          => 'awfah-posts/wp-add-category',
				'module'      => 'content_steward',
				'label'       => __( 'Add Category', 'ai-workflow-automation-ai-agent-hub' ),
				'description' => __( 'Add a new WordPress post category.', 'ai-workflow-automation-ai-agent-hub' ),
				'category'    => 'awfah-posts',
				'input_schema' => [
					'type'       => 'object',
					'required'   => [ 'name' ],
					'properties' => [
						'name'        => [
							'type'        => 'string',
							'description' => __( 'HTML title for the category.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'description' => [
							'type'        => 'string',
							'description' => __( 'HTML description of the category.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'slug'        => [
							'type'        => 'string',
							'description' => __( 'An alphanumeric identifier for the category unique to its type.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'parent'      => [
							'type'        => 'integer',
							'description' => __( 'The parent term ID.', 'ai-workflow-automation-ai-agent-hub' ),
						],
					],
				],
				'meta'        => [
					'show_in_rest' => true,
					'mcp'          => [ 'public' => true ],
					'annotations'  => [
						'readonly'    => false,
						'destructive' => false,
						'idempotent'  => false,
					],
				],
			],
			[
				'id'          => 'awfah-posts/wp-update-category',
				'module'      => 'content_steward',
				'label'       => __( 'Update Category', 'ai-workflow-automation-ai-agent-hub' ),
				'description' => __( 'Update a WordPress post category.', 'ai-workflow-automation-ai-agent-hub' ),
				'category'    => 'awfah-posts',
				'input_schema' => [
					'type'       => 'object',
					'required'   => [ 'id' ],
					'properties' => [
						'id'          => [
							'type'        => 'integer',
							'description' => __( 'The ID of the category to update.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'name'        => [
							'type'        => 'string',
							'description' => __( 'HTML title for the category.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'description' => [
							'type'        => 'string',
							'description' => __( 'HTML description of the category.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'slug'        => [
							'type'        => 'string',
							'description' => __( 'An alphanumeric identifier for the category unique to its type.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'parent'      => [
							'type'        => 'integer',
							'description' => __( 'The parent term ID.', 'ai-workflow-automation-ai-agent-hub' ),
						],
					],
				],
				'meta'        => [
					'show_in_rest' => true,
					'mcp'          => [ 'public' => true ],
					'annotations'  => [
						'readonly'    => false,
						'destructive' => false,
						'idempotent'  => true,
					],
				],
			],
			[
				'id'          => 'awfah-posts/wp-delete-category',
				'module'      => 'content_steward',
				'label'       => __( 'Delete Category', 'ai-workflow-automation-ai-agent-hub' ),
				'description' => __( 'Delete a WordPress post category.', 'ai-workflow-automation-ai-agent-hub' ),
				'category'    => 'awfah-posts',
				'input_schema' => [
					'type'       => 'object',
					'required'   => [ 'id' ],
					'properties' => [
						'id'    => [
							'type'        => 'integer',
							'description' => __( 'The ID of the category to delete.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'force' => [
							'type'        => 'boolean',
							'description' => __( 'Required to be true, as terms do not support trashing.', 'ai-workflow-automation-ai-agent-hub' ),
							'default'     => false,
						],
					],
				],
				'meta'        => [
					'show_in_rest' => true,
					'mcp'          => [ 'public' => true ],
					'annotations'  => [
						'readonly'    => false,
						'destructive' => true,
						'idempotent'  => true,
					],
				],
			],

			// ── Tags ─────────────────────────────────────────────────
			[
				'id'          => 'awfah-posts/wp-list-tags',
				'module'      => 'content_steward',
				'label'       => __( 'List Tags', 'ai-workflow-automation-ai-agent-hub' ),
				'description' => __( 'List all WordPress post tags.', 'ai-workflow-automation-ai-agent-hub' ),
				'category'    => 'awfah-posts',
				'input_schema' => [
					'type'       => 'object',
					'properties' => [
						'search'   => [
							'type'        => 'string',
							'description' => __( 'Limit results to those matching a string.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'page'     => [
							'type'        => 'integer',
							'description' => __( 'Current page of the collection.', 'ai-workflow-automation-ai-agent-hub' ),
							'default'     => 1,
							'minimum'     => 1,
						],
						'per_page' => [
							'type'        => 'integer',
							'description' => __( 'Maximum number of items to be returned in result set.', 'ai-workflow-automation-ai-agent-hub' ),
							'default'     => 10,
							'minimum'     => 1,
							'maximum'     => 100,
						],
					],
				],
				'meta'        => [
					'show_in_rest' => true,
					'mcp'          => [ 'public' => true ],
					'uri'          => 'wordpress://ai-agent-hub/tags',
					'mimeType'     => 'application/json',
					'annotations'  => [
						'readonly'    => true,
						'destructive' => null,
						'idempotent'  => null,
					],
				],
			],
			[
				'id'          => 'awfah-posts/wp-add-tag',
				'module'      => 'content_steward',
				'label'       => __( 'Add Tag', 'ai-workflow-automation-ai-agent-hub' ),
				'description' => __( 'Add a new WordPress post tag.', 'ai-workflow-automation-ai-agent-hub' ),
				'category'    => 'awfah-posts',
				'input_schema' => [
					'type'       => 'object',
					'required'   => [ 'name' ],
					'properties' => [
						'name'        => [
							'type'        => 'string',
							'description' => __( 'HTML title for the tag.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'description' => [
							'type'        => 'string',
							'description' => __( 'HTML description of the tag.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'slug'        => [
							'type'        => 'string',
							'description' => __( 'An alphanumeric identifier for the tag unique to its type.', 'ai-workflow-automation-ai-agent-hub' ),
						],
					],
				],
				'meta'        => [
					'show_in_rest' => true,
					'mcp'          => [ 'public' => true ],
					'annotations'  => [
						'readonly'    => false,
						'destructive' => false,
						'idempotent'  => false,
					],
				],
			],
			[
				'id'          => 'awfah-posts/wp-update-tag',
				'module'      => 'content_steward',
				'label'       => __( 'Update Tag', 'ai-workflow-automation-ai-agent-hub' ),
				'description' => __( 'Update a WordPress post tag.', 'ai-workflow-automation-ai-agent-hub' ),
				'category'    => 'awfah-posts',
				'input_schema' => [
					'type'       => 'object',
					'required'   => [ 'id' ],
					'properties' => [
						'id'          => [
							'type'        => 'integer',
							'description' => __( 'The ID of the tag to update.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'name'        => [
							'type'        => 'string',
							'description' => __( 'HTML title for the tag.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'description' => [
							'type'        => 'string',
							'description' => __( 'HTML description of the tag.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'slug'        => [
							'type'        => 'string',
							'description' => __( 'An alphanumeric identifier for the tag unique to its type.', 'ai-workflow-automation-ai-agent-hub' ),
						],
					],
				],
				'meta'        => [
					'show_in_rest' => true,
					'mcp'          => [ 'public' => true ],
					'annotations'  => [
						'readonly'    => false,
						'destructive' => false,
						'idempotent'  => true,
					],
				],
			],
			[
				'id'          => 'awfah-posts/wp-delete-tag',
				'module'      => 'content_steward',
				'label'       => __( 'Delete Tag', 'ai-workflow-automation-ai-agent-hub' ),
				'description' => __( 'Delete a WordPress post tag.', 'ai-workflow-automation-ai-agent-hub' ),
				'category'    => 'awfah-posts',
				'input_schema' => [
					'type'       => 'object',
					'required'   => [ 'id' ],
					'properties' => [
						'id'    => [
							'type'        => 'integer',
							'description' => __( 'The ID of the tag to delete.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'force' => [
							'type'        => 'boolean',
							'description' => __( 'Required to be true, as terms do not support trashing.', 'ai-workflow-automation-ai-agent-hub' ),
							'default'     => false,
						],
					],
				],
				'meta'        => [
					'show_in_rest' => true,
					'mcp'          => [ 'public' => true ],
					'annotations'  => [
						'readonly'    => false,
						'destructive' => true,
						'idempotent'  => true,
					],
				],
			],
		];
	}

	/**
	 * Register all post-related abilities with the Abilities API.
	 */
	public static function register(): void {
		if ( ! function_exists( 'wp_register_ability' ) ) {
			return;
		}

		$callbacks = [
			'awfah-posts/wp-posts-search'    => [ __CLASS__, 'execute_search_posts' ],
			'awfah-posts/wp-get-post'        => [ __CLASS__, 'execute_get_post' ],
			'awfah-posts/wp-add-post'        => [ __CLASS__, 'execute_add_post' ],
			'awfah-posts/wp-update-post'     => [ __CLASS__, 'execute_update_post' ],
			'awfah-posts/wp-delete-post'     => [ __CLASS__, 'execute_delete_post' ],
			'awfah-posts/wp-list-categories' => [ __CLASS__, 'execute_list_categories' ],
			'awfah-posts/wp-add-category'    => [ __CLASS__, 'execute_add_category' ],
			'awfah-posts/wp-update-category' => [ __CLASS__, 'execute_update_category' ],
			'awfah-posts/wp-delete-category' => [ __CLASS__, 'execute_delete_category' ],
			'awfah-posts/wp-list-tags'       => [ __CLASS__, 'execute_list_tags' ],
			'awfah-posts/wp-add-tag'         => [ __CLASS__, 'execute_add_tag' ],
			'awfah-posts/wp-update-tag'      => [ __CLASS__, 'execute_update_tag' ],
			'awfah-posts/wp-delete-tag'      => [ __CLASS__, 'execute_delete_tag' ],
		];

		foreach ( self::get_abilities() as $ability ) {
			$config = $ability;
			$id     = $ability['id'];
			unset( $config['id'], $config['module'] );

			// Workaround: MCP ResourcesHandler calls execute() with no input.
			// Adding default empty object prevents "input is not of type object" validation error.
			if ( isset( $config['meta']['uri'], $config['input_schema']['type'] ) && 'object' === $config['input_schema']['type'] ) {
				$config['input_schema']['default'] = (object) [];
			}

			wp_register_ability(
				$id,
				array_merge(
					$config,
					[
						'execute_callback'    => $callbacks[ $id ],
						'permission_callback' => static function () use ( $id ) {
							return \AtlasAiDev\Awfah\Plugin::check_ability_access( $id, 'edit_posts' );
						},
					]
				)
			);
		}
	}

	// ─── Execute callbacks ──────────────────────────────────────────

	/**
	 * Search posts.
	 *
	 * @param array|null $input Query parameters (search, page, per_page, etc.).
	 * @return array|WP_Error
	 */
	public static function execute_search_posts( $input = null ) {
		return self::dispatch_rest( 'GET', '/wp/v2/posts', (array) $input );
	}

	/**
	 * Get a single post by ID.
	 *
	 * @param array|null $input Must contain 'id'.
	 * @return array|WP_Error
	 */
	public static function execute_get_post( $input = null ) {
		$input = (array) $input;
		$id    = isset( $input['id'] ) ? (int) $input['id'] : 0;
		unset( $input['id'] );

		return self::dispatch_rest( 'GET', '/wp/v2/posts/' . $id, $input );
	}

	/**
	 * Add a new post.
	 *
	 * @param array|null $input Post data (title, content, etc.).
	 * @return array|WP_Error
	 */
	public static function execute_add_post( $input = null ) {
		return self::dispatch_rest( 'POST', '/wp/v2/posts', (array) $input );
	}

	/**
	 * Update an existing post.
	 *
	 * @param array|null $input Must contain 'id' and fields to update.
	 * @return array|WP_Error
	 */
	public static function execute_update_post( $input = null ) {
		$input = (array) $input;
		$id    = isset( $input['id'] ) ? (int) $input['id'] : 0;
		unset( $input['id'] );

		return self::dispatch_rest( 'POST', '/wp/v2/posts/' . $id, $input );
	}

	/**
	 * Delete a post.
	 *
	 * @param array|null $input Must contain 'id'. Optional 'force'.
	 * @return array|WP_Error
	 */
	public static function execute_delete_post( $input = null ) {
		$input = (array) $input;
		$id    = isset( $input['id'] ) ? (int) $input['id'] : 0;
		unset( $input['id'] );

		return self::dispatch_rest( 'DELETE', '/wp/v2/posts/' . $id, $input );
	}

	/**
	 * List categories.
	 *
	 * @param array|null $input Query parameters.
	 * @return array|WP_Error
	 */
	public static function execute_list_categories( $input = null ) {
		return self::dispatch_rest( 'GET', '/wp/v2/categories', (array) $input );
	}

	/**
	 * Add a new category.
	 *
	 * @param array|null $input Category data (name, description, slug, parent).
	 * @return array|WP_Error
	 */
	public static function execute_add_category( $input = null ) {
		return self::dispatch_rest( 'POST', '/wp/v2/categories', (array) $input );
	}

	/**
	 * Update a category.
	 *
	 * @param array|null $input Must contain 'id' and fields to update.
	 * @return array|WP_Error
	 */
	public static function execute_update_category( $input = null ) {
		$input = (array) $input;
		$id    = isset( $input['id'] ) ? (int) $input['id'] : 0;
		unset( $input['id'] );

		return self::dispatch_rest( 'POST', '/wp/v2/categories/' . $id, $input );
	}

	/**
	 * Delete a category.
	 *
	 * @param array|null $input Must contain 'id'. Optional 'force'.
	 * @return array|WP_Error
	 */
	public static function execute_delete_category( $input = null ) {
		$input = (array) $input;
		$id    = isset( $input['id'] ) ? (int) $input['id'] : 0;
		unset( $input['id'] );

		return self::dispatch_rest( 'DELETE', '/wp/v2/categories/' . $id, $input );
	}

	/**
	 * List tags.
	 *
	 * @param array|null $input Query parameters.
	 * @return array|WP_Error
	 */
	public static function execute_list_tags( $input = null ) {
		return self::dispatch_rest( 'GET', '/wp/v2/tags', (array) $input );
	}

	/**
	 * Add a new tag.
	 *
	 * @param array|null $input Tag data (name, description, slug).
	 * @return array|WP_Error
	 */
	public static function execute_add_tag( $input = null ) {
		return self::dispatch_rest( 'POST', '/wp/v2/tags', (array) $input );
	}

	/**
	 * Update a tag.
	 *
	 * @param array|null $input Must contain 'id' and fields to update.
	 * @return array|WP_Error
	 */
	public static function execute_update_tag( $input = null ) {
		$input = (array) $input;
		$id    = isset( $input['id'] ) ? (int) $input['id'] : 0;
		unset( $input['id'] );

		return self::dispatch_rest( 'POST', '/wp/v2/tags/' . $id, $input );
	}

	/**
	 * Delete a tag.
	 *
	 * @param array|null $input Must contain 'id'. Optional 'force'.
	 * @return array|WP_Error
	 */
	public static function execute_delete_tag( $input = null ) {
		$input = (array) $input;
		$id    = isset( $input['id'] ) ? (int) $input['id'] : 0;
		unset( $input['id'] );

		return self::dispatch_rest( 'DELETE', '/wp/v2/tags/' . $id, $input );
	}

	// ─── Internal helpers ───────────────────────────────────────────

	/**
	 * Dispatch an internal REST API request.
	 *
	 * @param string $method HTTP method (GET, POST, DELETE).
	 * @param string $route  REST route (e.g. /wp/v2/posts).
	 * @param array  $params Parameters to pass to the request.
	 * @return array|WP_Error Response data or error.
	 */
	private static function dispatch_rest( string $method, string $route, array $params = [] ) {
		$request = new WP_REST_Request( $method, $route );

		foreach ( $params as $key => $value ) {
			$request->set_param( $key, $value );
		}

		$response = rest_do_request( $request );

		if ( $response->is_error() ) {
			$error = $response->as_error();
			return new WP_Error(
				$error->get_error_code(),
				$error->get_error_message(),
				[ 'status' => $response->get_status() ]
			);
		}

		$data = $response->get_data();

		// MCP structuredContent requires an object. Wrap sequential arrays.
		if ( is_array( $data ) && array_is_list( $data ) ) {
			return [ 'results' => $data ];
		}

		return $data;
	}
}
