<?php
/**
 * List Options Tool.
 *
 * List WordPress site options/settings with search and filtering. Supports
 * prefix filtering and excludes transients by default.
 *
 * @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_Options_Tool class.
 */
class List_Options_Tool extends Tool {

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

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

	/**
	 * Get the tool description.
	 *
	 * @return string The tool description.
	 * @since     1.0.0
	 */
	public function get_description() {
		return 'List WordPress site options/settings. Can search by option name pattern and filter by autoload status.';
	}

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

	/**
	 * Get the parameters schema 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' => 'Search pattern to filter options by name (SQL LIKE pattern, use % as wildcard).',
				),
				'autoload' => array(
					'type'        => 'string',
					'enum'        => array( 'yes', 'no', 'all' ),
					'description' => 'Filter by autoload status. Default: all.',
				),
				'limit'    => array(
					'type'        => 'integer',
					'description' => 'Maximum number of options to return (default: 100, max: 500).',
				),
				'offset'   => array(
					'type'        => 'integer',
					'description' => 'Number of options to skip for pagination (default: 0).',
				),
			),
			'required'   => array(),
		);
	}

	/**
	 * Get the default enabled status for this tool.
	 *
	 * @return bool True if enabled by default, false otherwise.
	 * @since     1.0.0
	 */
	public function get_default_enabled_status() {
		return true;
	}

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

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

		$search   = $args['search'] ?? '';
		$autoload = $args['autoload'] ?? 'all';
		$limit    = min( max( 1, $args['limit'] ?? 100 ), 500 );
		$offset   = max( 0, $args['offset'] ?? 0 );

		$where  = array();
		$params = array();

		if ( ! empty( $search ) ) {
			$where[]  = 'option_name LIKE %s';
			$params[] = '%' . $wpdb->esc_like( $search ) . '%';
		}

		if ( 'yes' === $autoload || 'no' === $autoload ) {
			$where[]  = 'autoload = %s';
			$params[] = $autoload;
		}

		$where_sql = ! empty( $where ) ? 'WHERE ' . implode( ' AND ', $where ) : '';

		$count_sql = "SELECT COUNT(*) FROM {$wpdb->options} {$where_sql}";
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- $wpdb->options is a WordPress core table name, $where_sql contains only placeholders; caching not applicable.
		$total = (int) $wpdb->get_var( ! empty( $params ) ? $wpdb->prepare( $count_sql, ...$params ) : $count_sql );

		$query    = "SELECT option_name, autoload FROM {$wpdb->options} {$where_sql} ORDER BY option_name ASC LIMIT %d OFFSET %d";
		$params[] = $limit;
		$params[] = $offset;

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- $wpdb->options is a WordPress core table name, user input uses placeholders; caching not applicable.
		$results = $wpdb->get_results( $wpdb->prepare( $query, ...$params ), ARRAY_A );

		$options = array();
		foreach ( $results as $row ) {
			$options[] = array(
				'name'     => $row['option_name'],
				'autoload' => $row['autoload'],
			);
		}

		return $this->success_response(
			'Options retrieved',
			array(
				'options'  => $options,
				'total'    => $total,
				'returned' => count( $options ),
				'offset'   => $offset,
				'has_more' => ( $offset + count( $options ) ) < $total,
			)
		);
	}
}
