<?php

namespace Limb_Chatbot\Includes\AI_Providers\Open_Ai\Endpoints\Assistant\Tools;

use Limb_Chatbot\Includes\Data_Objects\Chatbot_Tool;
use Limb_Chatbot\Includes\AI_Providers\Open_AI\Endpoints\Thread_Message\Thread_Message;
use Limb_Chatbot\Includes\AI_Providers\Open_Ai\Utilities\Thread_Utility;
use Limb_Chatbot\Includes\Exceptions\Error_Codes;
use Limb_Chatbot\Includes\Exceptions\Exception;
use Limb_Chatbot\Includes\Services\Helper;

/**
 * Class Function_Calling
 *
 * Executes dynamic function calls declared as assistant tool functions.
 *
 * @package Limb_Chatbot\Includes\AI_Providers\Open_Ai\Endpoints\Assistant\Tools
 * @since 1.0.0
 */
class Function_Calling {

	/**
	 * The tool call data array received from the assistant.
	 *
	 * @var array
	 * @since 1.0.0
	 */
	public array $tool_call;

	/**
	 * The name of the function being called.
	 *
	 * @var string
	 * @since 1.0.0
	 */
	public string $name;

	/**
	 * The output result of the function call.
	 *
	 * @var mixed
	 * @since 1.0.0
	 */
	public $output;

	/**
	 * The utility helper for working with threads.
	 *
	 * @var Thread_Utility
	 * @since 1.0.0
	 */
	public Thread_Utility $thread_utility;

	/**
	 * The current thread message instance.
	 *
	 * @var Thread_Message
	 * @since 1.0.0
	 */
	public Thread_Message $thread_message;

	/**
	 * Constructor.
	 *
	 * @param Thread_Utility  $thread_utility   The thread utility instance.
	 * @param Thread_Message  $thread_message   The thread message containing the function call.
	 * @param array           $tool_call        The tool call definition from OpenAI.
	 *
	 * @since 1.0.0
	 */
	public function __construct( Thread_Utility $thread_utility, Thread_Message $thread_message, $tool_call ) {
		$this->thread_utility = $thread_utility;
		$this->thread_message = $thread_message;
		$this->tool_call      = $tool_call;
	}

	/**
	 * Executes the function defined by the tool call.
	 *
	 * Uses the defined function name and decoded arguments from the tool call,
	 * then executes the function and stores the output.
	 *
	 * @return void
	 *
	 * @throws Exception If the specified function is not defined.
	 *
	 * @since 1.0.0
	 */
	public function call() {
		$function_name = Chatbot_Tool::FUNCTION_PREFIX . $this->tool_call['function']['name'];
		if ( ! function_exists( $function_name ) ) {
			// translators: %s is the name of the function that was not found.
			throw new Exception( Error_Codes::NOT_FOUND, sprintf( __( 'Function %s does not exist.', 'limb-chatbot' ), $function_name ) );
		}
		$this->output = call_user_func_array( $function_name, Helper::maybe_json_decode( $this->tool_call['function']['arguments'] ) );
	}
}