<?php

namespace Limb_Chatbot\Includes\Chatbot_Tools\Tools;

use Limb_Chatbot\Includes\Chatbot_Tools\Chatbot_Tool;
use Limb_Chatbot\Includes\Data_Objects\Message;
use Limb_Chatbot\Includes\Data_Objects\Tool_Calls_Message;
use Limb_Chatbot\Includes\Exceptions\Exception;
use Limb_Chatbot\Includes\Services\Knowledge\Knowledge_Source_Store;
use Limb_Chatbot\Includes\Services\User_Prompt_Manager;
use Limb_Chatbot\Includes\Utilities\Chatbot_Utility;

/**
 * Chatbot tool for searching knowledge base.
 *
 * Uses a search query to retrieve relevant knowledge from the vector store
 * when internal knowledge is insufficient or missing.
 *
 * @since 1.0.0
 */
class Knowledge_Search extends Chatbot_Tool {

	/**
	 * Executes the tool action.
	 *
	 * If the chatbot has a knowledge base, builds a user prompt using the
	 * given search query and retrieves relevant knowledge. If no knowledge
	 * base is available, returns null.
	 *
	 * @param  array  $params  Tool parameters (must include 'search_query').
	 * @param  Tool_Calls_Message  $message  Original message triggering the tool.
	 * @param  Chatbot_Utility  $utility  Chatbot utility instance.
	 *
	 * @return array Result containing 'knowledge' (string|null) and 'success' status.
	 * @throws Exception
	 * @since 1.0.0
	 */
	public function execute( array $params, Tool_Calls_Message $message, Chatbot_Utility $utility ): array {
		if ( ! $utility->get_knowledge_base() ) {
			return [
				'knowledge' => null,
				'success'   => true,
			];
		}

		$search_message = Message::make( [
			'content'   => [
				[
					'type' => 'text',
					'text' => [
						'value' => $params['search_query'],
					],
				],
			],
			'role'      => Message::ROLE_USER,
			'chat_uuid' => $message->get_chat_uuid(),
		] );

		$user_prompt_manager = new User_Prompt_Manager( $search_message );
		$knowledge           = $user_prompt_manager->fetch_knowledge( $utility );

		// Replace existing sources with function calling sources
		$source_store = Knowledge_Source_Store::instance();
		$source_store->set_context( $utility, $search_message->extract_text() );
		$source_store->set_function_calling_sources( $knowledge );

		return [
			'knowledge' => $source_store->stringify_knowledge( $knowledge ),
			'success'   => true,
		];
	}

	/**
	 * Defines the tool's internal name.
	 *
	 * @return string Tool name used for registration and retrieval.
	 * @since 1.0.0
	 */
	protected function define_name(): string {
		return 'knowledge_search';
	}

	/**
	 * Returns a description of the tool and its usage rules.
	 *
	 * Explains when to trigger the tool and when not to trigger it.
	 *
	 * @return string Description of the tool and trigger conditions.
	 * @since 1.0.0
	 */
	protected function define_description(): string {
		return <<<DESC
Searches the internal knowledge base for relevant information.
Use this tool when:
- The user's question requires specific or factual details
- Current VERIFIED KNOWLEDGE does not contain the full answer
- You need more context to respond accurately
Do NOT use when:
- The answer is fully available in the provided references
- The question is casual, greeting, or off-topic
Craft a precise, keyword-rich search query.
DESC;
	}

	/**
	 * Defines the schema for tool parameters.
	 *
	 * @return array JSON Schema-like structure for validation and documentation.
	 * @since 1.0.0
	 */
	protected function define_parameters_schema(): array {
		return [
			'type'       => 'object',
			'properties' => [
				'search_query' => [
					'type'        => 'string',
					'description' => implode(" ", [ "A search query with relevant keywords and terms to find information in the knowledge base.", "Can be a question, phrase, or keywords.", "Should be specific and self-contained.", ]),
				],
			],
			'required'   => [ 'search_query' ],
		];
	}
}