<?php

namespace AtlasAiDev\Awfah\Abilities;

use WP_Error;
use WP_REST_Request;

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

class Rest_Api_Abilities {

	public static function get_abilities(): array {
		return [
			[
				'id'           => 'awfah-rest-api/list-api-functions',
				'module'       => 'rest_api',
				'label'        => __( 'List API Functions', 'ai-workflow-automation-ai-agent-hub' ),
				'description'  => __( 'List all available WordPress REST API endpoints that support CRUD operations.', 'ai-workflow-automation-ai-agent-hub' ),
				'category'     => 'awfah-rest-api',
				'input_schema' => [ 'type' => 'object', 'properties' => (object) [] ],
				'meta'         => [
					'show_in_rest' => true,
					'mcp'          => [ 'public' => true ],
					'uri'          => 'wordpress://ai-agent-hub/api/functions',
					'mimeType'     => 'application/json',
				],
			],
			[
				'id'           => 'awfah-rest-api/get-function-details',
				'module'       => 'rest_api',
				'label'        => __( 'Get Function Details', 'ai-workflow-automation-ai-agent-hub' ),
				'description'  => __( 'Get detailed metadata for a specific WordPress REST API endpoint and HTTP method.', 'ai-workflow-automation-ai-agent-hub' ),
				'category'     => 'awfah-rest-api',
				'input_schema' => [
					'type'       => 'object',
					'required'   => [ 'route', 'method' ],
					'properties' => [
						'route'  => [ 'type' => 'string', 'description' => __( 'The REST API route (e.g., "/wp/v2/posts").', 'ai-workflow-automation-ai-agent-hub' ) ],
						'method' => [ 'type' => 'string', 'enum' => [ 'GET', 'POST', 'PATCH', 'DELETE' ] ],
					],
				],
				'meta'         => [
					'show_in_rest' => true,
					'mcp'          => [ 'public' => true ],
					'uri'          => 'wordpress://ai-agent-hub/api/functions/{route}',
					'mimeType'     => 'application/json',
				],
			],
			[
				'id'           => 'awfah-rest-api/run-api-function',
				'module'       => 'rest_api',
				'label'        => __( 'Run API Function', 'ai-workflow-automation-ai-agent-hub' ),
				'description'  => __( 'Execute a specific WordPress REST API function by providing the endpoint route, HTTP method, and any required parameters.', 'ai-workflow-automation-ai-agent-hub' ),
				'category'     => 'awfah-rest-api',
				'input_schema' => [
					'type'       => 'object',
					'required'   => [ 'route', 'method' ],
					'properties' => [
						'route'  => [ 'type' => 'string' ],
						'method' => [ 'type' => 'string', 'enum' => [ 'GET', 'POST', 'PATCH', 'DELETE' ] ],
						'data'   => [ 'type' => 'object', 'description' => __( 'Request body for POST/PATCH or query parameters for GET/DELETE.', 'ai-workflow-automation-ai-agent-hub' ) ],
					],
				],
				'meta'         => [ 'show_in_rest' => true, 'mcp' => [ 'public' => true ] ],
			],
		];
	}

	public static function register(): void {
		if ( ! function_exists( 'wp_register_ability' ) ) {
			return;
		}
		$callbacks = [
			'awfah-rest-api/list-api-functions'  => [ __CLASS__, 'execute_list_api_functions' ],
			'awfah-rest-api/get-function-details' => [ __CLASS__, 'execute_get_function_details' ],
			'awfah-rest-api/run-api-function'    => [ __CLASS__, 'execute_run_api_function' ],
		];
		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, 'manage_options' );
				},
			] ) );
		}
	}

	public static function execute_list_api_functions( $input = null ) {
		$exact_ignore   = [ '/', '/batch/v1' ];
		$string_ignore  = [ 'oembed', 'autosaves', 'revisions', 'jwt-auth' ];
		$routes = rest_get_server()->get_routes();
		$result = [];
		foreach ( $routes as $route => $methods ) {
			if ( in_array( $route, $exact_ignore, true ) ) {
				continue;
			}
			$skip = false;
			foreach ( $string_ignore as $ignore ) {
				if ( strpos( $route, $ignore ) !== false ) {
					$skip = true;
					break;
				}
			}
			if ( $skip ) {
				continue;
			}
			foreach ( $methods as $the_methods ) {
				$result[] = [
					'route'  => $route,
					'method' => key( $the_methods['methods'] ),
				];
			}
		}
		return $result;
	}

	public static function execute_get_function_details( $input = null ) {
		$input        = (array) $input;
		$target_route = $input['route'] ?? '';
		$target_method = $input['method'] ?? '';
		$routes       = rest_get_server()->get_routes();
		foreach ( $routes as $route => $endpoints ) {
			if ( $route !== $target_route ) {
				continue;
			}
			foreach ( $endpoints as $endpoint ) {
				if ( isset( $endpoint['methods'][ $target_method ] ) ) {
					return $endpoint;
				}
			}
		}
		return new WP_Error( 'not_found', __( 'Endpoint not found.', 'ai-workflow-automation-ai-agent-hub' ) );
	}

	public static function execute_run_api_function( $input = null ) {
		$input  = (array) $input;
		$route  = $input['route'] ?? '';
		$method = $input['method'] ?? 'GET';
		$data   = $input['data'] ?? [];

		$parsed_route = $route;
		$query_params = [];
		if ( strpos( $route, '?' ) !== false ) {
			$parts        = explode( '?', $route, 2 );
			$parsed_route = $parts[0];
			parse_str( $parts[1], $query_params );
		}
		if ( 'GET' === $method && ! empty( $data ) ) {
			$query_params = array_merge( $query_params, $data );
		}

		$request = new WP_REST_Request( $method, $parsed_route );
		if ( 'GET' === $method || 'DELETE' === $method ) {
			if ( ! empty( $query_params ) ) {
				$request->set_query_params( $query_params );
			}
		} else {
			if ( ! empty( $data ) ) {
				$request->set_body_params( $data );
			}
		}

		$response = rest_do_request( $request );
		$data = $response->get_data();
		if ( is_array( $data ) && array_is_list( $data ) ) {
			return [ 'results' => $data ];
		}
		return $data;
	}
}
