<?php
/**
 * List Shortcodes Tool.
 *
 * Lists all registered WordPress shortcodes with their callbacks. Reads from
 * global $shortcode_tags array with pagination support.
 *
 * @package   Agenistrator
 * @since     1.0.0
 * @author    Alex Ruban <alex@maximum.guru>
 * @author    Maximum Software Inc <contact@maximum.software>
 * @license   GPL-3.0-only
 * @link      https://agenistrator.com/
 *
 * SPDX-FileCopyrightText: 2025-2026 Alex Ruban <alex@maximum.guru>
 * SPDX-FileCopyrightText: 2025-2026 Maximum Software Inc <contact@maximum.software>
 * SPDX-License-Identifier: GPL-3.0-only
 */

namespace Agenistrator;

// Direct access prevention
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * List_Shortcodes_Tool class.
 */
class List_Shortcodes_Tool extends Tool {

	/**
	 * Get the tool ID.
	 *
	 * @return string The tool ID.
	 * @since     1.0.0
	 */
	public function get_id() {
		return 'list_shortcodes';
	}

	/**
	 * Get the tool name.
	 *
	 * @return string The tool name.
	 * @since     1.0.0
	 */
	public function get_name() {
		return __( 'List Shortcodes', 'agenistrator' );
	}

	/**
	 * Get the description of the tool.
	 *
	 * @return string The description of the tool.
	 * @since     1.0.0
	 */
	public function get_description() {
		return 'Lists all registered WordPress shortcodes with their callback functions.';
	}

	/**
	 * Get the parameters for this tool.
	 *
	 * @return array Parameters schema in JSON Schema format.
	 * @since     1.0.0
	 */
	public function get_parameters() {
		return array(
			'type'       => 'object',
			'properties' => array(
				'search' => array(
					'type'        => 'string',
					'description' => 'Optional search term to filter shortcodes by tag name.',
				),
				'limit'  => array(
					'type'        => 'integer',
					'description' => 'Maximum number of shortcodes to return',
					'default'     => 100,
				),
				'offset' => array(
					'type'        => 'integer',
					'description' => 'Number of shortcodes to skip',
					'default'     => 0,
				),
			),
			'required'   => array(),
		);
	}

	/**
	 * Check if the current user has permission to execute this tool.
	 *
	 * @return bool Whether the user has permission.
	 * @since     1.0.0
	 */
	public function current_user_can_execute() {
		return current_user_can( 'manage_options' );
	}

	/**
	 * Check if this tool is read-only.
	 *
	 * @return bool True - this tool only reads data.
	 * @since     1.0.0
	 */
	public function is_read_only() {
		return true;
	}

	/**
	 * Execute the tool with the given arguments.
	 *
	 * @param array $args The arguments for the tool.
	 * @return array The result of executing the tool.
	 * @since     1.0.0
	 */
	protected function execute( $args ) {
		global $shortcode_tags;

		$search     = strtolower( $args['search'] ?? '' );
		$limit      = isset( $args['limit'] ) ? intval( $args['limit'] ) : 100;
		$offset     = isset( $args['offset'] ) ? intval( $args['offset'] ) : 0;
		$shortcodes = array();

		if ( empty( $shortcode_tags ) || ! is_array( $shortcode_tags ) ) {
			return $this->success_response(
				'No shortcodes registered',
				array(
					'shortcodes' => array(),
					'count'      => 0,
					'total'      => 0,
					'limit'      => $limit,
					'offset'     => $offset,
					'has_more'   => false,
				)
			);
		}

		foreach ( $shortcode_tags as $tag => $callback ) {
			// Apply search filter if provided
			if ( $search && strpos( strtolower( $tag ), $search ) === false ) {
				continue;
			}

			$shortcode_data        = $this->get_shortcode_info( $callback );
			$shortcode_data['tag'] = $tag;

			$shortcodes[] = $shortcode_data;
		}

		// Sort alphabetically by tag
		usort(
			$shortcodes,
			function ( $a, $b ) {
				return strcmp( $a['tag'], $b['tag'] );
			}
		);

		// Apply pagination
		$total_shortcodes = count( $shortcodes );
		$shortcodes       = array_slice( $shortcodes, $offset, $limit );
		$has_more         = ( $offset + count( $shortcodes ) ) < $total_shortcodes;

		$count   = count( $shortcodes );
		$message = String_Utils::replace_tags( '{count} shortcodes found', array( 'count' => $count ) );

		return $this->success_response(
			$message,
			array(
				'shortcodes' => $shortcodes,
				'count'      => $count,
				'total'      => $total_shortcodes,
				'limit'      => $limit,
				'offset'     => $offset,
				'has_more'   => $has_more,
			)
		);
	}

	/**
	 * Get detailed shortcode information using reflection.
	 *
	 * @param mixed $callback The callback to analyze.
	 * @return array The shortcode information.
	 */
	private function get_shortcode_info( $callback ) {
		$info = array(
			'callback' => PHP_Utils::get_callback_name( $callback ),
			'source'   => null,
		);

		$reflection = PHP_Utils::get_callback_reflection( $callback );

		if ( $reflection ) {
			$file = $reflection->getFileName();
			if ( $file ) {
				$info['source'] = WordPress_Utils::get_relative_path( $file );
				$info['line']   = $reflection->getStartLine();
			}
		}

		return $info;
	}
}
