/**
 * Copyright 2022-2025 Theai, Inc. dba Inworld AI
 */

#pragma once

#include "CoreMinimal.h"
#include "Graph/InworldNode.h"
#include "InworldNode_Custom.h"

#include "InworldNode_MCP.generated.h"

/**
 * @class UInworldNode_MCPListTools
 * @brief A node that lists available tools from an MCP server.
 *
 * This node connects to an MCP server and retrieves the list of available tools. It takes no inputs and returns a structure
 * containing all available tools.
 *
 * @input none
 * @output FInworldData_ListToolsResponse
 */
UCLASS()
class INWORLDRUNTIME_API UInworldNode_MCPListTools : public UInworldNode
{
	GENERATED_BODY()

public:
	/**
	 * @brief Default constructor for the node.
	 */
	UInworldNode_MCPListTools();

	/**
	 * @brief Native utility function. Creates a new node instance with the specified configuration
	 * @param Outer The UObject that will own this node
	 * @param NodeName The name to assign to the node
	 * @param ExecutionConfig The configuration for executing the node
	 * @return Newly created node instance
	 */
	static UInworldNode_MCPListTools* CreateNative(
		class UObject* Outer, const FString& NodeName, const FInworldMCPListToolsNodeExecutionConfig& ExecutionConfig);

	/** Configuration settings */
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Inworld")
	FInworldMCPListToolsNodeExecutionConfig ExecutionConfig{};

private:
	/**
	 * @brief Generates JSON configuration for the node.
	 *
	 * This override generates the JSON configuration needed for the node's
	 * processing operations.
	 *
	 * @param GraphJson The JSON object to populate with the node's configuration data
	 * @return Error code indicating success or failure of configuration generation
	 */
	virtual EInworldRuntimeErrors GetJsonConfig(const TSharedRef<FJsonObject>& GraphJson) override;

	UFUNCTION()
	UPARAM(meta = (DisplayName = "Tools"))
	FInworldData_ListToolsResponse Process_ListTools()
	{
		checkNoEntry();
		return {};
	}
};

/**
 * @class UInworldNode_MCPCallTool
 * @brief A node that calls multiple tools on an MCP server in parallel.
 *
 * This node takes FInworldData_ToolCallRequest input containing the tool call information and executes them on the MCP server in
 * parallel, returning the results as ToolCallResponse.
 *
 * @input FInworldData_ToolCallRequest Contains the list of tools and their associated arguments
 * @output FInworldData_ToolCallResponse Results of each tool call
 */
UCLASS()
class INWORLDRUNTIME_API UInworldNode_MCPCallTool : public UInworldNode
{
	GENERATED_BODY()

public:
	/**
	 * @brief Default constructor for the node.
	 */
	UInworldNode_MCPCallTool();

	/**
	 * @brief Native utility function. Creates a new node instance with the specified configuration
	 * @param Outer The UObject that will own this node
	 * @param NodeName The name to assign to the node
	 * @param ExecutionConfig The configuration for executing the node
	 * @return Newly created node instance
	 */
	static UInworldNode_MCPCallTool* CreateNative(
		class UObject* Outer, const FString& NodeName, const FInworldMCPCallToolNodeExecutionConfig& ExecutionConfig);

	/** Configuration settings */
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Inworld")
	FInworldMCPCallToolNodeExecutionConfig ExecutionConfig{};

private:
	/**
	 * @brief Generates JSON configuration for the node.
	 *
	 * This override generates the JSON configuration needed for the node's
	 * processing operations.
	 *
	 * @param GraphJson The JSON object to populate with the node's configuration data
	 * @return Error code indicating success or failure of configuration generation
	 */
	virtual EInworldRuntimeErrors GetJsonConfig(const TSharedRef<FJsonObject>& GraphJson) override;

	UFUNCTION()
	UPARAM(meta = (DisplayName = "Results"))
	FInworldData_ToolCallResponse Process_CallTool(const FInworldData_ToolCallRequest& ToolCallRequest)
	{
		checkNoEntry();
		return {};
	}
};

/**
 * @class UInworldNode_ExtractMCPRequest
 * @brief Takes in JSON text and extracts MCP request structure from it
 *
 * @input FInworldData_Text Contains JSON data of tool call requests
 * @output FInworldData_ToolCallRequest Tool call requests extracted from text (error if none)
 */
UCLASS()
class INWORLDRUNTIME_API UInworldNode_ExtractMCPRequest : public UInworldNode_Custom
{
	GENERATED_BODY()

public:
	/**
	 * @brief Default constructor for the node.
	 */
	UInworldNode_ExtractMCPRequest();

protected:
	/**
	 * @brief Takes input text and attempts to deserialize it into a tool call request structure
	 * @param Text JSON input text
	 * @return FInworldData_ToolCallRequest List of tool calls to request
	 */
	UFUNCTION()
	FInworldData_ToolCallRequest Process_Default(const FInworldData_Text& Text) const;
};
