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

#pragma once

#include "CoreMinimal.h"
#include "Primitives/Knowledge/InworldKnowledgeTypes.h"
#include "Primitives/LLM/InworldLLMTypes.h"
#include "Primitives/STT/InworldSTTTypes.h"
#include "Primitives/TTS/InworldTTSTypes.h"
#include "Primitives/TextEmbedder/InworldTextEmbedderTypes.h"
#include "UObject/NoExportTypes.h"

#include "InworldRuntimeSettings.generated.h"

/**
 * @enum EInworldLogVerbosity
 * @brief Enumeration for controlling telemetry logging verbosity levels.
 */
UENUM()
enum class EInworldLogVerbosity : uint8
{
	/** Display level logging - only essential messages */
	Display,
	/** Standard logging level */
	Log,
	/** Verbose logging - additional detail */
	Verbose,
	/** Very verbose logging - maximum detail */
	VeryVerbose,
};

/**
 * @class UInworldRuntimeSettings
 * @brief Configuration settings for the Inworld Runtime system.
 *
 * This class manages all configuration settings for the Inworld Runtime plugin,
 * including API keys, endpoints, telemetry settings, and creation configurations
 * for various primitives like LLM, STT, TTS, and TextEmbedder components.
 */
UCLASS(Config = Inworld, DefaultConfig)
class INWORLDRUNTIME_API UInworldRuntimeSettings : public UObject
{
	GENERATED_BODY()

public:
	UInworldRuntimeSettings(const FObjectInitializer& ObjectInitializer);
#if WITH_EDITOR
	virtual void PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) override;
