#pragma once

#include "CoreMinimal.h"
#include "HyperTwistCoreTypes.generated.h"

UENUM(BlueprintType)
enum class EHyperTwistPuzzleFamily : uint8
{
	ClassicCube UMETA(DisplayName = "Classic Cube"),
	Hypercube UMETA(DisplayName = "Hypercube"),
	Tiling UMETA(DisplayName = "Tiling"),
	Other UMETA(DisplayName = "Other")
};

UENUM(BlueprintType)
enum class EHyperTwistStateEncodingKind : uint8
{
	PieceOrbit UMETA(DisplayName = "Piece Orbit"),
	Facelet UMETA(DisplayName = "Facelet"),
	CellComplex UMETA(DisplayName = "Cell Complex"),
	FamilySpecific UMETA(DisplayName = "Family Specific")
};

UENUM(BlueprintType)
enum class EHyperTwistStateSource : uint8
{
	Runtime UMETA(DisplayName = "Runtime"),
	Recognition UMETA(DisplayName = "Recognition"),
	SmartDevice UMETA(DisplayName = "Smart Device"),
	Import UMETA(DisplayName = "Import"),
	ManualEntry UMETA(DisplayName = "Manual Entry")
};

UENUM(BlueprintType)
enum class EHyperTwistTransformKind : uint8
{
	SingleMove UMETA(DisplayName = "Single Move"),
	Algorithm UMETA(DisplayName = "Algorithm"),
	Rotation UMETA(DisplayName = "Rotation"),
	Slice UMETA(DisplayName = "Slice"),
	Composite UMETA(DisplayName = "Composite")
};

USTRUCT(BlueprintType)
struct FHyperTwistPuzzleDefinitionRef
{
	GENERATED_BODY()

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

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	EHyperTwistPuzzleFamily PuzzleFamily = EHyperTwistPuzzleFamily::ClassicCube;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	int32 Dimension = 3;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString DefinitionVersion = TEXT("2026.04");

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString NotationProfile = TEXT("classic-wca");

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	TArray<int32> SizeVector;

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

	bool IsStructurallyValid() const
	{
		return !PuzzleId.IsEmpty() && Dimension > 0 && !DefinitionVersion.IsEmpty() && !NotationProfile.IsEmpty();
	}
};

USTRUCT(BlueprintType)
struct FHyperTwistOrientationFrame
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString Reference = TEXT("canonical-default");
};

USTRUCT(BlueprintType)
struct FHyperTwistSerializedPayload
{
	GENERATED_BODY()

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

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

	bool IsStructurallyValid() const
	{
		return !EncodingProfile.IsEmpty();
	}
};

USTRUCT(BlueprintType)
struct FHyperTwistPuzzleState
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString SchemaVersion = TEXT("ht-puzzle-state/v1");

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

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	EHyperTwistStateEncodingKind StateEncodingKind = EHyperTwistStateEncodingKind::PieceOrbit;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FHyperTwistSerializedPayload StateEncoding;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FHyperTwistOrientationFrame OrientationFrame;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	bool bIsSolved = false;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	EHyperTwistStateSource Source = EHyperTwistStateSource::Runtime;

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

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

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

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

	bool IsStructurallyValid() const
	{
		return !SchemaVersion.IsEmpty() && Definition.IsStructurallyValid() && StateEncoding.IsStructurallyValid();
	}
};

USTRUCT(BlueprintType)
struct FHyperTwistTransformation
{
	GENERATED_BODY()

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

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	EHyperTwistTransformKind TransformKind = EHyperTwistTransformKind::SingleMove;

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

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FHyperTwistSerializedPayload TransformEncoding;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	bool bInvertible = true;

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

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	TArray<FString> NormalizationWarnings;

	bool IsStructurallyValid() const
	{
		return Definition.IsStructurallyValid() && !Notation.IsEmpty() && TransformEncoding.IsStructurallyValid();
	}
};

USTRUCT(BlueprintType)
struct FHyperTwistStateSnapshot
{
	GENERATED_BODY()

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

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FHyperTwistPuzzleState State;

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

	bool IsStructurallyValid() const
	{
		return !SnapshotId.IsEmpty() && State.IsStructurallyValid() && !DerivedHash.IsEmpty();
	}
};

USTRUCT(BlueprintType)
struct FHyperTwistPieceSetState
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	TArray<int32> Permutation;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	TArray<int32> Orientation;
};

USTRUCT(BlueprintType)
struct FHyperTwistClassicPieceOrbitState
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString EncodingProfile = TEXT("classic-piece-orbit-v1");

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FHyperTwistPieceSetState Corners;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FHyperTwistPieceSetState Edges;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FHyperTwistPieceSetState Centers;
};

USTRUCT(BlueprintType)
struct FHyperTwistClassicFaceletSnapshotState
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString EncodingProfile = TEXT("classic-facelet-snapshot-v1");

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	TArray<FString> U;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	TArray<FString> R;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	TArray<FString> F;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	TArray<FString> D;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	TArray<FString> L;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	TArray<FString> B;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	bool bPreviewState = true;
};

USTRUCT(BlueprintType)
struct FHyperTwistHypercubePieceMapState
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString EncodingProfile = TEXT("hypercube-piece-map-v1");

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	TArray<FString> Corners;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	TArray<FString> Edges;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	TArray<FString> Faces;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	TArray<FString> Cells;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString FrameProfile = TEXT("hypercube-canonical-v1");

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString TopologyVersion = TEXT("2x2x2x2/v1");
};

USTRUCT(BlueprintType)
struct FHyperTwistClassicTransformEncoding
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString EncodingProfile = TEXT("classic-transform-v1");

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	TArray<FString> MoveSequence;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString CachedFamily = TEXT("classic-cube");
};

USTRUCT(BlueprintType)
struct FHyperTwistHypercubeTransformEncoding
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	FString EncodingProfile = TEXT("hypercube-transform-v1");

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

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

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
	int32 TurnAmount = 1;
};
