// Copyright HyperTwist, Inc. All Rights Reserved.

#include "Misc/AutomationTest.h"

#include "HyperTwistBootstrap/HyperTwistContractLibrary.h"
#include "HyperTwistTraining/HyperTwistTrainingCatalogLibrary.h"
#include "HyperTwistTraining/HyperTwistTrainingLibrary.h"

#if WITH_AUTOMATION_TESTS

namespace HyperTwistHyperspeedcubePhase6RATestInternal
{
	FHyperTwistTrainingDeck MakeHypercubeDeck(const FString& PuzzleId)
	{
		FHyperTwistTrainingDeck Deck;
		Deck.DeckId = TEXT("phase6r-a/hypercube-catalog");
		Deck.Title = TEXT("Phase 6R-A Hyper Puzzle Catalog");
		Deck.DeliveryModes = {EHyperTwistTrainingDeliveryMode::Timer};

		FHyperTwistTrainingCase TrainingCase;
		TrainingCase.CaseId = TEXT("phase6r-a-case");
		TrainingCase.PuzzleId = PuzzleId;
		TrainingCase.PromptLabel = TEXT("Phase 6R-A Hyper Puzzle");
		TrainingCase.AllowedDeliveryModes = {EHyperTwistTrainingDeliveryMode::Timer};
		Deck.Cases = {TrainingCase};
		return Deck;
	}
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistHyperspeedcubePhase6RACatalogLookupTest,
	"HyperTwist.Permissive.Hyperspeedcube.Phase6R.A.CatalogLookup",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistHyperspeedcubePhase6RACatalogLookupTest::RunTest(const FString& Parameters)
{
	const FHyperTwistRetainedHyperPuzzleCatalog Catalog =
		UHyperTwistTrainingCatalogLibrary::MakeRetainedHyperPuzzleCatalog();

	TestTrue(TEXT("The retained hyper puzzle catalog must be structurally valid."), Catalog.IsStructurallyValid());
	TestTrue(TEXT("The retained hyper puzzle catalog must register multiple retained entries."), Catalog.Entries.Num() >= 5);

	FHyperTwistRetainedHyperPuzzleCatalogEntry VirtualEntry;
	TestTrue(
		TEXT("The catalog must resolve the virtual 3x3x3x3 alias."),
		UHyperTwistTrainingCatalogLibrary::TryGetRetainedHyperPuzzleCatalogEntry(TEXT("3x3x3x3"), VirtualEntry)
	);
	TestEqual(
		TEXT("The virtual 3x3x3x3 alias must map to the canonical retained puzzle id."),
		VirtualEntry.PuzzleId,
		TEXT("hypercube/3x3x3x3")
	);
	TestEqual(
		TEXT("The virtual 3x3x3x3 alias must resolve as a 4D hypercube."),
		VirtualEntry.Dimension,
		4
	);

	FHyperTwistRetainedHyperPuzzleCatalogEntry PhysicalEntry;
	TestTrue(
		TEXT("The catalog must resolve the physical 2x2x2x2 alias."),
		UHyperTwistTrainingCatalogLibrary::TryGetRetainedHyperPuzzleCatalogEntry(TEXT("phys_2x2x2x2"), PhysicalEntry)
	);
	TestEqual(
		TEXT("The physical 2x2x2x2 alias must map to the canonical retained puzzle id."),
		PhysicalEntry.PuzzleId,
		TEXT("hypercube/2x2x2x2/physical")
	);
	TestEqual(
		TEXT("The physical 2x2x2x2 entry must preserve the physical variant label."),
		PhysicalEntry.Variant,
		TEXT("physical")
	);

	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistHyperspeedcubePhase6RATrainingRunDefinitionTest,
	"HyperTwist.Permissive.Hyperspeedcube.Phase6R.A.TrainingRunDefinition",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistHyperspeedcubePhase6RATrainingRunDefinitionTest::RunTest(const FString& Parameters)
{
	const FHyperTwistTrainingRunState RunState = UHyperTwistTrainingLibrary::StartTrainingRun(
		HyperTwistHyperspeedcubePhase6RATestInternal::MakeHypercubeDeck(TEXT("3x3x3x3")),
		TEXT("phase6r-a-user"),
		TEXT("phase6r-a-session"),
		EHyperTwistTrainingDeliveryMode::Timer
	);

	TestTrue(TEXT("The bounded 6R-A deck must start a structurally valid run."), RunState.IsStructurallyValid());
	TestEqual(
		TEXT("The replay packet must promote the virtual 3x3x3x3 alias to the canonical retained puzzle id."),
		RunState.ReplayPacket.PuzzleDefinition.PuzzleId,
		TEXT("hypercube/3x3x3x3")
	);
	TestEqual(
		TEXT("The replay packet must retain the retained hyper notation profile."),
		RunState.ReplayPacket.PuzzleDefinition.NotationProfile,
		TEXT("hyper-4d")
	);
	TestEqual(
		TEXT("The replay packet must retain the 4D hypercube family."),
		RunState.ReplayPacket.PuzzleDefinition.PuzzleFamily,
		EHyperTwistPuzzleFamily::Hypercube
	);
	TestEqual(
		TEXT("The replay packet must retain the 4D hypercube dimension."),
		RunState.ReplayPacket.PuzzleDefinition.Dimension,
		4
	);
	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistHyperspeedcubePhase6RASampleDefinitionTest,
	"HyperTwist.Permissive.Hyperspeedcube.Phase6R.A.SampleDefinition",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistHyperspeedcubePhase6RASampleDefinitionTest::RunTest(const FString& Parameters)
{
	const FHyperTwistPuzzleDefinitionRef Definition =
		UHyperTwistContractLibrary::MakeSampleHyperPuzzleDefinition();

	TestEqual(
		TEXT("The sample hyper definition must resolve through the retained hyper puzzle catalog."),
		Definition.PuzzleId,
		TEXT("hypercube/2x2x2x2")
	);
	TestEqual(TEXT("The sample hyper definition must remain 4D."), Definition.Dimension, 4);
	TestEqual(TEXT("The sample hyper definition must retain the hyper notation profile."), Definition.NotationProfile, TEXT("hyper-4d"));
	return true;
}

#endif
