#pragma once

#include "CoreMinimal.h"
#include "HyperTwistCore/HyperTwistCoreTypes.h"
#include "HyperTwistReplayTypes.generated.h"

UENUM(BlueprintType)
enum class EHyperTwistCaptureMode : uint8
{
	Manual UMETA(DisplayName = "Manual"),
	Runtime UMETA(DisplayName = "Runtime"),
	Recognition UMETA(DisplayName = "Recognition"),
	SmartDevice UMETA(DisplayName = "Smart Device"),
	Imported UMETA(DisplayName = "Imported")
};

UENUM(BlueprintType)
enum class EHyperTwistReplayEventType : uint8
{
	InspectionStart UMETA(DisplayName = "Inspection Start"),
	InspectionEnd UMETA(DisplayName = "Inspection End"),
	TimerStart UMETA(DisplayName = "Timer Start"),
	Move UMETA(DisplayName = "Move"),
	Rotation UMETA(DisplayName = "Rotation"),
	StateSnapshot UMETA(DisplayName = "State Snapshot"),
	PhaseMark UMETA(DisplayName = "Phase Mark"),
	DeviceSync UMETA(DisplayName = "Device Sync"),
	RecognitionPreview UMETA(DisplayName = "Recognition Preview"),
	RecognitionScan UMETA(DisplayName = "Recognition Scan"),
	RecognitionCommit UMETA(DisplayName = "Recognition Commit"),
	RecognitionCorrection UMETA(DisplayName = "Recognition Correction"),
	Pause UMETA(DisplayName = "Pause"),
	Resume UMETA(DisplayName = "Resume"),
	Annotation UMETA(DisplayName = "Annotation"),
	SolveEnd UMETA(DisplayName = "Solve End")
};

USTRUCT(BlueprintType)
struct FHyperTwistPhaseTiming
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString PhaseKind;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	int32 StartedAtMs = 0;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	int32 EndedAtMs = 0;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	int32 DurationMs = 0;
};

USTRUCT(BlueprintType)
struct FHyperTwistDerivedReplaySummary
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	int32 TotalTimeMs = 0;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	int32 InspectionTimeMs = 0;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	TArray<FHyperTwistPhaseTiming> PhaseTimings;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	int32 MoveCount = 0;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	float TPS = 0.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	int32 RecognizedSegments = 0;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	float ConfidenceRollup = -1.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString Result;
};

USTRUCT(BlueprintType)
struct FHyperTwistReplayEvent
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString EventId;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	int32 Sequence = 0;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	int32 TimeMs = 0;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	EHyperTwistReplayEventType EventType = EHyperTwistReplayEventType::Annotation;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString PayloadJson;

	bool IsStructurallyValid() const
	{
		return !EventId.IsEmpty() && Sequence > 0 && TimeMs >= 0;
	}
};

USTRUCT(BlueprintType)
struct FHyperTwistReplayPacket
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString PacketVersion = TEXT("ht-replay/v1");

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString ReplayId;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FHyperTwistPuzzleDefinitionRef PuzzleDefinition;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	EHyperTwistCaptureMode CaptureMode = EHyperTwistCaptureMode::Runtime;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString SessionId;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString StartedAtUtc;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString EndedAtUtc;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	TArray<FHyperTwistReplayEvent> Events;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString SourceImportFormat;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString AnnotationsJson;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FHyperTwistDerivedReplaySummary DerivedSummary;

	bool IsStructurallyValid() const
	{
		if (ReplayId.IsEmpty() || SessionId.IsEmpty() || !PuzzleDefinition.IsStructurallyValid() || Events.Num() == 0)
		{
			return false;
		}

		int32 PreviousSequence = 0;
		for (const FHyperTwistReplayEvent& Event : Events)
		{
			if (!Event.IsStructurallyValid() || Event.Sequence <= PreviousSequence)
			{
				return false;
			}

			PreviousSequence = Event.Sequence;
		}

		return true;
	}
};

USTRUCT(BlueprintType)
struct FHyperTwistReplayMovePayload
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString Notation;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString TransformationRef;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString Source;
};

USTRUCT(BlueprintType)
struct FHyperTwistReplayPhaseMarkPayload
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString PhaseId;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString PhaseKind;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString PhaseSource;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString PhaseAction;
};

USTRUCT(BlueprintType)
struct FHyperTwistReplayRecognitionPayload
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FHyperTwistStateSnapshot Snapshot;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	float Confidence = 0.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString ScanStage;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString CommittedFaceOrStage;
};

USTRUCT(BlueprintType)
struct FHyperTwistReplayDeviceSyncPayload
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString DeviceKind;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString DeviceEvent;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString DevicePayloadJson;
};
