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

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

#include "InworldNode_SubgraphNode.generated.h"

class UInworldGraphAsset;

/**
 * @class UInworldNode_SubgraphNode
 * @brief A node that executes another graph as a subgraph within the current graph.
 *
 * This node allows for modular graph design by embedding one graph asset within another.
 * It manages the execution of the subgraph and handles data flow between the parent graph
 * and the embedded subgraph. This enables graph reusability and complex hierarchical workflows.
 */
UCLASS()
class INWORLDRUNTIME_API UInworldNode_SubgraphNode : public UInworldNode
{
	GENERATED_BODY()

public:
	/** Soft reference to the graph asset that will be executed as a subgraph */
	UPROPERTY(BlueprintReadOnly, Category = "Inworld",
		Meta = (ToolTip = "Soft reference to the graph asset that will be executed as a subgraph"))
	TSoftObjectPtr<UInworldGraphAsset> GraphAsset;

	/** Description of the subgraph functionality and purpose */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Inworld",
		meta = (MultiLine = true, ToolTip = "Description of the subgraph functionality and purpose"))
	FString Description{};

	/** Map of runtime data keys and types required for subgraph execution */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Inworld",
		Meta = (ToolTip = "Map of runtime data keys and types required for subgraph execution"))
	TMap<FString, FString> ExecutionRequiredRuntimeData;

	/**
	 * @brief Sets the graph asset to be used as a subgraph.
	 *
	 * This function configures which graph asset will be executed when this subgraph node runs.
	 * It also refreshes the node's details to reflect the new graph's requirements.
	 *
	 * @param Asset The graph asset to set as the subgraph
	 */
	void SetGraphAsset(UInworldGraphAsset* Asset);

	/**
	 * @brief Retrieves the currently configured graph asset.
	 *
	 * @return Pointer to the graph asset, or nullptr if none is set
	 */
	UInworldGraphAsset* GetGraphAsset();

	/**
	 * @brief Refreshes the node's details based on the current graph asset.
	 *
	 * This function updates the description and runtime data requirements
	 * based on the currently set graph asset.
	 */
	void RefreshDetails();

	virtual const FString& GetDescription() override;

	const UInworldNode* GetStartNode();
	const UInworldNode* GetEndNode();

private:
	/** Cached reference to the loaded graph asset object */
	UPROPERTY(Transient, Meta = (ToolTip = "Cached reference to the loaded graph asset object"))
	TObjectPtr<UInworldGraphAsset> GraphAssetObject;

	/**
	 * @brief Retrieves JSON configuration for the subgraph node.
	 *
	 * This override implementation generates the JSON configuration needed
	 * for the subgraph node, including references to the embedded graph asset.
	 *
	 * @param GraphJson The JSON object to populate with configuration data
	 * @return Error code indicating success or failure of configuration generation
	 */
	virtual EInworldRuntimeErrors GetJsonConfig(const TSharedRef<FJsonObject>& GraphJson) override;
};
