<?php

namespace Limb_Chatbot\Includes\Chatbot_Tools;

use Limb_Chatbot\Includes\Chatbot_Tools\Actions\Action_Chatbot_Tool;
use Limb_Chatbot\Includes\Chatbot_Tools\Tools\Agent_Operation_Tool;
use Limb_Chatbot\Includes\Data_Objects\Action;
use Limb_Chatbot\Includes\Traits\SingletonTrait;
use Limb_Chatbot\Includes\Utilities\Chatbot_Utility;

/**
 * Manages the registration and retrieval of chatbot tools.
 *
 * This class acts as a central registry for all available chatbot tools,
 * such as topic detection and knowledge generation. Implements the Singleton
 * pattern to ensure a single shared instance.
 *
 * @since 1.0.0
 */
class Chatbot_Tools {

	use SingletonTrait;

	/**
	 * Registered chatbot tools.
	 *
	 * Array structure: [ tool_name => Chatbot_Tool instance ]
	 *
	 * @var Chatbot_Tool[]
	 * @since 1.0.0
	 */
	private array $tools = [];

	/**
	 * Constructor.
	 *
	 * Registers default tools like Knowledge_Search.
	 *
	 * @since 1.0.0
	 */
	public function __construct( Chatbot_Utility $chatbot_utility ) {
		$this->register_actions( $chatbot_utility );
		static::$instance = $this;
	}

	/**
	 * Register a chatbot tool.
	 *
	 * Adds a new tool to the internal registry. If a tool with the same name
	 * exists, it will be overwritten.
	 *
	 * @param  Chatbot_Tool  $tool  Tool instance to register.
	 *
	 * @since 1.0.0
	 */
	public function register_tool( Chatbot_Tool $tool ): void {
		$this->tools[ $tool->get_name() ] = $tool;
	}

	/**
	 * Register chatbot action tools.
	 *
	 * Retrieves all actions from the chatbot utility and registers each
	 * as a Chatbot_Tool instance.
	 *
	 * @param  Chatbot_Utility  $chatbot_utility  Chatbot utility instance.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	private function register_actions( Chatbot_Utility $chatbot_utility ) {
		if ( ( $actions = $chatbot_utility->get_actions() ) && ! $actions->is_empty() ) {
			foreach ( $actions->get() as $action ) {
				if ( $action->get_type() === Action::TYPE_CONVERSATIONAL ) {
					$this->tools[ $action->get_name() ] = new Action_Chatbot_Tool( $action );
				}
			}
		}
	}

	/**
	 * Retrieve all registered chatbot tools.
	 *
	 * @return Chatbot_Tool[] Array of tool instances, keyed by tool name.
	 * @since 1.0.0
	 */
	public function get_tools(): array {
		return $this->tools;
	}

	/**
	 * Retrieve a specific chatbot tool by name.
	 *
	 * Returns the tool instance if it exists, or null if not found.
	 *
	 * @param  string  $name  Tool name to retrieve.
	 *
	 * @return Chatbot_Tool|null Tool instance or null.
	 * @since 1.0.0
	 */
	public function get_tool( string $name ): ?Chatbot_Tool {
		return $this->tools[ $name ] ?? null;
	}

	/**
	 * Unregister a chatbot tool by name.
	 *
	 * Removes a tool from the internal registry.
	 *
	 * @param  string  $name  Tool name to unregister.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function unregister_tool( string $name ): void {
		unset( $this->tools[ $name ] );
	}

	public function get_operations() {
		foreach ( $this->tools as $tool ) {
			if ( $tool instanceof Agent_Operation_Tool ) {
				$res[] = $tool;
			}
		}

		return $res ?? [];
	}

	public function has_operations() {
		return ! empty( array_values( array_filter( $this->tools, function ( $tool ) {
			return $tool instanceof Agent_Operation_Tool;
		} ) ) );
	}
}
