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

#pragma once

#include "CoreMinimal.h"
#include "Graph/Edges/InworldEdge_WithCondition.h"
#include "Graph/InworldData.h"

#include "InworldEdge_SafetyResult.generated.h"

/**
 * @class UInworldEdge_SafetyResult
 * @brief An edge that controls data flow based on content safety evaluation results
 *
 * This edge class evaluates safety check results to determine if data should flow through
 * the graph. It can be configured to either allow only safe content or only flagged content
 * to pass through, making it useful for implementing content filtering and safety workflows.
 */
UCLASS(Blueprintable, BlueprintType)
class INWORLDRUNTIME_API UInworldEdge_SafetyResult : public UInworldEdge_WithCondition
{
	GENERATED_BODY()

public:
	/**
	 * @brief Default constructor for the safety result edge.
	 *
	 * Initializes the edge with default settings for safety-based data flow control.
	 * Sets the edge title to "IsSafe" and hides the negation option since safety
	 * logic is controlled through the bRequireSafe property instead.
	 */
	UInworldEdge_SafetyResult()
	{
		EdgeTitle = "Is Safe";
		bHideNegatation = true;
	}
	/**
	 * @brief Native utility function. Creates a new safety result edge instance
	 * @param Outer The UObject that will own this edge
	 * @param Source The source node name
	 * @param Destination The destination node name
	 * @param IsRequired Whether this edge is required for graph execution
	 * @param IsLoopEdge Whether this edge creates a loop in the graph
	 * @param bRequireSafe Whether to allow only safe content through this edge
	 * @return Newly created safety result edge
	 */
	static UInworldEdge_SafetyResult* CreateNative(
		UObject* Outer, const FString& Source, const FString& Destination, bool IsRequired, bool IsLoopEdge, bool bRequireSafe)
	{
		const FString SourceFormated = Source.Replace(TEXT(" "), TEXT(""));
		const FString DestinationFormated = Destination.Replace(TEXT(" "), TEXT(""));
		const FString ObjectName = FString::Printf(TEXT("Edge_%s_to_%s"), *SourceFormated, *DestinationFormated);
		UInworldEdge_SafetyResult* NewNode = NewObject<UInworldEdge_SafetyResult>(Outer, FName(ObjectName));
		NewNode->Source = Source;
		NewNode->Destination = Destination;
		NewNode->IsRequired = IsRequired;
		NewNode->IsLoopEdge = IsLoopEdge;
		NewNode->bRequireSafe = bRequireSafe;
		return NewNode;
	}

protected:
	/**
	 * @brief Controls whether the edge allows safe or flagged content to pass through.
	 *
	 * This property determines the safety filtering behavior of the edge:
	 * - When true: Only allows content that passed safety checks (is considered safe)
	 * - When false: Only allows content that failed safety checks (was flagged as unsafe)
	 *
	 * This enables flexible content filtering workflows where safe content can be
	 * processed normally while unsafe content can be routed to different handling
	 * mechanisms such as filtering, moderation, or alternative responses.
	 */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Inworld",
		Meta = (ToolTip = "When true, only allows content that passed safety checks. When false, only allows flagged content"))
	bool bRequireSafe{true};

	UFUNCTION()
	bool MeetsCondition_SafetyMatch(const UInworldProcessContext* ProcessContext, const FInworldData_SafetyResult& Input) const;

private:
	friend class UInworldEdgeAsset;
};
