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

#pragma once

#include "InworldRuntimeTypes.h"
#include "Logging/LogMacros.h"

namespace inworld
{
class TextEmbedderInterface;
}

#include "InworldTextEmbedderTypes.generated.h"

INWORLDRUNTIME_API DECLARE_LOG_CATEGORY_EXTERN(LogInworldTextEmbedder, Log, All);

/**
 * @struct FInworldRetrievalConfig
 * @brief Configuration for text embedding retrieval operations.
 *
 * This structure defines parameters for retrieving relevant text embeddings or knowledge
 * records based on similarity searches, including threshold and result count settings.
 */
USTRUCT(BlueprintType)
struct FInworldRetrievalConfig
{
	GENERATED_BODY()

	/** The minimum relevance score for records to be retrieved (0.0-1.0, defaults to 0.5) */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, config, Category = "Inworld|Text Embedding",
		Meta = (ToolTip = "The minimum relevance score for records to be retrieved (0.0-1.0, defaults to 0.5)"))
	float Threshold = 0.5f;

	/** The maximum number of records to retrieve (defaults to 5) */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, config, Category = "Inworld|Text Embedding",
		Meta = (ToolTip = "The maximum number of records to retrieve (defaults to 5)"))
	int32 TopK = 5;
};

/**
 * @struct FInworldLocalTextEmbedderCreationConfig
 * @brief Configuration for creating local text embedder instances.
 *
 * This structure defines the parameters required for setting up local text embedding processing,
 * including compute host selection and model specification.
 */
USTRUCT(BlueprintType)
struct FInworldLocalTextEmbedderCreationConfig
{
	GENERATED_BODY()

	/** The local compute device to use for text embedding processing */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Inworld|TextEmbedder",
		Meta = (ToolTip = "The local compute device to use for text embedding processing"))
	EInworldLocalComputeHost LocalComputeHost{EInworldLocalComputeHost::CPU};

	/** The text embedder model to use for generating embeddings */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Inworld|TextEmbedder",
		Meta = (GetOptions = "InworldRuntimeSettings.GetLocalTextEmbedderModels", NoResetToDefault,
			ToolTip = "The text embedder model to use for generating embeddings"))
	FString Model{"bge-large-en-v1.5_fp32.gguf"};
};

/**
 * @struct FInworldRemoteTextEmbedderCreationConfig
 * @brief Configuration for creating remote text embedder instances.
 *
 * This structure defines the parameters required for setting up remote text embedding processing,
 * including provider and model selection for cloud-based embedding services.
 */
USTRUCT(BlueprintType)
struct FInworldRemoteTextEmbedderCreationConfig
{
	GENERATED_BODY()

	/** The remote text embedder provider to use for embedding generation */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Inworld|TextEmbedder",
		Meta = (GetOptions = "InworldRuntimeSettings.GetRemoteTextEmbedderProviders", NoResetToDefault,
			ToolTip = "The remote text embedder provider to use for embedding generation"))
	FString Provider{"inworld"};

	/** The text embedder model to use for generating embeddings */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Inworld|TextEmbedder",
		Meta = (GetOptions = "InworldRuntimeSettings.GetRemoteTextEmbedderModels", NoResetToDefault,
			ToolTip = "The text embedder model to use for generating embeddings"))
	FString Model{"BAAI/bge-large-en-v1.5"};
};

/**
 * @struct FInworldTextEmbedderCreationConfig
 * @brief Main configuration structure for creating text embedder instances.
 *
 * This structure defines whether to use local or remote text embedding processing
 * and contains the appropriate sub-configuration for the selected compute host.
 */
USTRUCT(BlueprintType)
struct FInworldTextEmbedderCreationConfig
{
	GENERATED_BODY()

	/** Whether to use local or remote compute host for text embedding processing */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Inworld|TextEmbedder",
		Meta = (ToolTip = "Whether to use local or remote compute host for text embedding processing"))
	EInworldComputeHost ComputeHost{EInworldComputeHost::REMOTE};

	/** Configuration for local text embedding processing */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Inworld|TextEmbedder",
		meta = (EditCondition = "ComputeHost == EInworldComputeHost::LOCAL", EditConditionHides,
			ToolTip = "Configuration for local text embedding processing"))
	FInworldLocalTextEmbedderCreationConfig LocalCreationConfig{};

	/** Configuration for remote text embedding processing */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Inworld|TextEmbedder",
		meta = (EditCondition = "ComputeHost == EInworldComputeHost::REMOTE", EditConditionHides,
			ToolTip = "Configuration for remote text embedding processing"))
	FInworldRemoteTextEmbedderCreationConfig RemoteCreationConfig{};
};

/** Native delegate called when text embedder primitive creation completes with interface access */
DECLARE_DELEGATE_OneParam(
	FOnInworldTextEmbedderPrimitiveCreatedNative, TSharedPtr<inworld::TextEmbedderInterface> /*TextEmbedder*/);

namespace inworld
{

class LocalTextEmbedderConfig;
/**
 * @brief Converts Unreal local text embedder creation configuration to internal configuration.
 * @param In The Unreal local text embedder creation configuration to convert
 * @param Out The internal local text embedder configuration to populate
 */
void INWORLDRUNTIME_API Convert(const FInworldLocalTextEmbedderCreationConfig& In, inworld::LocalTextEmbedderConfig& Out);

class RemoteTextEmbedderConfig;
/**
 * @brief Converts Unreal remote text embedder creation configuration to internal configuration.
 * @param In The Unreal remote text embedder creation configuration to convert
 * @param Out The internal remote text embedder configuration to populate
 */
void INWORLDRUNTIME_API Convert(const FInworldRemoteTextEmbedderCreationConfig& In, inworld::RemoteTextEmbedderConfig& Out);

}	 // namespace inworld
