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

#pragma once

#include "CoreMinimal.h"
#include "Graph/InworldNode.h"
#include "InworldNode_Custom.h"
#include "Primitives/LLM/InworldLLMTypes.h"

#include "InworldNode_LLM.generated.h"

/**
 * @class UInworldNode_LLM
 * @brief A workflow node that processes chat messages and produces either
 * complete text output or a stream of text tokens based on the stream
 * parameter.
 *
 * UInworldNode_LLM encapsulates the functionality of an LLM client to generate text
 * responses within a workflow graph. It can be configured to output complete
 * text or stream tokens as they are generated.
 *
 * @input FInworldData_LLMChatRequest
 * @output FInworldData_LLMChatResponse
 */
UCLASS(Blueprintable, BlueprintType)
class INWORLDRUNTIME_API UInworldNode_LLM : public UInworldNode
{
	GENERATED_BODY()

public:
	/**
	 * @brief Default constructor for the LLM node.
	 *
	 * Initializes the node with default settings for Large Language Model processing.
	 */
	UInworldNode_LLM();

	/**
	 * @brief Native utility function. Creates a new LLM node instance with the specified configuration
	 * @param Outer The outer object that will own this node
	 * @param NodeName The name to assign to the node
	 * @param InExecutionConfig Execution configuration settings for text generation
	 * @return Newly created LLM node instance
	 */
	static UInworldNode_LLM* CreateNative(
		class UObject* Outer, const FString& NodeName, const FInworldLLMChatNodeExecutionConfig& InExecutionConfig);

	/**
	 * Used to define and manage parameters such as token limits, randomness,
	 * and other options that influence the behavior of text generation. This
	 * configuration ensures fine-grained control over the output quality and
	 * style of generated text by the Large Language Model.
	 */
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Inworld",
		Meta = (ToolTip =
					"Configuration settings for LLM execution including token limits, temperature, and other generation parameters"))
	FInworldLLMChatNodeExecutionConfig ExecutionConfig;

private:
	/**
	 * @brief Generates JSON configuration for the LLM node.
	 *
	 * This override generates the JSON configuration needed for the LLM node's
	 * processing operations, including creation config (compute host, model selection,
	 * routing options) and execution config (token limits, temperature, etc.).
	 *
	 * @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;

	/**
	 * @brief Processes LLM chat requests to generate text responses using the configured language model.
	 *
	 * This function handles the core LLM processing logic by sending chat requests to the
	 * configured language model (local or remote) and returning the generated response.
	 * The response can be streaming or complete based on the execution configuration.
	 *
	 * @param ChatRequest The input chat request containing conversation history and generation parameters
	 * @return Chat response containing generated text and metadata
	 */
	UFUNCTION()
	UPARAM(meta = (DisplayName = "Chat Response"))
	FInworldData_LLMChatResponse Process_LLM(const FInworldData_LLMChatRequest& ChatRequest)
	{
		checkNoEntry();
		return {};
	}
};

/**
 * @class UInworldNode_LLMToTextStream
 * @brief A proxy node to convert LLMChatResponse
 * to a DataStream_String.
 *
 * @input FInworldData_LLMChatResponse
 * @output FInworldData_DataStream_String
 */
UCLASS(Blueprintable, BlueprintType)
class INWORLDRUNTIME_API UInworldNode_LLMToTextStream : public UInworldNode_Custom
{
	GENERATED_BODY()

public:
	/**
	 * @brief Default constructor for the LLM to text stream converter node.
	 *
	 * Initializes the node with default settings for converting LLM chat responses
	 * to text data streams.
	 */
	UInworldNode_LLMToTextStream();

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

private:
	/**
	 * @brief Converts LLM chat response to a text data stream.
	 *
	 * This function extracts the text content from an LLM chat response and converts
	 * it into a text data stream format. This is useful for connecting LLM output
	 * to nodes that expect streaming text input, such as TTS or text processing nodes.
	 *
	 * @param ChatResponse The LLM chat response containing generated text content
	 * @return Text data stream containing the extracted text content
	 */
	UFUNCTION()
	virtual UPARAM(meta = (DisplayName = "Text Stream")) FInworldData_DataStream_String
		Process_Default(const FInworldData_LLMChatResponse& ChatResponse) const;
};

/**
 * @class UInworldNode_LLMToText
 * @brief A proxy node to convert LLMChatResponse to Text.
 *
 * @input FInworldData_LLMChatResponse
 * @output FInworldData_Text
 */
UCLASS(Blueprintable, BlueprintType)
class INWORLDRUNTIME_API UInworldNode_LLMToText : public UInworldNode_Custom
{
	GENERATED_BODY()

public:
	/**
	 * @brief Default constructor for the LLM to text converter node.
	 *
	 * Initializes the node with default settings for converting LLM chat responses
	 * to simple text output.
	 */
	UInworldNode_LLMToText();

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

private:
	/**
	 * @brief Converts LLM chat response to simple text output.
	 *
	 * This function extracts the text content from an LLM chat response and converts
	 * it into a simple text format. This is useful for connecting LLM output to nodes
	 * that expect single text input, such as text aggregators or display components.
	 *
	 * @param ChatResponse The LLM chat response containing generated text content
	 * @return Simple text data containing the extracted text content
	 */
	UFUNCTION()
	virtual UPARAM(meta = (DisplayName = "Text")) FInworldData_Text
		Process_Default(const FInworldData_LLMChatResponse& ChatResponse) const;
};
