#pragma once

#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "UObject/Object.h"
#include "HyperTwistRecognition/HyperTwistRecognitionTypes.h"
#include "HyperTwistSpeechClient.generated.h"

UINTERFACE(BlueprintType)
class UNREALHYPERTWIST_API UHyperTwistSpeechClient : public UInterface
{
	GENERATED_BODY()
};

class UNREALHYPERTWIST_API IHyperTwistSpeechClient
{
	GENERATED_BODY()

public:
	virtual bool OpenSpeechSession(const FHyperTwistSpeechSessionConfig& Config, FString& OutError) = 0;
	virtual FHyperTwistSpeechTranscriptResult TranscribeSpeechUtterance(const FHyperTwistSpeechUtteranceEnvelope& Utterance) = 0;
	virtual bool CloseSpeechSession(const FString& SessionId, FString& OutError) = 0;
	virtual FHyperTwistSpeechServiceHealth GetSpeechServiceHealth() const = 0;
};

UCLASS(BlueprintType)
class UNREALHYPERTWIST_API UHyperTwistMockSpeechClient : public UObject, public IHyperTwistSpeechClient
{
	GENERATED_BODY()

public:
	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Recognition")
	virtual bool OpenSpeechSession(const FHyperTwistSpeechSessionConfig& Config, FString& OutError) override;

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Recognition")
	virtual FHyperTwistSpeechTranscriptResult TranscribeSpeechUtterance(const FHyperTwistSpeechUtteranceEnvelope& Utterance) override;

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Recognition")
	virtual bool CloseSpeechSession(const FString& SessionId, FString& OutError) override;

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Recognition")
	virtual FHyperTwistSpeechServiceHealth GetSpeechServiceHealth() const override;

private:
	UPROPERTY()
	TMap<FString, FHyperTwistSpeechSessionConfig> SessionConfigs;

	UPROPERTY()
	TMap<FString, int32> SessionUtteranceCounts;
};

UCLASS(BlueprintType, Config = Game, DefaultConfig)
class UNREALHYPERTWIST_API UHyperTwistHttpSpeechClient : public UObject, public IHyperTwistSpeechClient
{
	GENERATED_BODY()

public:
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Config, Category = "HyperTwist|Recognition")
	FString ProviderLabel = TEXT("local-http-sidecar");

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Config, Category = "HyperTwist|Recognition")
	FString ServiceBaseUrl = TEXT("http://127.0.0.1:8766");

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Config, Category = "HyperTwist|Recognition")
	FString OpenSessionPath = TEXT("/speech/session/open");

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Config, Category = "HyperTwist|Recognition")
	FString TranscribeUtterancePath = TEXT("/speech/utterance");

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Config, Category = "HyperTwist|Recognition")
	FString CloseSessionPath = TEXT("/speech/session/close");

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Config, Category = "HyperTwist|Recognition")
	FString HealthPath = TEXT("/speech/health");

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Config, Category = "HyperTwist|Recognition")
	float RequestTimeoutSeconds = 5.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Config, Category = "HyperTwist|Recognition")
	FString AuthorizationToken;

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Recognition")
	virtual bool OpenSpeechSession(const FHyperTwistSpeechSessionConfig& Config, FString& OutError) override;

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Recognition")
	virtual FHyperTwistSpeechTranscriptResult TranscribeSpeechUtterance(const FHyperTwistSpeechUtteranceEnvelope& Utterance) override;

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Recognition")
	virtual bool CloseSpeechSession(const FString& SessionId, FString& OutError) override;

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Recognition")
	virtual FHyperTwistSpeechServiceHealth GetSpeechServiceHealth() const override;

private:
	UPROPERTY()
	TMap<FString, FHyperTwistSpeechSessionConfig> SessionConfigs;

	UPROPERTY()
	FHyperTwistSpeechSessionConfig LastRequestedSessionConfig;

	mutable FString LastTransportError;
};
