#pragma once

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

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

class UNREALHYPERTWIST_API IHyperTwistVisionClient
{
	GENERATED_BODY()

public:
	virtual bool OpenVisionSession(const FHyperTwistVisionSessionConfig& Config, FString& OutError) = 0;
	virtual FHyperTwistVisionPreviewResult SubmitVisionFrame(const FHyperTwistVisionFrameEnvelope& Frame) = 0;
	virtual FHyperTwistVisionCommitResult CommitVisionObservation(const FHyperTwistVisionCommitRequest& Request) = 0;
	virtual FHyperTwistVisionFinalizeResult FinalizeVisionSession(const FString& SessionId) = 0;
	virtual bool CloseVisionSession(const FString& SessionId, FString& OutError) = 0;
	virtual FHyperTwistVisionServiceHealth GetVisionServiceHealth() const = 0;
};

UCLASS(BlueprintType)
class UNREALHYPERTWIST_API UHyperTwistMockVisionClient : public UObject, public IHyperTwistVisionClient
{
	GENERATED_BODY()

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

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Recognition")
	virtual FHyperTwistVisionPreviewResult SubmitVisionFrame(const FHyperTwistVisionFrameEnvelope& Frame) override;

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Recognition")
	virtual FHyperTwistVisionCommitResult CommitVisionObservation(const FHyperTwistVisionCommitRequest& Request) override;

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Recognition")
	virtual FHyperTwistVisionFinalizeResult FinalizeVisionSession(const FString& SessionId) override;

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

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Recognition")
	virtual FHyperTwistVisionServiceHealth GetVisionServiceHealth() const override;

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

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

UCLASS(BlueprintType, Config = Game, DefaultConfig)
class UNREALHYPERTWIST_API UHyperTwistHttpVisionClient : public UObject, public IHyperTwistVisionClient
{
	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("/vision/session/open");

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Config, Category = "HyperTwist|Recognition")
	FString SubmitFramePath = TEXT("/vision/frame");

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Config, Category = "HyperTwist|Recognition")
	FString CommitObservationPath = TEXT("/vision/commit");

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Config, Category = "HyperTwist|Recognition")
	FString FinalizeSessionPath = TEXT("/vision/session/finalize");

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

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Config, Category = "HyperTwist|Recognition")
	FString HealthPath = TEXT("/vision/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 OpenVisionSession(const FHyperTwistVisionSessionConfig& Config, FString& OutError) override;

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Recognition")
	virtual FHyperTwistVisionPreviewResult SubmitVisionFrame(const FHyperTwistVisionFrameEnvelope& Frame) override;

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Recognition")
	virtual FHyperTwistVisionCommitResult CommitVisionObservation(const FHyperTwistVisionCommitRequest& Request) override;

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Recognition")
	virtual FHyperTwistVisionFinalizeResult FinalizeVisionSession(const FString& SessionId) override;

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

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Recognition")
	virtual FHyperTwistVisionServiceHealth GetVisionServiceHealth() const override;

private:
	mutable FString LastTransportError;
};
