#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "HyperTwistClassicCubeLeaderboardLibrary.generated.h"

USTRUCT(BlueprintType)
struct FHyperTwistClassicCubeLeaderboardEntry
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|ClassicCube|Leaderboard")
	FString PuzzleId = TEXT("cube/3x3x3");

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|ClassicCube|Leaderboard")
	int32 ScrambleLength = 0;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|ClassicCube|Leaderboard")
	int32 FinalTimeMs = 0;

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

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

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|ClassicCube|Leaderboard")
	FString ScrambleNotation;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|ClassicCube|Leaderboard")
	FString RecordedAtUtc;

	bool IsStructurallyValid() const
	{
		return !PuzzleId.IsEmpty()
			&& ScrambleLength >= 0
			&& FinalTimeMs > 0
			&& !RecordedAtUtc.IsEmpty();
	}
};

USTRUCT(BlueprintType)
struct FHyperTwistClassicCubeLeaderboardState
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|ClassicCube|Leaderboard")
	FString SchemaVersion = TEXT("ht-classic-cube-leaderboard/v1");

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|ClassicCube|Leaderboard")
	TArray<FHyperTwistClassicCubeLeaderboardEntry> Entries;

	bool IsStructurallyValid() const
	{
		if (SchemaVersion.IsEmpty())
		{
			return false;
		}

		for (const FHyperTwistClassicCubeLeaderboardEntry& Entry : Entries)
		{
			if (!Entry.IsStructurallyValid())
			{
				return false;
			}
		}

		return true;
	}
};

UCLASS()
class UNREALHYPERTWIST_API UHyperTwistClassicCubeLeaderboardLibrary : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()

public:
	UFUNCTION(BlueprintPure, Category = "HyperTwist|ClassicCube|Leaderboard")
	static FString GetDefaultLeaderboardPath();

	UFUNCTION(BlueprintPure, Category = "HyperTwist|ClassicCube|Leaderboard")
	static FString FormatBestTimeMs(int32 FinalTimeMs);

	UFUNCTION(BlueprintPure, Category = "HyperTwist|ClassicCube|Leaderboard")
	static FString ResolveLeaderboardPath(const FString& LeaderboardPath);

	UFUNCTION(BlueprintPure, Category = "HyperTwist|ClassicCube|Leaderboard")
	static FHyperTwistClassicCubeLeaderboardState NormalizeLeaderboardState(
		const FHyperTwistClassicCubeLeaderboardState& LeaderboardState
	);

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|ClassicCube|Leaderboard")
	static bool SaveLeaderboardStateToFile(
		const FHyperTwistClassicCubeLeaderboardState& LeaderboardState,
		const FString& LeaderboardPath,
		FString& OutResolvedPath
	);

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|ClassicCube|Leaderboard")
	static bool LoadLeaderboardStateFromFile(
		const FString& LeaderboardPath,
		FHyperTwistClassicCubeLeaderboardState& OutLeaderboardState,
		FString& OutResolvedPath
	);

	UFUNCTION(BlueprintPure, Category = "HyperTwist|ClassicCube|Leaderboard")
	static FHyperTwistClassicCubeLeaderboardState RecordBestTime(
		const FHyperTwistClassicCubeLeaderboardState& LeaderboardState,
		const FHyperTwistClassicCubeLeaderboardEntry& Entry
	);

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|ClassicCube|Leaderboard")
	static bool FindBestEntry(
		const FHyperTwistClassicCubeLeaderboardState& LeaderboardState,
		const FString& PuzzleId,
		int32 ScrambleLength,
		FHyperTwistClassicCubeLeaderboardEntry& OutEntry
	);

	UFUNCTION(BlueprintPure, Category = "HyperTwist|ClassicCube|Leaderboard")
	static FString BuildLeaderboardStatusLine(
		const FHyperTwistClassicCubeLeaderboardState& LeaderboardState,
		const FString& PuzzleId,
		int32 ScrambleLength
	);
};
