<?php
declare( strict_types=1 );

namespace BLU\Abilities;

/**
 * CustomPostTypes abilities for WordPress custom post types.
 *
 * Every ability that takes a `post_type` argument routes through
 * blu_resolve_post_type() so callers can pass the slug, REST base,
 * or any label form. Single-item and list responses use the
 * blu_project_post_* helpers so the returned shape always leads
 * with the numeric `id` (which LLMs would otherwise routinely drop).
 */
class CustomPostTypes {

	/**
	 * Constructor - registers custom post type abilities.
	 */
	public function __construct() {
		$this->register_abilities();
	}

	/**
	 * Register custom post type abilities.
	 */
	private function register_abilities(): void {
		// List post types
		blu_register_ability(
			'blu/list-post-types',
			array(
				'label'               => 'List Post Types',
				'description'         => 'List all registered WordPress post types (built-in and custom). Use this to discover which post type slugs exist before creating or searching items.',
				'category'            => 'blu-mcp',
				'input_schema'        => array(
					'type' => 'object',
				),
				'execute_callback'    => function () {
					$request  = new \WP_REST_Request( 'GET', '/wp/v2/types' );
					$response = rest_do_request( $request );
					return blu_standardize_rest_response( $response );
				},
				'permission_callback' => fn() => current_user_can( 'edit_posts' ),
				'meta'                => array(
					'annotations' => array(
						'readonly'    => true,
						'destructive' => false,
						'idempotent'  => true,
					),
				),
			)
		);

		// Search custom post types
		blu_register_ability(
			'blu/cpt-search',
			array(
				'label'               => 'Search Custom Post Type Items',
				'description'         => 'Search and filter content items within a custom post type with pagination. Accepts friendly post_type identifiers (slug, REST base, or label). Results are slim projections — note the `id` of each result to use with blu/get-cpt, blu/update-cpt, or blu/delete-cpt.',
				'category'            => 'blu-mcp',
				'input_schema'        => array(
					'type'       => 'object',
					'properties' => array(
						'post_type' => array(
							'type'        => 'string',
							'description' => 'Post type identifier — slug ("bmcp_book"), REST base ("books"), or label ("Books"/"Book"). Case-insensitive.',
						),
						'search'    => array(
							'type'        => 'string',
							'description' => 'Search term',
						),
						'author'    => array(
							'type'        => 'integer',
							'description' => 'Filter by author ID',
						),
						'status'    => array(
							'type'        => 'string',
							'description' => 'Filter by post status. Defaults to "publish". Pass "any" to include drafts and other statuses.',
						),
						'page'      => array(
							'type'        => 'integer',
							'description' => 'Page number',
							'default'     => 1,
						),
						'per_page'  => array(
							'type'        => 'integer',
							'description' => 'Items per page',
							'default'     => 10,
						),
					),
					'required'   => array( 'post_type' ),
				),
				'execute_callback'    => function ( $input ) {
					$resolved = blu_resolve_post_type( (string) $input['post_type'] );
					if ( null === $resolved ) {
						return blu_post_type_not_found_response( (string) $input['post_type'] );
					}

					$page     = $input['page'] ?? 1;
					$per_page = $input['per_page'] ?? 10;

					$args = array(
						'post_type'      => $resolved,
						'posts_per_page' => $per_page,
						'paged'          => $page,
						'post_status'    => 'publish',
					);

					if ( ! empty( $input['search'] ) ) {
						$args['s'] = sanitize_text_field( $input['search'] );
					}

					if ( ! empty( $input['author'] ) ) {
						$args['author'] = intval( $input['author'] );
					}

					if ( ! empty( $input['status'] ) ) {
						$args['post_status'] = sanitize_text_field( $input['status'] );
					}

					$query   = new \WP_Query( $args );
					$results = array_map( 'blu_project_post_summary', $query->posts );

					return blu_prepare_ability_response(
						200,
						array(
							'post_type' => $resolved,
							'results'   => $results,
							'total'     => (int) $query->found_posts,
							'pages'     => (int) $query->max_num_pages,
							'page'      => (int) $page,
							'per_page'  => (int) $per_page,
						)
					);
				},
				'permission_callback' => fn() => current_user_can( 'edit_posts' ),
				'meta'                => array(
					'annotations' => array(
						'readonly'    => true,
						'destructive' => false,
						'idempotent'  => true,
					),
				),
			)
		);

		// Get custom post type
		blu_register_ability(
			'blu/get-cpt',
			array(
				'label'               => 'Get Custom Post Type Item',
				'description'         => 'Get a single content item from a custom post type by its ID. Accepts friendly post_type identifiers (slug, REST base, or label).',
				'category'            => 'blu-mcp',
				'input_schema'        => array(
					'type'       => 'object',
					'properties' => array(
						'post_type' => array(
							'type'        => 'string',
							'description' => 'Post type identifier — slug, REST base, or label. Case-insensitive.',
						),
						'id'        => array(
							'type'        => 'integer',
							'description' => 'Post ID',
						),
					),
					'required'   => array( 'post_type', 'id' ),
				),
				'execute_callback'    => function ( $input ) {
					$resolved = blu_resolve_post_type( (string) $input['post_type'] );
					if ( null === $resolved ) {
						return blu_post_type_not_found_response( (string) $input['post_type'] );
					}

					$post = get_post( intval( $input['id'] ) );
					if ( ! $post || $post->post_type !== $resolved ) {
						return blu_prepare_ability_response(
							404,
							sprintf( 'No %s item found with ID %d.', $resolved, (int) $input['id'] )
						);
					}

					return blu_prepare_ability_response( 200, blu_project_post_full( $post ) );
				},
				'permission_callback' => fn() => current_user_can( 'edit_posts' ),
				'meta'                => array(
					'annotations' => array(
						'readonly'    => true,
						'destructive' => false,
						'idempotent'  => true,
					),
				),
			)
		);

		// Add custom post type
		blu_register_ability(
			'blu/add-cpt',
			array(
				'label'               => 'Add Custom Post Type Item',
				'description'         => 'Create a new content item within an existing custom post type (e.g. add a new menu item, event, or recipe). Accepts friendly post_type identifiers (slug, REST base, or label). This does NOT register a new post type — use blu-list-post-types to discover what exists.',
				'category'            => 'blu-mcp',
				'input_schema'        => array(
					'type'       => 'object',
					'properties' => array(
						'post_type' => array(
							'type'        => 'string',
							'description' => 'Post type identifier — slug, REST base, or label. Case-insensitive. Must match a registered post type.',
						),
						'title'     => array(
							'type'        => 'string',
							'description' => 'Post title',
						),
						'content'   => array(
							'type'        => 'string',
							'description' => 'Post content in Gutenberg block format',
						),
						'excerpt'   => array(
							'type'        => 'string',
							'description' => 'Post excerpt',
						),
						'status'    => array(
							'type'        => 'string',
							'description' => 'Post status (e.g. "publish", "draft"). Defaults to "draft".',
						),
					),
					'required'   => array( 'post_type', 'title', 'content' ),
				),
				'execute_callback'    => function ( $input ) {
					$resolved = blu_resolve_post_type( (string) $input['post_type'] );
					if ( null === $resolved ) {
						return blu_post_type_not_found_response( (string) $input['post_type'] );
					}

					$post_data = array(
						'post_type'    => $resolved,
						'post_title'   => sanitize_text_field( $input['title'] ),
						'post_content' => wp_kses_post( $input['content'] ),
						'post_status'  => 'draft',
					);

					if ( ! empty( $input['excerpt'] ) ) {
						$post_data['post_excerpt'] = sanitize_text_field( $input['excerpt'] );
					}

					if ( ! empty( $input['status'] ) ) {
						$post_data['post_status'] = sanitize_text_field( $input['status'] );
					}

					$post_id = wp_insert_post( $post_data, true );
					if ( is_wp_error( $post_id ) ) {
						return blu_prepare_ability_response( 500, $post_id->get_error_message() );
					}

					return blu_prepare_ability_response( 201, blu_project_post_full( get_post( $post_id ) ) );
				},
				'permission_callback' => fn() => current_user_can( 'edit_posts' ),
				'meta'                => array(
					'annotations' => array(
						'readonly'    => false,
						'destructive' => false,
						'idempotent'  => false,
					),
				),
			)
		);

		// Update custom post type
		blu_register_ability(
			'blu/update-cpt',
			array(
				'label'               => 'Update Custom Post Type Item',
				'description'         => 'Update an existing content item in a custom post type by its ID. Accepts friendly post_type identifiers (slug, REST base, or label).',
				'category'            => 'blu-mcp',
				'input_schema'        => array(
					'type'       => 'object',
					'properties' => array(
						'post_type' => array(
							'type'        => 'string',
							'description' => 'Post type identifier — slug, REST base, or label. Case-insensitive.',
						),
						'id'        => array(
							'type'        => 'integer',
							'description' => 'Post ID',
						),
						'title'     => array(
							'type'        => 'string',
							'description' => 'Post title',
						),
						'content'   => array(
							'type'        => 'string',
							'description' => 'Post content',
						),
						'excerpt'   => array(
							'type'        => 'string',
							'description' => 'Post excerpt',
						),
						'status'    => array(
							'type'        => 'string',
							'description' => 'Post status',
						),
					),
					'required'   => array( 'post_type', 'id' ),
				),
				'execute_callback'    => function ( $input ) {
					$resolved = blu_resolve_post_type( (string) $input['post_type'] );
					if ( null === $resolved ) {
						return blu_post_type_not_found_response( (string) $input['post_type'] );
					}

					$post = get_post( intval( $input['id'] ) );
					if ( ! $post || $post->post_type !== $resolved ) {
						return blu_prepare_ability_response(
							404,
							sprintf( 'No %s item found with ID %d.', $resolved, (int) $input['id'] )
						);
					}

					$post_data = array( 'ID' => $post->ID );

					if ( ! empty( $input['title'] ) ) {
						$post_data['post_title'] = sanitize_text_field( $input['title'] );
					}

					if ( ! empty( $input['content'] ) ) {
						$post_data['post_content'] = wp_kses_post( $input['content'] );
					}

					if ( ! empty( $input['excerpt'] ) ) {
						$post_data['post_excerpt'] = sanitize_text_field( $input['excerpt'] );
					}

					if ( ! empty( $input['status'] ) ) {
						$post_data['post_status'] = sanitize_text_field( $input['status'] );
					}

					$post_id = wp_update_post( $post_data, true );
					if ( is_wp_error( $post_id ) ) {
						return blu_prepare_ability_response( 500, $post_id->get_error_message() );
					}

					return blu_prepare_ability_response( 200, blu_project_post_full( get_post( $post_id ) ) );
				},
				'permission_callback' => fn() => current_user_can( 'edit_posts' ),
				'meta'                => array(
					'annotations' => array(
						'readonly'    => false,
						'destructive' => false,
						'idempotent'  => true,
					),
				),
			)
		);

		// Delete custom post type
		blu_register_ability(
			'blu/delete-cpt',
			array(
				'label'               => 'Delete Custom Post Type Item',
				'description'         => 'Permanently delete a content item from a custom post type by its ID. Accepts friendly post_type identifiers (slug, REST base, or label).',
				'category'            => 'blu-mcp',
				'input_schema'        => array(
					'type'       => 'object',
					'properties' => array(
						'post_type' => array(
							'type'        => 'string',
							'description' => 'Post type identifier — slug, REST base, or label. Case-insensitive.',
						),
						'id'        => array(
							'type'        => 'integer',
							'description' => 'Post ID',
						),
					),
					'required'   => array( 'post_type', 'id' ),
				),
				'execute_callback'    => function ( $input ) {
					$resolved = blu_resolve_post_type( (string) $input['post_type'] );
					if ( null === $resolved ) {
						return blu_post_type_not_found_response( (string) $input['post_type'] );
					}

					$post = get_post( intval( $input['id'] ) );
					if ( ! $post || $post->post_type !== $resolved ) {
						return blu_prepare_ability_response(
							404,
							sprintf( 'No %s item found with ID %d.', $resolved, (int) $input['id'] )
						);
					}

					$result = wp_delete_post( $post->ID, true );
					if ( ! $result ) {
						return blu_prepare_ability_response( 500, 'Failed to delete post with ID ' . $post->ID );
					}

					return blu_prepare_ability_response(
						200,
						array(
							'deleted'   => true,
							'id'        => (int) $post->ID,
							'post_type' => $resolved,
						)
					);
				},
				'permission_callback' => fn() => current_user_can( 'delete_posts' ),
				'meta'                => array(
					'annotations' => array(
						'readonly'    => false,
						'destructive' => true,
						'idempotent'  => true,
					),
				),
			)
		);
	}
}