#endif

	UPROPERTY(config, EditAnywhere, Category = "Inworld|Binary",
		meta = (ConfigRestartRequired = true, GetOptions = "InworldRuntimeSettings.GetAlternativeBinaryTypes",
			ToolTip = "Alternative binary type to use for runtime processing"))
	FString AlternativeBinaryType;

	UFUNCTION()
	static TArray<FString> GetAlternativeBinaryTypes();

	UPROPERTY(config, EditAnywhere, Category = "Inworld|Telemetry",
		Meta = (ConfigRestartRequired = true, ToolTip = "Whether telemetry and logging is enabled for the Inworld Runtime"))
	bool bTelemetryEnabled;

	UPROPERTY(config, EditAnywhere, Category = "Inworld|Telemetry",
		Meta = (ConfigRestartRequired = true, ToolTip = "Verbosity level for telemetry logging"))
	EInworldLogVerbosity TelemetryLogVerbosity;

	UPROPERTY(config, EditAnywhere, Category = "Inworld|Telemetry",
		meta = (EditCondition = "bTelemetryEnabled", EditConditionHides,
			ToolTip = "Whether to enable graph execution history tracking for debugging"))
	bool bEnableGraphExecutionHistory{true};

	UPROPERTY(config, EditAnywhere, Category = "Inworld|Telemetry",
		meta = (ClampMin = "10", ClampMax = "1000", UIMin = "10", UIMax = "1000", EditCondition = "bEnableGraphExecutionHistory",
			EditConditionHides, ToolTip = "Maximum number of graph execution history entries to keep in memory"))
	int32 GraphExecutionHistoryMaxCount{100};

	UPROPERTY(config, EditAnywhere, Category = "Inworld|ApiKey",
		Meta = (ConfigRestartRequired = true, ToolTip = "Runtime API key for authenticating with Inworld services"))
	FString RuntimeApiKey;

	UPROPERTY(config, EditAnywhere, Category = "Inworld|Endpoint",
		Meta = (ConfigRestartRequired = true, ToolTip = "Inworld endpoint URL for API connections"))
	FString InworldEndpoint;

	UPROPERTY(config, EditAnywhere, Category = "Inworld|Endpoint",
		Meta = (ConfigRestartRequired = true, ToolTip = "Inworld HTTP endpoint URL for HTTP API connections"))
	FString InworldHttpEndpoint;

	UPROPERTY(config, EditAnywhere, BlueprintReadOnly, Category = "Inworld|Primitives",
		Meta = (ToolTip = "Map of LLM creation configurations indexed by unique identifiers"))
	TMap<FString, FInworldLLMCreationConfig> LLMCreationConfig;

	UPROPERTY(config, EditAnywhere, Category = "Inworld|Primitives",
		Meta = (ToolTip = "Map of Speech-to-Text creation configurations indexed by unique identifiers"))
	TMap<FString, FInworldSTTCreationConfig> STTCreationConfig;

	UPROPERTY(config, EditAnywhere, Category = "Inworld|Primitives",
		Meta = (ToolTip = "Map of Streaming Speech-to-Text creation configurations indexed by unique identifiers"))
	TMap<FString, FInworldStreamingSTTCreationConfig> StreamingSTTCreationConfig;

	UPROPERTY(config, EditAnywhere, Category = "Inworld|Primitives",
		Meta = (ToolTip = "Map of Text-to-Speech creation configurations indexed by unique identifiers"))
	TMap<FString, FInworldTTSCreationConfig> TTSCreationConfig;

	UPROPERTY(config, EditAnywhere, BlueprintReadOnly, Category = "Inworld|Primitives",
		Meta = (ToolTip = "Map of Text Embedder creation configurations indexed by unique identifiers"))
	TMap<FString, FInworldTextEmbedderCreationConfig> TextEmbedderCreationConfig;

	UPROPERTY(config, EditAnywhere, Category = "Inworld|LLM", Meta = (ToolTip = "Array of available remote LLM providers"))
	TArray<FString> RemoteLLMProviders;

	UPROPERTY(config, EditAnywhere, Category = "Inworld|LLM", Meta = (ToolTip = "Array of available remote LLM models"))
	TArray<FString> RemoteLLMModels;

	UPROPERTY(config, EditAnywhere, Category = "Inworld|TTS", Meta = (ToolTip = "Array of available remote Text-to-Speech models"))
	TArray<FString> RemoteTTSModels;

	UPROPERTY(config, EditAnywhere, Category = "Inworld|TextEmbedder",
		Meta = (ToolTip = "Array of available remote Text Embedder providers"))
	TArray<FString> RemoteTextEmbedderProviders;

	UPROPERTY(config, EditAnywhere, Category = "Inworld|TextEmbedder",
		Meta = (ToolTip = "Array of available remote Text Embedder models"))
	TArray<FString> RemoteTextEmbedderModels;

	UPROPERTY(config, EditAnywhere, Category = "Inworld|Character",
		meta = (RequiredAssetDataTags = "RowStructure=/Script/InworldCharacter.InworldCharacterConfig",
			ToolTip = "Default character data table containing character configurations"))
	TSoftObjectPtr<UDataTable> DefaultCharacterDataTable;

	UFUNCTION()
	static TArray<FString> GetRemoteLLMProviders();

	UFUNCTION(meta = (DeprecatedFunction, DeprecationMessage = "Use GetRemoteLLMProviders instead."))
	static TArray<FString> GetLLMProviders();

	UFUNCTION()
	static TArray<FString> GetRemoteLLMModels();

	UFUNCTION()
	static TArray<FString> GetLocalLLMModels();

	UFUNCTION(meta = (DeprecatedFunction, DeprecationMessage = "Use GetRemoteLLMModels/GetLocalLLMModels instead."))
	static TArray<FString> GetLLMModels();

	UFUNCTION()
	static TArray<FString> GetRemoteTTSModels();

	UFUNCTION()
	static TArray<FString> GetLLMIds()
	{
		TArray<FString> Keys;
		GetDefault<UInworldRuntimeSettings>()->LLMCreationConfig.GetKeys(Keys);
		return Keys;
	}

	UFUNCTION()
	static TArray<FString> GetLocalSTTModels();

	UFUNCTION()
	static TArray<FString> GetSTTIds()
	{
		TArray<FString> Keys;
		GetDefault<UInworldRuntimeSettings>()->STTCreationConfig.GetKeys(Keys);
		return Keys;
	}

	UFUNCTION()
	static TArray<FString> GetStreamingSTTIds()
	{
		TArray<FString> Keys;
		GetDefault<UInworldRuntimeSettings>()->StreamingSTTCreationConfig.GetKeys(Keys);
		return Keys;
	}

	UFUNCTION()
	static TArray<FString> GetRemoteTextEmbedderProviders();
	UFUNCTION()
	static TArray<FString> GetRemoteTextEmbedderModels();

	UFUNCTION()
	static TArray<FString> GetLocalTextEmbedderModels();

	UFUNCTION()
	static TArray<FString> GetTextEmbedderIds()
	{
		TArray<FString> Keys;
		GetDefault<UInworldRuntimeSettings>()->TextEmbedderCreationConfig.GetKeys(Keys);
		return Keys;
	}

	UFUNCTION()
	static TArray<FString> GetLocalTTSModels();

	UFUNCTION()
	static TArray<FString> GetTTSIds()
	{
		TArray<FString> Keys;
		GetDefault<UInworldRuntimeSettings>()->TTSCreationConfig.GetKeys(Keys);
		return Keys;
	}
};
