<?php

namespace AtlasAiDev\Awfah\Abilities;

use WP_Error;
use WP_REST_Request;

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

/**
 * Registers WordPress media CRUD abilities using the Abilities API.
 *
 * @package AtlasAiDev\Awfah\Abilities
 */
class Media_Abilities {

	/**
	 * MIME type to file extension map.
	 *
	 * @var array<string, string>
	 */
	private static array $mime_map = [
		'image/jpeg'                    => 'jpg',
		'image/png'                     => 'png',
		'image/gif'                     => 'gif',
		'image/webp'                    => 'webp',
		'image/svg+xml'                 => 'svg',
		'image/svg'                     => 'svg',
		'application/pdf'               => 'pdf',
		'application/msword'            => 'doc',
		'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx',
		'application/vnd.ms-excel'      => 'xls',
		'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx',
		'application/vnd.ms-powerpoint' => 'ppt',
		'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'pptx',
		'text/plain'                    => 'txt',
		'text/csv'                      => 'csv',
		'text/html'                     => 'html',
		'text/xml'                      => 'xml',
		'application/json'              => 'json',
		'audio/mpeg'                    => 'mp3',
		'audio/wav'                     => 'wav',
		'audio/ogg'                     => 'ogg',
		'video/mp4'                     => 'mp4',
		'video/webm'                    => 'webm',
		'video/ogg'                     => 'ogv',
		'video/quicktime'               => 'mov',
		'video/x-msvideo'              => 'avi',
		'video/x-ms-wmv'               => 'wmv',
	];

	public static function get_abilities(): array {
		return [
			[
				'id'           => 'awfah-media/wp-list-media',
				'module'       => 'media_manager',
				'label'        => __( 'List Media', 'ai-workflow-automation-ai-agent-hub' ),
				'description'  => __( 'List WordPress media items with pagination and filtering.', 'ai-workflow-automation-ai-agent-hub' ),
				'category'     => 'awfah-media',
				'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',
							'default' => 1,
							'minimum' => 1,
						],
						'per_page' => [
							'type'    => 'integer',
							'default' => 10,
							'minimum' => 1,
							'maximum' => 100,
						],
						'media_type' => [
							'type'        => 'string',
							'description' => __( 'Filter by media type (image, video, audio, application).', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'mime_type'  => [
							'type'        => 'string',
							'description' => __( 'Filter by MIME type (e.g., image/jpeg, video/mp4).', 'ai-workflow-automation-ai-agent-hub' ),
						],
					],
				],
				'meta'         => [
					'show_in_rest' => true,
					'mcp'          => [ 'public' => true ],
					'uri'          => 'wordpress://ai-agent-hub/media',
					'mimeType'     => 'application/json',
				],
			],
			[
				'id'           => 'awfah-media/wp-get-media',
				'module'       => 'media_manager',
				'label'        => __( 'Get Media', 'ai-workflow-automation-ai-agent-hub' ),
				'description'  => __( 'Get a WordPress media item details by ID.', 'ai-workflow-automation-ai-agent-hub' ),
				'category'     => 'awfah-media',
				'input_schema' => [
					'type'       => 'object',
					'required'   => [ 'id' ],
					'properties' => [
						'id'      => [
							'type'        => 'integer',
							'description' => __( 'The ID of the media item.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'context' => [
							'type'    => 'string',
							'enum'    => [ 'view', 'embed', 'edit' ],
							'default' => 'view',
						],
					],
				],
				'meta'         => [
					'show_in_rest' => true,
					'mcp'          => [ 'public' => true ],
					'uri'          => 'wordpress://ai-agent-hub/media/{id}',
					'mimeType'     => 'application/json',
				],
			],
			[
				'id'           => 'awfah-media/wp-get-media-file',
				'module'       => 'media_manager',
				'label'        => __( 'Get Media File', 'ai-workflow-automation-ai-agent-hub' ),
				'description'  => __( 'Get the actual file content (blob) of a WordPress media item.', 'ai-workflow-automation-ai-agent-hub' ),
				'category'     => 'awfah-media',
				'input_schema' => [
					'type'       => 'object',
					'required'   => [ 'id' ],
					'properties' => [
						'id'   => [
							'type'        => 'integer',
							'description' => __( 'The ID of the media item.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'size' => [
							'type'        => 'string',
							'description' => __( 'Optional. The size of the image to retrieve (thumbnail, medium, large, full). Defaults to full/original size.', 'ai-workflow-automation-ai-agent-hub' ),
						],
					],
				],
				'meta'         => [
					'show_in_rest' => true,
					'mcp'          => [ 'public' => true ],
					'uri'          => 'wordpress://ai-agent-hub/media/{id}/file',
					'mimeType'     => 'application/octet-stream',
				],
			],
			[
				'id'           => 'awfah-media/wp-upload-media',
				'module'       => 'media_manager',
				'label'        => __( 'Upload Media', 'ai-workflow-automation-ai-agent-hub' ),
				'description'  => __( 'Upload a new media file to WordPress.', 'ai-workflow-automation-ai-agent-hub' ),
				'category'     => 'awfah-media',
				'input_schema' => [
					'type'       => 'object',
					'required'   => [ 'file' ],
					'properties' => [
						'file'        => [
							'type'        => 'string',
							'description' => __( 'The file to upload (base64 encoded).', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'title'       => [
							'type'        => 'string',
							'description' => __( 'The title of the media item.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'caption'     => [
							'type'        => 'string',
							'description' => __( 'The caption of the media item.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'description' => [
							'type'        => 'string',
							'description' => __( 'The description of the media item.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'alt_text'    => [
							'type'        => 'string',
							'description' => __( 'The alt text for the media item.', 'ai-workflow-automation-ai-agent-hub' ),
						],
					],
				],
				'meta'         => [
					'show_in_rest' => true,
					'mcp'          => [ 'public' => true ],
				],
			],
			[
				'id'           => 'awfah-media/wp-update-media',
				'module'       => 'media_manager',
				'label'        => __( 'Update Media', 'ai-workflow-automation-ai-agent-hub' ),
				'description'  => __( 'Update a WordPress media item.', 'ai-workflow-automation-ai-agent-hub' ),
				'category'     => 'awfah-media',
				'input_schema' => [
					'type'       => 'object',
					'required'   => [ 'id' ],
					'properties' => [
						'id'          => [
							'type'        => 'integer',
							'description' => __( 'The ID of the media item to update.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'title'       => [
							'type' => 'string',
						],
						'caption'     => [
							'type' => 'string',
						],
						'description' => [
							'type' => 'string',
						],
						'alt_text'    => [
							'type' => 'string',
						],
					],
				],
				'meta'         => [
					'show_in_rest' => true,
					'mcp'          => [ 'public' => true ],
				],
			],
			[
				'id'           => 'awfah-media/wp-delete-media',
				'module'       => 'media_manager',
				'label'        => __( 'Delete Media', 'ai-workflow-automation-ai-agent-hub' ),
				'description'  => __( 'Delete a WordPress media item permanently (requires force=true).', 'ai-workflow-automation-ai-agent-hub' ),
				'category'     => 'awfah-media',
				'input_schema' => [
					'type'       => 'object',
					'required'   => [ 'id' ],
					'properties' => [
						'id'    => [
							'type'        => 'integer',
							'description' => __( 'The ID of the media item to delete.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'force' => [
							'type'    => 'boolean',
							'default' => true,
						],
					],
				],
				'meta'         => [
					'show_in_rest' => true,
					'mcp'          => [ 'public' => true ],
				],
			],
			[
				'id'           => 'awfah-media/wp-search-media',
				'module'       => 'media_manager',
				'label'        => __( 'Search Media', 'ai-workflow-automation-ai-agent-hub' ),
				'description'  => __( 'Search WordPress media items by title, caption, or description.', 'ai-workflow-automation-ai-agent-hub' ),
				'category'     => 'awfah-media',
				'input_schema' => [
					'type'       => 'object',
					'properties' => [
						'search'     => [
							'type'        => 'string',
							'description' => __( 'Search term to look for in media titles, captions, and descriptions.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'media_type' => [
							'type'        => 'string',
							'description' => __( 'Filter by media type (image, video, audio, application).', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'mime_type'  => [
							'type'        => 'string',
							'description' => __( 'Filter by MIME type (e.g., image/jpeg, video/mp4).', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'author'     => [
							'type'        => 'integer',
							'description' => __( 'Filter by author ID.', 'ai-workflow-automation-ai-agent-hub' ),
						],
						'parent'     => [
							'type'        => 'integer',
							'description' => __( 'Filter by parent post ID.', 'ai-workflow-automation-ai-agent-hub' ),
						],
					],
				],
				'meta'         => [
					'show_in_rest' => true,
					'mcp'          => [ 'public' => true ],
					'uri'          => 'wordpress://ai-agent-hub/media/search',
					'mimeType'     => 'application/json',
				],
			],
		];
	}

	public static function register(): void {
		if ( ! function_exists( 'wp_register_ability' ) ) {
			return;
		}

		$callbacks = [
			'awfah-media/wp-list-media'     => [ __CLASS__, 'execute_list_media' ],
			'awfah-media/wp-get-media'      => [ __CLASS__, 'execute_get_media' ],
			'awfah-media/wp-get-media-file' => [ __CLASS__, 'execute_get_media_file' ],
			'awfah-media/wp-upload-media'   => [ __CLASS__, 'execute_upload_media' ],
			'awfah-media/wp-update-media'   => [ __CLASS__, 'execute_update_media' ],
			'awfah-media/wp-delete-media'   => [ __CLASS__, 'execute_delete_media' ],
			'awfah-media/wp-search-media'   => [ __CLASS__, 'execute_search_media' ],
		];

		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, 'upload_files' );
						},
					]
				)
			);
		}
	}

	public static function execute_list_media( $input = null ) {
		return self::dispatch_rest( 'GET', '/wp/v2/media', (array) $input );
	}

	public static function execute_get_media( $input = null ) {
		$input = (array) $input;
		$id    = isset( $input['id'] ) ? (int) $input['id'] : 0;
		unset( $input['id'] );
		return self::dispatch_rest( 'GET', '/wp/v2/media/' . $id, $input );
	}

	/**
	 * Get the actual file content (blob) of a WordPress media item.
	 *
	 * @param array|null $input Must contain 'id'. Optional 'size'.
	 * @return array|WP_Error
	 */
	public static function execute_get_media_file( $input = null ) {
		$input = (array) $input;
		$id    = isset( $input['id'] ) ? (int) $input['id'] : 0;
		$size  = isset( $input['size'] ) ? sanitize_text_field( $input['size'] ) : 'full';

		if ( ! $id ) {
			return new WP_Error( 'invalid_id', __( 'Invalid media ID.', 'ai-workflow-automation-ai-agent-hub' ) );
		}

		$file_path = get_attached_file( $id );
		if ( ! $file_path || ! file_exists( $file_path ) ) {
			return new WP_Error( 'file_not_found', __( 'File not found.', 'ai-workflow-automation-ai-agent-hub' ) );
		}

		if ( 'full' !== $size && 'original' !== $size ) {
			$meta = wp_get_attachment_metadata( $id );
			if ( isset( $meta['sizes'][ $size ]['file'] ) ) {
				$base_dir  = pathinfo( $file_path, PATHINFO_DIRNAME );
				$file_path = $base_dir . '/' . $meta['sizes'][ $size ]['file'];
			}
		}

		if ( ! file_exists( $file_path ) ) {
			return new WP_Error( 'size_not_found', __( 'Requested size not found.', 'ai-workflow-automation-ai-agent-hub' ) );
		}

		$mime_type = get_post_mime_type( $id );
		$file_data = file_get_contents( $file_path ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents

		return [
			'results'  => $file_data,
			'type'     => 'image',
			'mimeType' => $mime_type,
		];
	}

	/**
	 * Upload a new media file to WordPress from base64 data.
	 *
	 * @param array|null $input Must contain 'file' (base64). Optional title, caption, description, alt_text.
	 * @return array|WP_Error
	 */
	public static function execute_upload_media( $input = null ) {
		$input      = (array) $input;
		$base64_data = $input['file'] ?? '';

		if ( empty( $base64_data ) ) {
			return new WP_Error( 'missing_file', __( 'No file data provided.', 'ai-workflow-automation-ai-agent-hub' ) );
		}

		// Remove data URI prefix if present.
		if ( strpos( $base64_data, 'data:' ) === 0 ) {
			$base64_data = preg_replace( '/^data:.*?;base64,/', '', $base64_data );
		}

		$file_data = base64_decode( $base64_data, true ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode
		if ( false === $file_data ) {
			return new WP_Error( 'invalid_base64', __( 'Invalid base64 data.', 'ai-workflow-automation-ai-agent-hub' ) );
		}

		$finfo     = finfo_open( FILEINFO_MIME_TYPE );
		$mime_type = finfo_buffer( $finfo, $file_data );
		finfo_close( $finfo );

		if ( empty( $mime_type ) || ! isset( self::$mime_map[ $mime_type ] ) ) {
			return new WP_Error( 'unsupported_type', __( 'File type not supported.', 'ai-workflow-automation-ai-agent-hub' ) );
		}

		$filename  = isset( $input['title'] ) ? sanitize_file_name( $input['title'] ) : 'upload';
		$filename .= '.' . self::$mime_map[ $mime_type ];

		$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
		$request->set_header( 'content-type', $mime_type );
		$request->set_header( 'content-disposition', 'attachment; filename="' . $filename . '"' );
		$request->set_body( $file_data );

		if ( ! empty( $input['title'] ) ) {
			$request->set_param( 'title', $input['title'] );
		}
		if ( ! empty( $input['caption'] ) ) {
			$request->set_param( 'caption', $input['caption'] );
		}
		if ( ! empty( $input['description'] ) ) {
			$request->set_param( 'description', $input['description'] );
		}
		if ( ! empty( $input['alt_text'] ) ) {
			$request->set_param( 'alt_text', $input['alt_text'] );
		}

		$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() ] );
		}

		return $response->get_data();
	}

	public static function execute_update_media( $input = null ) {
		$input = (array) $input;
		$id    = isset( $input['id'] ) ? (int) $input['id'] : 0;
		unset( $input['id'] );
		return self::dispatch_rest( 'POST', '/wp/v2/media/' . $id, $input );
	}

	public static function execute_delete_media( $input = null ) {
		$input = (array) $input;
		$id    = isset( $input['id'] ) ? (int) $input['id'] : 0;
		unset( $input['id'] );
		return self::dispatch_rest( 'DELETE', '/wp/v2/media/' . $id, $input );
	}

	public static function execute_search_media( $input = null ) {
		return self::dispatch_rest( 'GET', '/wp/v2/media', (array) $input );
	}

	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();
		if ( is_array( $data ) && array_is_list( $data ) ) {
			return [ 'results' => $data ];
		}
		return $data;
	}
}
