// Copyright HyperTwist, Inc. All Rights Reserved.

#include "Engine/GameInstance.h"
#include "Engine/Level.h"
#include "Engine/World.h"
#include "GameFramework/PlayerStart.h"
#include "GameFramework/WorldSettings.h"
#include "Misc/FileHelper.h"
#include "Misc/AutomationTest.h"
#include "Misc/PackageName.h"
#include "Misc/Paths.h"
#include "Misc/SecureHash.h"
#include "Serialization/JsonReader.h"
#include "Serialization/JsonSerializer.h"

#include "HyperTwistSimulation/HyperTwistSimulationLibrary.h"
#include "HyperTwistTraining/HyperTwistHigherDimensionalTrainingGameMode.h"
#include "HyperTwistTraining/HyperTwistHigherDimensionalTrainingShellActor.h"
#include "HyperTwistTraining/HyperTwistTrainingLibrary.h"
#include "HyperTwistTraining/HyperTwistTrainingRuntimeLibrary.h"
#include "HyperTwistTraining/HyperTwistTrainingSubsystem.h"

#if WITH_AUTOMATION_TESTS

namespace HyperTwistHigherDimensionalPhase6CTestInternal
{
	struct FPhase6CDedicatedMapManifestEntry
	{
		FString MapKind;
		FString FamilyKey;
		FString MapAssetPath;
		FString MapFileRelativePath;
		FString MapHashMd5;
		FString TrainingShellId;
		FString ActivationProfileId;
		FString HostSurfaceId;
		FString LaunchSurfaceId;
		FString ViewContextSurfaceId;
		FString SessionSurfaceId;
		FString InteractiveSceneSurfaceId;
		FString SceneContextId;
		FString PuzzleId;
		FString RuntimeModeId;
		FString ProjectionProfileId;
		FString PrimaryPersistenceBoundaryId;
		FString AuthoredViaGameModeClassPath;
		FString RuntimePresentationClassPath;
		FString PresentationEnvironmentOwnership;
		int32 CanonicalRenderableElementCount = 0;
	};

	struct FPhase6CDedicatedMapManifest
	{
		FString ManifestId;
		FString ManifestVersion;
		FString ClassicReferenceMapHashMd5;
		TArray<FPhase6CDedicatedMapManifestEntry> Entries;
	};

	FHyperTwistTrainingDeck MakeDeck(const FString& DeckId, const FString& PuzzleId)
	{
		FHyperTwistTrainingDeck Deck;
		Deck.DeckId = DeckId;
		Deck.Title = DeckId;
		Deck.DeliveryModes = {EHyperTwistTrainingDeliveryMode::VirtualCube};

		FHyperTwistTrainingCase TrainingCase;
		TrainingCase.CaseId = FString::Printf(TEXT("%s/case"), *DeckId);
		TrainingCase.PuzzleId = PuzzleId;
		TrainingCase.PromptLabel = PuzzleId;
		TrainingCase.AllowedDeliveryModes = {EHyperTwistTrainingDeliveryMode::VirtualCube};
		Deck.Cases = {TrainingCase};
		return Deck;
	}

	FHyperTwistTrainingImportedGeneratedModeLaunchRequest MakeGeneratedModeLaunchRequest(
		const FString& DeckId,
		const FString& TrainingSessionId,
		const FString& PuzzleId,
		const FString& RuntimeModeId
	)
	{
		FHyperTwistTrainingImportedRuntimeSelectorChoice SelectorChoice;
		SelectorChoice.SelectorId = TEXT("family-mode");
		SelectorChoice.SelectorBinding = TEXT("family-mode");
		SelectorChoice.SelectedValue = TEXT("order3");
		SelectorChoice.DisplayValue = TEXT("Order 3");

		FHyperTwistTrainingImportedGeneratedModeLaunchConfig LaunchConfig;
		LaunchConfig.DeckId = DeckId;
		LaunchConfig.UserId = TEXT("phase6c-user");
		LaunchConfig.TrainingSessionId = TrainingSessionId;
		LaunchConfig.DeliveryMode = EHyperTwistTrainingDeliveryMode::VirtualCube;
		LaunchConfig.PuzzleId = PuzzleId;
		LaunchConfig.SurfaceId = TEXT("phase6c/imported-runtime-surface");
		LaunchConfig.SurfaceLabel = TEXT("Phase 6C Imported Runtime Surface");
		LaunchConfig.RuntimeModeId = RuntimeModeId;
		LaunchConfig.GeneratorType = TEXT("cleanroom-generated-mode");
		LaunchConfig.SelectorChoices = {SelectorChoice};
		LaunchConfig.OriginPaths = {TEXT("phase6c/generated-mode")};
		LaunchConfig.Notes = TEXT("Phase 6C contract test launch request.");

		FHyperTwistTrainingImportedGeneratedModeLaunchRequest Request;
		Request.RequestId = FString::Printf(TEXT("%s/request"), *DeckId);
		Request.RequestedAtUtc = TEXT("2026-06-13T00:00:00Z");
		Request.RequestSource = TEXT("phase6c-contract-test");
		Request.LaunchConfig = LaunchConfig;
		return Request;
	}

	UHyperTwistTrainingSubsystem* MakeTrainingSubsystem()
	{
		UGameInstance* GameInstance = NewObject<UGameInstance>();
		if (GameInstance == nullptr)
		{
			return nullptr;
		}

		UHyperTwistTrainingSubsystem* TrainingSubsystem =
			NewObject<UHyperTwistTrainingSubsystem>(GameInstance);
		if (TrainingSubsystem == nullptr)
		{
			return nullptr;
		}

		// Keep Phase 6C automation on the owned clean-room lane instead of
		// inheriting host-local speech or vision sidecar config.
		TrainingSubsystem->SetRecognitionClientKindForAutomation(TEXT("mock"));
		TrainingSubsystem->SetCompanionSpeechClientKindForAutomation(TEXT("mock"));
		TrainingSubsystem->RefreshCompanionSpeechServiceHealthForAutomation();
		return TrainingSubsystem;
	}

	FString GetManifestPath()
	{
		return FPaths::ConvertRelativePathToFull(FPaths::Combine(
			FPaths::ProjectDir(),
			TEXT("../docs/generated/higher_dimensional_training_maps/phase6c_dedicated_family_map_manifest.json")));
	}

	FString GetMapFilePathFromRelativePath(const FString& RelativePath)
	{
		return FPaths::ConvertRelativePathToFull(FPaths::Combine(
			FPaths::ProjectDir(),
			TEXT("../"),
			RelativePath));
	}

	FString ComputeFileMd5(const FString& FilePath)
	{
		if (!FPaths::FileExists(FilePath))
		{
			return FString();
		}

		TArray<uint8> FileBytes;
		if (!FFileHelper::LoadFileToArray(FileBytes, *FilePath))
		{
			return FString();
		}

		FMD5 Md5;
		if (FileBytes.Num() > 0)
		{
			Md5.Update(FileBytes.GetData(), FileBytes.Num());
		}

		uint8 Digest[16];
		Md5.Final(Digest);
		return BytesToHex(Digest, UE_ARRAY_COUNT(Digest)).ToLower();
	}

	bool ParseManifestEntry(
		const TSharedPtr<FJsonObject>& JsonObject,
		FPhase6CDedicatedMapManifestEntry& OutEntry
	)
	{
			double CanonicalRenderableElementCount = 0.0;
			const bool bParsed = JsonObject.IsValid()
				&& JsonObject->TryGetStringField(TEXT("mapKind"), OutEntry.MapKind)
			&& JsonObject->TryGetStringField(TEXT("familyKey"), OutEntry.FamilyKey)
			&& JsonObject->TryGetStringField(TEXT("mapAssetPath"), OutEntry.MapAssetPath)
			&& JsonObject->TryGetStringField(TEXT("mapFileRelativePath"), OutEntry.MapFileRelativePath)
			&& JsonObject->TryGetStringField(TEXT("mapHashMd5"), OutEntry.MapHashMd5)
			&& JsonObject->TryGetStringField(TEXT("trainingShellId"), OutEntry.TrainingShellId)
			&& JsonObject->TryGetStringField(TEXT("activationProfileId"), OutEntry.ActivationProfileId)
			&& JsonObject->TryGetStringField(TEXT("hostSurfaceId"), OutEntry.HostSurfaceId)
			&& JsonObject->TryGetStringField(TEXT("launchSurfaceId"), OutEntry.LaunchSurfaceId)
			&& JsonObject->TryGetStringField(TEXT("viewContextSurfaceId"), OutEntry.ViewContextSurfaceId)
			&& JsonObject->TryGetStringField(TEXT("sessionSurfaceId"), OutEntry.SessionSurfaceId)
			&& JsonObject->TryGetStringField(TEXT("interactiveSceneSurfaceId"), OutEntry.InteractiveSceneSurfaceId)
			&& JsonObject->TryGetStringField(TEXT("sceneContextId"), OutEntry.SceneContextId)
			&& JsonObject->TryGetStringField(TEXT("puzzleId"), OutEntry.PuzzleId)
				&& JsonObject->TryGetStringField(TEXT("runtimeModeId"), OutEntry.RuntimeModeId)
				&& JsonObject->TryGetStringField(TEXT("projectionProfileId"), OutEntry.ProjectionProfileId)
				&& JsonObject->TryGetStringField(TEXT("primaryPersistenceBoundaryId"), OutEntry.PrimaryPersistenceBoundaryId)
				&& JsonObject->TryGetStringField(TEXT("authoredViaGameModeClassPath"), OutEntry.AuthoredViaGameModeClassPath)
				&& JsonObject->TryGetStringField(TEXT("runtimePresentationClassPath"), OutEntry.RuntimePresentationClassPath)
				&& JsonObject->TryGetStringField(TEXT("presentationEnvironmentOwnership"), OutEntry.PresentationEnvironmentOwnership)
				&& JsonObject->TryGetNumberField(TEXT("canonicalRenderableElementCount"), CanonicalRenderableElementCount);
			if (bParsed)
			{
				OutEntry.CanonicalRenderableElementCount = static_cast<int32>(CanonicalRenderableElementCount);
			}
			return bParsed;
	}

	bool TryLoadDedicatedMapManifest(FPhase6CDedicatedMapManifest& OutManifest)
	{
		const FString ManifestPath = GetManifestPath();
		FString Json;
		if (!FFileHelper::LoadFileToString(Json, *ManifestPath))
		{
			return false;
		}

		TSharedPtr<FJsonObject> RootObject;
		if (!FJsonSerializer::Deserialize(TJsonReaderFactory<>::Create(Json), RootObject)
			|| !RootObject.IsValid())
		{
			return false;
		}

		const TArray<TSharedPtr<FJsonValue>>* EntryValues = nullptr;
		if (!RootObject->TryGetStringField(TEXT("manifestId"), OutManifest.ManifestId)
			|| !RootObject->TryGetStringField(TEXT("manifestVersion"), OutManifest.ManifestVersion)
			|| !RootObject->TryGetStringField(
				TEXT("classicReferenceMapHashMd5"),
				OutManifest.ClassicReferenceMapHashMd5)
			|| !RootObject->TryGetArrayField(TEXT("entries"), EntryValues)
			|| EntryValues == nullptr)
		{
			return false;
		}

		OutManifest.Entries.Reset();
		for (const TSharedPtr<FJsonValue>& EntryValue : *EntryValues)
		{
			const TSharedPtr<FJsonObject> EntryObject = EntryValue.IsValid()
				? EntryValue->AsObject()
				: nullptr;
			FPhase6CDedicatedMapManifestEntry Entry;
			if (!ParseManifestEntry(EntryObject, Entry))
			{
				return false;
			}

			OutManifest.Entries.Add(Entry);
		}

		return true;
	}

	const FPhase6CDedicatedMapManifestEntry* FindManifestEntryByFamilyKey(
		const FPhase6CDedicatedMapManifest& Manifest,
		const FString& FamilyKey
	)
	{
		for (const FPhase6CDedicatedMapManifestEntry& Entry : Manifest.Entries)
		{
			if (Entry.FamilyKey.Equals(FamilyKey, ESearchCase::IgnoreCase))
			{
				return &Entry;
			}
		}

		return nullptr;
	}

	FString BuildMapObjectPath(const FString& MapAssetPath)
	{
		if (MapAssetPath.IsEmpty())
		{
			return FString();
		}

		const FString MapName = FPackageName::GetShortName(MapAssetPath);
		return FString::Printf(TEXT("%s.%s"), *MapAssetPath, *MapName);
	}

	UWorld* LoadDedicatedMapWorld(const FString& MapAssetPath)
	{
		const FString MapObjectPath = BuildMapObjectPath(MapAssetPath);
		if (MapObjectPath.IsEmpty())
		{
			return nullptr;
		}

		return LoadObject<UWorld>(nullptr, *MapObjectPath);
	}

	template <typename ActorType>
	int32 CountActorsOfClass(UWorld* World)
	{
		if (World == nullptr || World->PersistentLevel == nullptr)
		{
			return 0;
		}

		int32 Count = 0;
		for (AActor* Actor : World->PersistentLevel->Actors)
		{
			if (Cast<ActorType>(Actor) != nullptr)
			{
				++Count;
			}
		}

		return Count;
	}

	template <typename ActorType>
	ActorType* FindActorOfClass(UWorld* World)
	{
		if (World == nullptr || World->PersistentLevel == nullptr)
		{
			return nullptr;
		}

		for (AActor* Actor : World->PersistentLevel->Actors)
		{
			if (ActorType* TypedActor = Cast<ActorType>(Actor))
			{
				return TypedActor;
			}
		}

		return nullptr;
	}
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistHigherDimensionalPhase6CActivationCatalogTest,
	"HyperTwist.FirstParty.HigherDimensional.Phase6C.ActivationCatalog",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistHigherDimensionalPhase6CActivationCatalogTest::RunTest(const FString& Parameters)
{
	const FHyperTwistTrainingHigherDimensionalRuntimeActivationCatalog Catalog =
		UHyperTwistTrainingRuntimeLibrary::GetBundledHigherDimensionalRuntimeActivationCatalog();

	TestTrue(TEXT("The Phase 6C higher-dimensional activation catalog must be structurally valid."), Catalog.IsStructurallyValid());
	TestEqual(TEXT("The Phase 6C higher-dimensional activation catalog must expose both retained family activations."), Catalog.Profiles.Num(), 2);
	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistHigherDimensionalPhase6CHostCatalogTest,
	"HyperTwist.FirstParty.HigherDimensional.Phase6C.HostCatalog",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistHigherDimensionalPhase6CHostCatalogTest::RunTest(const FString& Parameters)
{
	const FHyperTwistTrainingHigherDimensionalRuntimeHostCatalog Catalog =
		UHyperTwistTrainingRuntimeLibrary::GetBundledHigherDimensionalRuntimeHostCatalog();

	TestTrue(
		TEXT("The Phase 6C higher-dimensional host catalog must be structurally valid."),
		Catalog.IsStructurallyValid()
	);
	TestEqual(
		TEXT("The Phase 6C higher-dimensional host catalog must expose both retained family host surfaces."),
		Catalog.HostSurfaces.Num(),
		2
	);

	FHyperTwistTrainingHigherDimensionalRuntimeHostSurface Magic120CellHostSurface;
	TestTrue(
		TEXT("The Magic120Cell host surface must resolve from the bundled catalog."),
		UHyperTwistTrainingRuntimeLibrary::TryGetBundledHigherDimensionalRuntimeHostSurfaceByActivationProfileId(
			TEXT("magic120cell-cleanroom-runtime-activation"),
			Magic120CellHostSurface
		)
	);
	TestEqual(
		TEXT("The Magic120Cell host surface must preserve the preferred dedicated family map target."),
		Magic120CellHostSurface.PreferredHostMapPath,
		TEXT("/Game/HyperTwistTraining/Maps/L_HyperTwist_Magic120CellTraining")
	);
	TestEqual(
		TEXT("The Magic120Cell host surface must now resolve to the dedicated effective host."),
		Magic120CellHostSurface.EffectiveHostMapPath,
		TEXT("/Game/HyperTwistTraining/Maps/L_HyperTwist_Magic120CellTraining")
	);
	TestTrue(
		TEXT("The Magic120Cell host surface must now claim the dedicated host map is authored."),
		Magic120CellHostSurface.bDedicatedFamilyHostMapAuthored
	);
	TestFalse(
		TEXT("The Magic120Cell host surface must no longer depend on the shared-map fallback posture."),
		Magic120CellHostSurface.bUsesSharedTrainingMapFallback
	);
	TestTrue(
		TEXT("The Magic120Cell dedicated host map asset must exist."),
		FPackageName::DoesPackageExist(TEXT("/Game/HyperTwistTraining/Maps/L_HyperTwist_Magic120CellTraining"))
	);

	FHyperTwistTrainingHigherDimensionalRuntimeHostSurface MagicCube5DHostSurface;
	TestTrue(
		TEXT("The MagicCube5D host surface must resolve from the bundled catalog."),
		UHyperTwistTrainingRuntimeLibrary::TryGetBundledHigherDimensionalRuntimeHostSurfaceByPuzzleId(
			TEXT("hypercube/magiccube5d/order3"),
			MagicCube5DHostSurface
		)
	);
	TestEqual(
		TEXT("The MagicCube5D host surface must preserve the preferred dedicated family route id."),
		MagicCube5DHostSurface.PreferredHostMapRouteId,
		TEXT("phase6c/magiccube5d/dedicated-training-map-host")
	);
	TestTrue(
		TEXT("The MagicCube5D host surface must carry dedicated-host effective tags."),
		MagicCube5DHostSurface.HostTags.Contains(TEXT("effective-host:dedicated-family-map"))
	);
	TestTrue(
		TEXT("The MagicCube5D host surface must now claim the dedicated host map is authored."),
		MagicCube5DHostSurface.bDedicatedFamilyHostMapAuthored
	);
	TestFalse(
		TEXT("The MagicCube5D host surface must no longer depend on the shared-map fallback posture."),
		MagicCube5DHostSurface.bUsesSharedTrainingMapFallback
	);
	TestTrue(
		TEXT("The MagicCube5D dedicated host map asset must exist."),
		FPackageName::DoesPackageExist(TEXT("/Game/HyperTwistTraining/Maps/L_HyperTwist_MagicCube5DTraining"))
	);
	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistHigherDimensionalPhase6CDedicatedMapAuthoringManifestTest,
	"HyperTwist.FirstParty.HigherDimensional.Phase6C.DedicatedMapAuthoringManifest",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistHigherDimensionalPhase6CDedicatedMapAuthoringManifestTest::RunTest(
	const FString& Parameters)
{
	using namespace HyperTwistHigherDimensionalPhase6CTestInternal;

	FPhase6CDedicatedMapManifest Manifest;
	TestTrue(
		TEXT("The Phase 6C dedicated-family map authoring manifest must load."),
		TryLoadDedicatedMapManifest(Manifest)
	);
	if (Manifest.Entries.Num() == 0)
	{
		return false;
	}

	TestEqual(
		TEXT("The dedicated-family map authoring manifest id must stay stable."),
		Manifest.ManifestId,
		TEXT("phase6c/dedicated-family-training-map-authoring")
	);
	TestEqual(
		TEXT("The dedicated-family map authoring manifest must expose both authored family maps."),
		Manifest.Entries.Num(),
		2
	);

	const FString ClassicMapFilePath = GetMapFilePathFromRelativePath(
		TEXT("UnrealHyperTwist/Content/HyperTwistTraining/Maps/L_HyperTwist_ClassicTraining.umap"));
	const FString ClassicMapHashMd5 = ComputeFileMd5(ClassicMapFilePath);
	TestTrue(
		TEXT("The classic reference training map file must exist for dedicated-map differentiation checks."),
		!ClassicMapHashMd5.IsEmpty()
	);
	TestEqual(
		TEXT("The dedicated-family map manifest must track the current classic reference hash."),
		Manifest.ClassicReferenceMapHashMd5,
		ClassicMapHashMd5
	);

	const FPhase6CDedicatedMapManifestEntry* Magic120CellEntry =
		FindManifestEntryByFamilyKey(Manifest, TEXT("magic120cell"));
	const FPhase6CDedicatedMapManifestEntry* MagicCube5DEntry =
		FindManifestEntryByFamilyKey(Manifest, TEXT("magiccube5d"));
	TestNotNull(
		TEXT("The dedicated-family map manifest must contain the Magic120Cell authored entry."),
		Magic120CellEntry
	);
	TestNotNull(
		TEXT("The dedicated-family map manifest must contain the MagicCube5D authored entry."),
		MagicCube5DEntry
	);
	if (Magic120CellEntry == nullptr || MagicCube5DEntry == nullptr)
	{
		return false;
	}

	const FString Magic120CellMapFilePath = GetMapFilePathFromRelativePath(
		Magic120CellEntry->MapFileRelativePath);
	const FString MagicCube5DMapFilePath = GetMapFilePathFromRelativePath(
		MagicCube5DEntry->MapFileRelativePath);
	const FString Magic120CellMapHashMd5 = ComputeFileMd5(Magic120CellMapFilePath);
	const FString MagicCube5DMapHashMd5 = ComputeFileMd5(MagicCube5DMapFilePath);
	TestTrue(
		TEXT("The Magic120Cell dedicated-family map file must exist."),
		!Magic120CellMapHashMd5.IsEmpty()
	);
	TestTrue(
		TEXT("The MagicCube5D dedicated-family map file must exist."),
		!MagicCube5DMapHashMd5.IsEmpty()
	);
	TestEqual(
		TEXT("The Magic120Cell dedicated-family map hash must match the manifest."),
		Magic120CellEntry->MapHashMd5,
		Magic120CellMapHashMd5
	);
	TestEqual(
		TEXT("The MagicCube5D dedicated-family map hash must match the manifest."),
		MagicCube5DEntry->MapHashMd5,
		MagicCube5DMapHashMd5
	);
	TestNotEqual(
		TEXT("The Magic120Cell dedicated-family map must no longer be byte-identical to the classic training map."),
		Magic120CellMapHashMd5,
		ClassicMapHashMd5
	);
	TestNotEqual(
		TEXT("The MagicCube5D dedicated-family map must no longer be byte-identical to the classic training map."),
		MagicCube5DMapHashMd5,
		ClassicMapHashMd5
	);
	TestNotEqual(
		TEXT("The two dedicated-family maps must no longer be byte-identical to each other."),
		Magic120CellMapHashMd5,
		MagicCube5DMapHashMd5
	);

	FHyperTwistTrainingHigherDimensionalRuntimeHostSurface Magic120CellHostSurface;
	TestTrue(
		TEXT("The Magic120Cell host surface must resolve for map-manifest reconciliation."),
		UHyperTwistTrainingRuntimeLibrary::TryGetBundledHigherDimensionalRuntimeHostSurfaceByActivationProfileId(
			Magic120CellEntry->ActivationProfileId,
			Magic120CellHostSurface
		)
	);
	TestEqual(
		TEXT("The Magic120Cell manifest must stay aligned with the host-surface map asset path."),
		Magic120CellEntry->MapAssetPath,
		Magic120CellHostSurface.EffectiveHostMapPath
	);
	TestEqual(
		TEXT("The Magic120Cell manifest must stay aligned with the host-surface id."),
		Magic120CellEntry->HostSurfaceId,
		Magic120CellHostSurface.HostSurfaceId
	);

	FHyperTwistTrainingHigherDimensionalRuntimeLaunchSurface Magic120CellLaunchSurface;
	TestTrue(
		TEXT("The Magic120Cell launch surface must resolve for map-manifest reconciliation."),
		UHyperTwistTrainingRuntimeLibrary::TryGetBundledHigherDimensionalRuntimeLaunchSurfaceByActivationProfileId(
			Magic120CellEntry->ActivationProfileId,
			Magic120CellLaunchSurface
		)
	);
	TestEqual(
		TEXT("The Magic120Cell manifest must stay aligned with the launch-surface id."),
		Magic120CellEntry->LaunchSurfaceId,
		Magic120CellLaunchSurface.LaunchSurfaceId
	);
	TestEqual(
		TEXT("The Magic120Cell manifest must stay aligned with the launch-surface persistence boundary."),
		Magic120CellEntry->PrimaryPersistenceBoundaryId,
		Magic120CellLaunchSurface.PrimaryPersistenceBoundaryId
	);

	FHyperTwistTrainingHigherDimensionalRuntimeViewContextSurface Magic120CellViewContextSurface;
	TestTrue(
		TEXT("The Magic120Cell view-context surface must resolve for map-manifest reconciliation."),
		UHyperTwistTrainingRuntimeLibrary::TryGetBundledHigherDimensionalRuntimeViewContextSurfaceByActivationProfileId(
			Magic120CellEntry->ActivationProfileId,
			Magic120CellViewContextSurface
		)
	);
	TestEqual(
		TEXT("The Magic120Cell manifest must stay aligned with the view-context surface id."),
		Magic120CellEntry->ViewContextSurfaceId,
		Magic120CellViewContextSurface.ViewContextSurfaceId
	);

	FHyperTwistTrainingHigherDimensionalRuntimeSessionSurface Magic120CellSessionSurface;
	TestTrue(
		TEXT("The Magic120Cell session surface must resolve for map-manifest reconciliation."),
		UHyperTwistTrainingRuntimeLibrary::TryGetBundledHigherDimensionalRuntimeSessionSurfaceByActivationProfileId(
			Magic120CellEntry->ActivationProfileId,
			Magic120CellSessionSurface
		)
	);
	TestEqual(
		TEXT("The Magic120Cell manifest must stay aligned with the session surface id."),
		Magic120CellEntry->SessionSurfaceId,
		Magic120CellSessionSurface.SessionSurfaceId
	);

	FHyperTwistTrainingHigherDimensionalInteractiveSceneSurface Magic120CellSceneSurface;
	TestTrue(
		TEXT("The Magic120Cell interactive scene surface must resolve for map-manifest reconciliation."),
		UHyperTwistTrainingRuntimeLibrary::TryGetBundledHigherDimensionalInteractiveSceneSurfaceByActivationProfileId(
			Magic120CellEntry->ActivationProfileId,
			Magic120CellSceneSurface
		)
	);
	TestEqual(
		TEXT("The Magic120Cell manifest must stay aligned with the interactive-scene surface id."),
		Magic120CellEntry->InteractiveSceneSurfaceId,
		Magic120CellSceneSurface.SceneSurfaceId
	);
	TestEqual(
		TEXT("The Magic120Cell manifest must stay aligned with the scene-context id."),
		Magic120CellEntry->SceneContextId,
		Magic120CellSceneSurface.SceneContext.SceneContextId
	);
	TestEqual(
		TEXT("The Magic120Cell manifest must stay aligned with the interactive-scene projection profile."),
		Magic120CellEntry->ProjectionProfileId,
		Magic120CellSceneSurface.SceneContext.ProjectionSettings.ProjectionProfile
	);

	FHyperTwistTrainingHigherDimensionalRuntimeHostSurface MagicCube5DHostSurface;
	TestTrue(
		TEXT("The MagicCube5D host surface must resolve for map-manifest reconciliation."),
		UHyperTwistTrainingRuntimeLibrary::TryGetBundledHigherDimensionalRuntimeHostSurfaceByActivationProfileId(
			MagicCube5DEntry->ActivationProfileId,
			MagicCube5DHostSurface
		)
	);
	TestEqual(
		TEXT("The MagicCube5D manifest must stay aligned with the host-surface map asset path."),
		MagicCube5DEntry->MapAssetPath,
		MagicCube5DHostSurface.EffectiveHostMapPath
	);

	FHyperTwistTrainingHigherDimensionalRuntimeLaunchSurface MagicCube5DLaunchSurface;
	TestTrue(
		TEXT("The MagicCube5D launch surface must resolve for map-manifest reconciliation."),
		UHyperTwistTrainingRuntimeLibrary::TryGetBundledHigherDimensionalRuntimeLaunchSurfaceByActivationProfileId(
			MagicCube5DEntry->ActivationProfileId,
			MagicCube5DLaunchSurface
		)
	);
	TestEqual(
		TEXT("The MagicCube5D manifest must stay aligned with the launch-surface id."),
		MagicCube5DEntry->LaunchSurfaceId,
		MagicCube5DLaunchSurface.LaunchSurfaceId
	);
	TestEqual(
		TEXT("The MagicCube5D manifest must stay aligned with the persistence boundary."),
		MagicCube5DEntry->PrimaryPersistenceBoundaryId,
		MagicCube5DLaunchSurface.PrimaryPersistenceBoundaryId
	);

	FHyperTwistTrainingHigherDimensionalInteractiveSceneSurface MagicCube5DSceneSurface;
	TestTrue(
		TEXT("The MagicCube5D interactive scene surface must resolve for map-manifest reconciliation."),
		UHyperTwistTrainingRuntimeLibrary::TryGetBundledHigherDimensionalInteractiveSceneSurfaceByActivationProfileId(
			MagicCube5DEntry->ActivationProfileId,
			MagicCube5DSceneSurface
		)
	);
	TestEqual(
		TEXT("The MagicCube5D manifest must stay aligned with the interactive-scene surface id."),
		MagicCube5DEntry->InteractiveSceneSurfaceId,
		MagicCube5DSceneSurface.SceneSurfaceId
	);
	TestEqual(
		TEXT("The MagicCube5D manifest must stay aligned with the scene-context id."),
		MagicCube5DEntry->SceneContextId,
		MagicCube5DSceneSurface.SceneContext.SceneContextId
	);
	TestEqual(
		TEXT("The MagicCube5D manifest must stay aligned with the interactive-scene projection profile."),
		MagicCube5DEntry->ProjectionProfileId,
		MagicCube5DSceneSurface.SceneContext.ProjectionSettings.ProjectionProfile
	);
	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistHigherDimensionalPhase6CDedicatedMapOwnedShellTest,
	"HyperTwist.FirstParty.HigherDimensional.Phase6C.DedicatedMapOwnedShell",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistHigherDimensionalPhase6CDedicatedMapOwnedShellTest::RunTest(
	const FString& Parameters)
{
	using namespace HyperTwistHigherDimensionalPhase6CTestInternal;

	FPhase6CDedicatedMapManifest Manifest;
	TestTrue(
		TEXT("The Phase 6C dedicated-family map manifest must load for owned-shell checks."),
		TryLoadDedicatedMapManifest(Manifest)
	);
	if (Manifest.Entries.Num() == 0)
	{
		return false;
	}

	const FPhase6CDedicatedMapManifestEntry* Magic120CellEntry =
		FindManifestEntryByFamilyKey(Manifest, TEXT("magic120cell"));
	const FPhase6CDedicatedMapManifestEntry* MagicCube5DEntry =
		FindManifestEntryByFamilyKey(Manifest, TEXT("magiccube5d"));
	TestNotNull(
		TEXT("The owned-shell checks must find the Magic120Cell manifest entry."),
		Magic120CellEntry
	);
	TestNotNull(
		TEXT("The owned-shell checks must find the MagicCube5D manifest entry."),
		MagicCube5DEntry
	);
	if (Magic120CellEntry == nullptr || MagicCube5DEntry == nullptr)
	{
		return false;
	}

	TestEqual(
		TEXT("The runtime-owned Magic120Cell projection must expose exactly 120 canonical cell centers."),
		AHyperTwistHigherDimensionalTrainingShellActor::GetCanonicalElementCountForFamily(
			TEXT("magic120cell")),
		120
	);
	TestEqual(
		TEXT("The runtime-owned order-3 MagicCube5D projection must expose all 242 non-central cells."),
		AHyperTwistHigherDimensionalTrainingShellActor::GetCanonicalElementCountForFamily(
			TEXT("magiccube5d")),
		242
	);

	const AHyperTwistHigherDimensionalTrainingGameMode* RuntimeGameModeDefaults =
		GetDefault<AHyperTwistHigherDimensionalTrainingGameMode>();
	TestNotNull(
		TEXT("The dedicated higher-dimensional runtime game mode defaults must exist."),
		RuntimeGameModeDefaults
	);
	if (RuntimeGameModeDefaults == nullptr)
	{
		return false;
	}
	TestEqual(
		TEXT("The dedicated higher-dimensional runtime must use the orbit pawn."),
		RuntimeGameModeDefaults->DefaultPawnClass.Get(),
		AHyperTwistHigherDimensionalOrbitPawn::StaticClass()
	);
	TestEqual(
		TEXT("The dedicated higher-dimensional runtime must use its non-modal player controller."),
		RuntimeGameModeDefaults->PlayerControllerClass.Get(),
		AHyperTwistHigherDimensionalTrainingPlayerController::StaticClass()
	);
		TestEqual(
			TEXT("The dedicated higher-dimensional runtime must expose its native control HUD."),
			RuntimeGameModeDefaults->HUDClass.Get(),
			AHyperTwistHigherDimensionalTrainingHUD::StaticClass()
		);
		const AHyperTwistHigherDimensionalTrainingShellActor* RuntimeShellDefaults =
			GetDefault<AHyperTwistHigherDimensionalTrainingShellActor>();
		TestNotNull(
			TEXT("The runtime-owned higher-dimensional shell defaults must exist."),
			RuntimeShellDefaults
		);
		if (RuntimeShellDefaults == nullptr)
		{
			return false;
		}
		TestNotNull(
			TEXT("The runtime-owned higher-dimensional shell must self-provision its presentation floor."),
			RuntimeShellDefaults->PresentationFloor.Get()
		);
		TestEqual(
			TEXT("The runtime-owned higher-dimensional shell must expose six independently colored preview layers."),
			RuntimeShellDefaults->PreviewColorLayers.Num(),
			6
		);
		TestEqual(
			TEXT("The runtime-owned higher-dimensional shell must bind six distinct cook-safe first-party materials."),
			RuntimeShellDefaults->GetDistinctPreviewMaterialCount(),
			6
		);

	const auto VerifyDedicatedMapShell =
		[this](const FPhase6CDedicatedMapManifestEntry& Entry) -> bool
	{
		UWorld* MapWorld =
			HyperTwistHigherDimensionalPhase6CTestInternal::LoadDedicatedMapWorld(
				Entry.MapAssetPath);
		TestNotNull(
			*FString::Printf(
				TEXT("The dedicated-family map world asset must load for %s."),
				*Entry.FamilyKey),
			MapWorld
		);
		if (MapWorld == nullptr)
		{
			return false;
		}

		AWorldSettings* WorldSettings = MapWorld->GetWorldSettings();
		TestNotNull(
			*FString::Printf(
				TEXT("The dedicated-family world settings must load for %s."),
				*Entry.FamilyKey),
			WorldSettings
		);
		if (WorldSettings == nullptr)
		{
			return false;
		}

		const int32 TrainingShellActorCount =
			HyperTwistHigherDimensionalPhase6CTestInternal::CountActorsOfClass<
				AHyperTwistHigherDimensionalTrainingShellActor>(MapWorld);
			TestEqual(
				*FString::Printf(
					TEXT("The dedicated-family map must leave shell presentation exclusively to runtime ownership for %s."),
					*Entry.FamilyKey),
				TrainingShellActorCount,
				0
			);
		TestEqual(
			*FString::Printf(
				TEXT("The dedicated-family map must contain exactly one PlayerStart anchor for %s."),
				*Entry.FamilyKey),
			HyperTwistHigherDimensionalPhase6CTestInternal::CountActorsOfClass<
				APlayerStart>(MapWorld),
			1
		);

		AHyperTwistHigherDimensionalTrainingShellActor* TrainingShellActor =
			HyperTwistHigherDimensionalPhase6CTestInternal::FindActorOfClass<
				AHyperTwistHigherDimensionalTrainingShellActor>(MapWorld);
		APlayerStart* PlayerStart =
			HyperTwistHigherDimensionalPhase6CTestInternal::FindActorOfClass<
				APlayerStart>(MapWorld);
		TestNotNull(
			*FString::Printf(
				TEXT("The dedicated-family PlayerStart anchor must load for %s."),
				*Entry.FamilyKey),
			PlayerStart
		);
		if (PlayerStart == nullptr)
		{
			return false;
		}

		const FString ExpectedTitle = Entry.FamilyKey.Equals(
				TEXT("magic120cell"),
				ESearchCase::IgnoreCase)
			? TEXT("Magic120Cell dedicated training shell")
			: TEXT("MagicCube5D dedicated training shell");
		const FString ExpectedManifestPath =
			TEXT("docs/generated/higher_dimensional_training_maps/phase6c_dedicated_family_map_manifest.json");
		const FString ExpectedHostTag =
			FString::Printf(TEXT("host-surface:%s"), *Entry.HostSurfaceId);
		const FString ExpectedLaunchTag =
			FString::Printf(TEXT("launch-surface:%s"), *Entry.LaunchSurfaceId);
		const FString ExpectedViewContextTag =
			FString::Printf(TEXT("view-context-surface:%s"), *Entry.ViewContextSurfaceId);
		const FString ExpectedSessionTag =
			FString::Printf(TEXT("session-surface:%s"), *Entry.SessionSurfaceId);
		const FString ExpectedInteractiveSceneTag =
			FString::Printf(
				TEXT("interactive-scene-surface:%s"),
				*Entry.InteractiveSceneSurfaceId);
		const FString ExpectedSceneContextTag =
			FString::Printf(TEXT("scene-context:%s"), *Entry.SceneContextId);
		const FString ExpectedProjectionTag =
			FString::Printf(TEXT("projection:%s"), *Entry.ProjectionProfileId);
		const FString ExpectedPersistenceTag =
			FString::Printf(TEXT("persistence:%s"), *Entry.PrimaryPersistenceBoundaryId);
		const FString ExpectedTrainingShellTag =
			FString::Printf(TEXT("training-shell-id:%s"), *Entry.TrainingShellId);
		const FString ExpectedActivationTag =
			FString::Printf(TEXT("activation-profile:%s"), *Entry.ActivationProfileId);
		const FString ExpectedPuzzleTag =
			FString::Printf(TEXT("puzzle:%s"), *Entry.PuzzleId);
		const FString ExpectedRuntimeModeTag =
			FString::Printf(TEXT("runtime-mode:%s"), *Entry.RuntimeModeId);
		const auto HasActorTag = [](const AActor* Actor, const FString& Tag) -> bool
		{
			return Actor != nullptr && Actor->ActorHasTag(FName(*Tag));
		};

			TestEqual(
				*FString::Printf(
					TEXT("The dedicated-family world settings must preserve the interactive higher-dimensional game mode for %s."),
				*Entry.FamilyKey),
			WorldSettings->DefaultGameMode != nullptr
				? WorldSettings->DefaultGameMode->GetPathName()
				: FString(),
				AHyperTwistHigherDimensionalTrainingGameMode::StaticClass()->GetPathName()
			);
			TestEqual(
				*FString::Printf(
					TEXT("The manifest must bind the dedicated game mode for %s."),
					*Entry.FamilyKey),
				Entry.AuthoredViaGameModeClassPath,
				AHyperTwistHigherDimensionalTrainingGameMode::StaticClass()->GetPathName()
			);
			TestEqual(
				*FString::Printf(
					TEXT("The manifest must bind the runtime shell presentation class for %s."),
					*Entry.FamilyKey),
				Entry.RuntimePresentationClassPath,
				AHyperTwistHigherDimensionalTrainingShellActor::StaticClass()->GetPathName()
			);
			TestEqual(
				*FString::Printf(
					TEXT("The manifest must preserve runtime presentation-environment ownership for %s."),
					*Entry.FamilyKey),
				Entry.PresentationEnvironmentOwnership,
				TEXT("runtime-game-mode-and-shell-components")
			);
			TestEqual(
				*FString::Printf(
					TEXT("The manifest must preserve the exact canonical runtime element count for %s."),
					*Entry.FamilyKey),
				Entry.CanonicalRenderableElementCount,
				AHyperTwistHigherDimensionalTrainingShellActor::GetCanonicalElementCountForFamily(
					Entry.FamilyKey)
			);
		if (TrainingShellActor != nullptr)
		{
			TestEqual(
				*FString::Printf(
					TEXT("The optional dedicated-family training shell must preserve the family key for %s."),
					*Entry.FamilyKey),
				TrainingShellActor->FamilyKey,
				Entry.FamilyKey
			);
			TestEqual(
				*FString::Printf(
					TEXT("The optional dedicated-family training shell must preserve the title for %s."),
					*Entry.FamilyKey),
				TrainingShellActor->Title,
				ExpectedTitle
			);
			TestEqual(
				*FString::Printf(
					TEXT("The optional dedicated-family training shell must preserve the map asset path for %s."),
					*Entry.FamilyKey),
				TrainingShellActor->MapAssetPath,
				Entry.MapAssetPath
			);
			TestEqual(
				*FString::Printf(
					TEXT("The optional dedicated-family training shell must preserve the training-shell id for %s."),
					*Entry.FamilyKey),
				TrainingShellActor->TrainingShellId,
				Entry.TrainingShellId
			);
			TestEqual(
				*FString::Printf(
					TEXT("The optional dedicated-family training shell must preserve the activation profile id for %s."),
					*Entry.FamilyKey),
				TrainingShellActor->ActivationProfileId,
				Entry.ActivationProfileId
			);
			TestEqual(
				*FString::Printf(
					TEXT("The optional dedicated-family training shell must preserve the scene-context id for %s."),
					*Entry.FamilyKey),
				TrainingShellActor->SceneContextId,
				Entry.SceneContextId
			);
			TestEqual(
				*FString::Printf(
					TEXT("The optional dedicated-family training shell must preserve the projection profile id for %s."),
					*Entry.FamilyKey),
				TrainingShellActor->ProjectionProfileId,
				Entry.ProjectionProfileId
			);
			TestEqual(
				*FString::Printf(
					TEXT("The optional dedicated-family training shell must preserve the persistence boundary id for %s."),
					*Entry.FamilyKey),
				TrainingShellActor->PrimaryPersistenceBoundaryId,
				Entry.PrimaryPersistenceBoundaryId
			);
			TestEqual(
				*FString::Printf(
					TEXT("The optional dedicated-family training shell must preserve the authoring manifest path for %s."),
					*Entry.FamilyKey),
				TrainingShellActor->AuthoringManifestRelativePath,
				ExpectedManifestPath
			);
			TestTrue(
				*FString::Printf(
					TEXT("The optional dedicated-family training shell must preserve dedicated ownership for %s."),
					*Entry.FamilyKey),
				TrainingShellActor->bDedicatedFamilyOwnership
			);
			TestTrue(
				*FString::Printf(
					TEXT("The optional dedicated-family training shell must carry the authored shell tag for %s."),
					*Entry.FamilyKey),
				HasActorTag(
					TrainingShellActor,
					TEXT("HyperTwistHigherDimensionalTrainingShell"))
			);
			TestTrue(
				*FString::Printf(
					TEXT("The optional dedicated-family training shell must carry the authored training-shell id tag for %s."),
					*Entry.FamilyKey),
				HasActorTag(TrainingShellActor, ExpectedTrainingShellTag)
			);
			TestTrue(
				*FString::Printf(
					TEXT("The optional dedicated-family training shell must carry the authored host-surface tag for %s."),
					*Entry.FamilyKey),
				HasActorTag(TrainingShellActor, ExpectedHostTag)
			);
			TestTrue(
				*FString::Printf(
					TEXT("The optional dedicated-family training shell must carry the authored launch-surface tag for %s."),
					*Entry.FamilyKey),
				HasActorTag(TrainingShellActor, ExpectedLaunchTag)
			);
			TestTrue(
				*FString::Printf(
					TEXT("The optional dedicated-family training shell must carry the authored scene-context tag for %s."),
					*Entry.FamilyKey),
				HasActorTag(TrainingShellActor, ExpectedSceneContextTag)
			);
			TestTrue(
				*FString::Printf(
					TEXT("The optional dedicated-family training shell must carry the authored projection tag for %s."),
					*Entry.FamilyKey),
				HasActorTag(TrainingShellActor, ExpectedProjectionTag)
			);
			TestTrue(
				*FString::Printf(
					TEXT("The optional dedicated-family training shell must carry the authored persistence tag for %s."),
					*Entry.FamilyKey),
				HasActorTag(TrainingShellActor, ExpectedPersistenceTag)
			);
			TestTrue(
				*FString::Printf(
					TEXT("The optional dedicated-family training shell must carry the dedicated ownership tag for %s."),
					*Entry.FamilyKey),
				HasActorTag(TrainingShellActor, TEXT("ownership:dedicated-family"))
			);
		}
		TestTrue(
			*FString::Printf(
				TEXT("The dedicated-family PlayerStart anchor must carry the activation-profile tag for %s."),
				*Entry.FamilyKey),
			HasActorTag(PlayerStart, ExpectedActivationTag)
		);
		TestTrue(
			*FString::Printf(
				TEXT("The dedicated-family PlayerStart anchor must carry the view-context tag for %s."),
				*Entry.FamilyKey),
			HasActorTag(PlayerStart, ExpectedViewContextTag)
		);
		TestTrue(
			*FString::Printf(
				TEXT("The dedicated-family PlayerStart anchor must carry the session-surface tag for %s."),
				*Entry.FamilyKey),
			HasActorTag(PlayerStart, ExpectedSessionTag)
		);
		TestTrue(
			*FString::Printf(
				TEXT("The dedicated-family PlayerStart anchor must carry the interactive-scene tag for %s."),
				*Entry.FamilyKey),
			HasActorTag(PlayerStart, ExpectedInteractiveSceneTag)
		);
		TestTrue(
			*FString::Printf(
				TEXT("The dedicated-family PlayerStart anchor must carry the puzzle tag for %s."),
				*Entry.FamilyKey),
			HasActorTag(PlayerStart, ExpectedPuzzleTag)
		);
		TestTrue(
			*FString::Printf(
				TEXT("The dedicated-family PlayerStart anchor must carry the runtime-mode tag for %s."),
				*Entry.FamilyKey),
			HasActorTag(PlayerStart, ExpectedRuntimeModeTag)
		);

		return true;
	};

	return VerifyDedicatedMapShell(*Magic120CellEntry)
		&& VerifyDedicatedMapShell(*MagicCube5DEntry);
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistHigherDimensionalPhase6CLaunchCatalogTest,
	"HyperTwist.FirstParty.HigherDimensional.Phase6C.LaunchCatalog",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistHigherDimensionalPhase6CLaunchCatalogTest::RunTest(const FString& Parameters)
{
	const FHyperTwistTrainingHigherDimensionalRuntimeLaunchCatalog Catalog =
		UHyperTwistTrainingRuntimeLibrary::GetBundledHigherDimensionalRuntimeLaunchCatalog();

	TestTrue(
		TEXT("The Phase 6C higher-dimensional launch catalog must be structurally valid."),
		Catalog.IsStructurallyValid()
	);
	TestEqual(
		TEXT("The Phase 6C higher-dimensional launch catalog must expose both retained family launch surfaces."),
		Catalog.LaunchSurfaces.Num(),
		2
	);

	FHyperTwistTrainingHigherDimensionalRuntimeLaunchSurface Magic120CellLaunchSurface;
	TestTrue(
		TEXT("The Magic120Cell launch surface must resolve from the bundled catalog."),
		UHyperTwistTrainingRuntimeLibrary::TryGetBundledHigherDimensionalRuntimeLaunchSurfaceByActivationProfileId(
			TEXT("magic120cell-cleanroom-runtime-activation"),
			Magic120CellLaunchSurface
		)
	);
	TestEqual(
		TEXT("The Magic120Cell launch surface must now use the dedicated family training map host."),
		Magic120CellLaunchSurface.HostMapPath,
		TEXT("/Game/HyperTwistTraining/Maps/L_HyperTwist_Magic120CellTraining")
	);
	TestEqual(
		TEXT("The Magic120Cell launch surface must resolve through the explicit host surface seam."),
		Magic120CellLaunchSurface.HostSurfaceId,
		TEXT("phase6c/magic120cell/runtime-host-surface")
	);
	TestFalse(
		TEXT("The Magic120Cell launch surface must no longer be flagged as a shared-map fallback."),
		Magic120CellLaunchSurface.bUsesSharedTrainingMapFallback
	);
	TestEqual(
		TEXT("The Magic120Cell launch surface must preserve the generated runtime mode."),
		Magic120CellLaunchSurface.RuntimeModeId,
		TEXT("magic120cell-full-color-runtime-v1")
	);
	TestEqual(
		TEXT("The Magic120Cell launch surface must preserve the dedicated persistence boundary."),
		Magic120CellLaunchSurface.PrimaryPersistenceBoundaryId,
		TEXT("magic120cell-persistence-boundary")
	);
	TestEqual(
		TEXT("The Magic120Cell launch surface must preserve three default selector choices."),
		Magic120CellLaunchSurface.DefaultSelectorChoices.Num(),
		3
	);

	FHyperTwistTrainingHigherDimensionalRuntimeLaunchSurface MagicCube5DLaunchSurface;
	TestTrue(
		TEXT("The MagicCube5D launch surface must resolve from the bundled catalog."),
		UHyperTwistTrainingRuntimeLibrary::TryGetBundledHigherDimensionalRuntimeLaunchSurfaceByPuzzleId(
			TEXT("hypercube/magiccube5d/order3"),
			MagicCube5DLaunchSurface
		)
	);
	TestEqual(
		TEXT("The MagicCube5D launch surface must preserve the generated runtime mode."),
		MagicCube5DLaunchSurface.RuntimeModeId,
		TEXT("magiccube5d-order3-runtime-v1")
	);
	TestEqual(
		TEXT("The MagicCube5D launch surface must preserve the dedicated persistence boundary."),
		MagicCube5DLaunchSurface.PrimaryPersistenceBoundaryId,
		TEXT("magiccube5d-persistence-boundary")
	);
	TestEqual(
		TEXT("The MagicCube5D launch surface must resolve through the explicit host surface seam."),
		MagicCube5DLaunchSurface.HostSurfaceId,
		TEXT("phase6c/magiccube5d/runtime-host-surface")
	);
	TestEqual(
		TEXT("The MagicCube5D launch surface must now use the dedicated family training map host."),
		MagicCube5DLaunchSurface.HostMapPath,
		TEXT("/Game/HyperTwistTraining/Maps/L_HyperTwist_MagicCube5DTraining")
	);
	TestEqual(
		TEXT("The MagicCube5D launch surface must preserve three default selector choices."),
		MagicCube5DLaunchSurface.DefaultSelectorChoices.Num(),
		3
	);
	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistHigherDimensionalPhase6CViewContextCatalogTest,
	"HyperTwist.FirstParty.HigherDimensional.Phase6C.ViewContextCatalog",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistHigherDimensionalPhase6CViewContextCatalogTest::RunTest(const FString& Parameters)
{
	const FHyperTwistTrainingHigherDimensionalRuntimeViewContextCatalog Catalog =
		UHyperTwistTrainingRuntimeLibrary::GetBundledHigherDimensionalRuntimeViewContextCatalog();

	TestTrue(
		TEXT("The Phase 6C higher-dimensional view-context catalog must be structurally valid."),
		Catalog.IsStructurallyValid()
	);
	TestEqual(
		TEXT("The Phase 6C higher-dimensional view-context catalog must expose both retained family view surfaces."),
		Catalog.ViewContextSurfaces.Num(),
		2
	);

	FHyperTwistTrainingHigherDimensionalRuntimeViewContextSurface Magic120CellViewContextSurface;
	TestTrue(
		TEXT("The Magic120Cell view-context surface must resolve from the bundled catalog."),
		UHyperTwistTrainingRuntimeLibrary::TryGetBundledHigherDimensionalRuntimeViewContextSurfaceByActivationProfileId(
			TEXT("magic120cell-cleanroom-runtime-activation"),
			Magic120CellViewContextSurface
		)
	);
	TestEqual(
		TEXT("The Magic120Cell view-context surface must preserve the dedicated view-profile contract."),
		Magic120CellViewContextSurface.PrimaryViewProfileContractId,
		TEXT("magic120cell-focus-view-profile")
	);
	TestEqual(
		TEXT("The Magic120Cell view-context surface must preserve four default selector choices."),
		Magic120CellViewContextSurface.DefaultSelectorChoices.Num(),
		4
	);
	TestEqual(
		TEXT("The Magic120Cell view-context surface must preserve the explicit host surface seam."),
		Magic120CellViewContextSurface.HostSurfaceId,
		TEXT("phase6c/magic120cell/runtime-host-surface")
	);
	TestFalse(
		TEXT("The Magic120Cell view-context surface must no longer stay on the shared training-map fallback."),
		Magic120CellViewContextSurface.bUsesSharedTrainingMapFallback
	);

	FHyperTwistTrainingHigherDimensionalRuntimeViewContextSurface MagicCube5DViewContextSurface;
	TestTrue(
		TEXT("The MagicCube5D view-context surface must resolve from the bundled catalog."),
		UHyperTwistTrainingRuntimeLibrary::TryGetBundledHigherDimensionalRuntimeViewContextSurfaceByPuzzleId(
			TEXT("hypercube/magiccube5d/order3"),
			MagicCube5DViewContextSurface
		)
	);
	TestEqual(
		TEXT("The MagicCube5D view-context surface must preserve the dedicated view-profile contract."),
		MagicCube5DViewContextSurface.PrimaryViewProfileContractId,
		TEXT("magiccube5d-projection-view-profile")
	);
	TestEqual(
		TEXT("The MagicCube5D view-context surface must preserve four default selector choices."),
		MagicCube5DViewContextSurface.DefaultSelectorChoices.Num(),
		4
	);
	TestEqual(
		TEXT("The MagicCube5D view-context surface must preserve the explicit host surface seam."),
		MagicCube5DViewContextSurface.HostSurfaceId,
		TEXT("phase6c/magiccube5d/runtime-host-surface")
	);
	TestTrue(
		TEXT("The MagicCube5D view-context surface must expose stereo context tags."),
		MagicCube5DViewContextSurface.ContextSurfaceTags.Contains(TEXT("stereo disabled default"))
	);
	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistHigherDimensionalPhase6CSessionCatalogTest,
	"HyperTwist.FirstParty.HigherDimensional.Phase6C.SessionCatalog",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistHigherDimensionalPhase6CSessionCatalogTest::RunTest(const FString& Parameters)
{
	const FHyperTwistTrainingHigherDimensionalRuntimeSessionCatalog Catalog =
		UHyperTwistTrainingRuntimeLibrary::GetBundledHigherDimensionalRuntimeSessionCatalog();

	TestTrue(
		TEXT("The Phase 6C higher-dimensional session catalog must be structurally valid."),
		Catalog.IsStructurallyValid()
	);
	TestEqual(
		TEXT("The Phase 6C higher-dimensional session catalog must expose both retained family session surfaces."),
		Catalog.SessionSurfaces.Num(),
		2
	);

	FHyperTwistTrainingHigherDimensionalRuntimeSessionSurface Magic120CellSessionSurface;
	TestTrue(
		TEXT("The Magic120Cell session surface must resolve from the bundled catalog."),
		UHyperTwistTrainingRuntimeLibrary::TryGetBundledHigherDimensionalRuntimeSessionSurfaceByActivationProfileId(
			TEXT("magic120cell-cleanroom-runtime-activation"),
			Magic120CellSessionSurface
		)
	);
	TestEqual(
		TEXT("The Magic120Cell session surface must preserve the dedicated launch surface linkage."),
		Magic120CellSessionSurface.LaunchSurfaceId,
		TEXT("phase6c/magic120cell/dedicated-training-launch-surface")
	);
	TestEqual(
		TEXT("The Magic120Cell session surface must preserve the dedicated view-context linkage."),
		Magic120CellSessionSurface.ViewContextSurfaceId,
		TEXT("phase6c/magic120cell/dedicated-training-view-context-surface")
	);
	TestEqual(
		TEXT("The Magic120Cell session surface must merge all unique launch and view selector families."),
		Magic120CellSessionSurface.Selectors.Num(),
		7
	);
	TestEqual(
		TEXT("The Magic120Cell session surface must merge all unique default selector choices."),
		Magic120CellSessionSurface.DefaultSelectorChoices.Num(),
		7
	);
	TestTrue(
		TEXT("The Magic120Cell session surface must mark the merged session-default posture."),
		Magic120CellSessionSurface.SessionTags.Contains(TEXT("session-defaults:launch-plus-view-context"))
	);

	FHyperTwistTrainingHigherDimensionalRuntimeSessionSurface MagicCube5DSessionSurface;
	TestTrue(
		TEXT("The MagicCube5D session surface must resolve from the bundled catalog."),
		UHyperTwistTrainingRuntimeLibrary::TryGetBundledHigherDimensionalRuntimeSessionSurfaceByPuzzleId(
			TEXT("hypercube/magiccube5d/order3"),
			MagicCube5DSessionSurface
		)
	);
	TestEqual(
		TEXT("The MagicCube5D session surface must preserve the dedicated launch surface linkage."),
		MagicCube5DSessionSurface.LaunchSurfaceId,
		TEXT("phase6c/magiccube5d/dedicated-training-launch-surface")
	);
	TestEqual(
		TEXT("The MagicCube5D session surface must preserve the dedicated view-context linkage."),
		MagicCube5DSessionSurface.ViewContextSurfaceId,
		TEXT("phase6c/magiccube5d/dedicated-training-view-context-surface")
	);
	TestEqual(
		TEXT("The MagicCube5D session surface must merge duplicate stereo and visibility selectors rather than duplicating them."),
		MagicCube5DSessionSurface.Selectors.Num(),
		5
	);
	TestEqual(
		TEXT("The MagicCube5D session surface must preserve one default choice per merged selector."),
		MagicCube5DSessionSurface.DefaultSelectorChoices.Num(),
		5
	);
	TestEqual(
		TEXT("The MagicCube5D session surface must now stay on the dedicated family host."),
		MagicCube5DSessionSurface.HostMapPath,
		TEXT("/Game/HyperTwistTraining/Maps/L_HyperTwist_MagicCube5DTraining")
	);
	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistHigherDimensionalPhase6CInteractiveSceneCatalogTest,
	"HyperTwist.FirstParty.HigherDimensional.Phase6C.InteractiveSceneCatalog",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistHigherDimensionalPhase6CInteractiveSceneCatalogTest::RunTest(const FString& Parameters)
{
	const FHyperTwistTrainingHigherDimensionalInteractiveSceneCatalog Catalog =
		UHyperTwistTrainingRuntimeLibrary::GetBundledHigherDimensionalInteractiveSceneCatalog();

	TestTrue(
		TEXT("The Phase 6C higher-dimensional interactive-scene catalog must be structurally valid."),
		Catalog.IsStructurallyValid()
	);
	TestEqual(
		TEXT("The Phase 6C higher-dimensional interactive-scene catalog must expose both retained family scene surfaces."),
		Catalog.SceneSurfaces.Num(),
		2
	);

	FHyperTwistTrainingHigherDimensionalInteractiveSceneSurface Magic120CellSceneSurface;
	TestTrue(
		TEXT("The Magic120Cell interactive scene surface must resolve from the bundled catalog."),
		UHyperTwistTrainingRuntimeLibrary::TryGetBundledHigherDimensionalInteractiveSceneSurfaceByActivationProfileId(
			TEXT("magic120cell-cleanroom-runtime-activation"),
			Magic120CellSceneSurface
		)
	);
	TestEqual(
		TEXT("The Magic120Cell interactive scene surface must preserve the session-surface linkage."),
		Magic120CellSceneSurface.SessionSurfaceId,
		TEXT("phase6c/magic120cell/dedicated-training-session-surface")
	);
	TestTrue(
		TEXT("The Magic120Cell interactive scene surface must remain renderable."),
		UHyperTwistSimulationLibrary::CanRenderSceneContext(Magic120CellSceneSurface.SceneContext)
	);
	TestFalse(
		TEXT("The Magic120Cell interactive scene surface must no longer keep the placeholder-state posture."),
		Magic120CellSceneSurface.bUsesPlaceholderStateEnvelope
	);
	TestEqual(
		TEXT("The Magic120Cell interactive scene surface must preserve the canonical puzzle id."),
		Magic120CellSceneSurface.SceneContext.PuzzleState.Definition.PuzzleId,
		TEXT("polychoron/magic120cell")
	);
	TestEqual(
		TEXT("The Magic120Cell interactive scene surface must preserve the dedicated projection profile."),
		Magic120CellSceneSurface.SceneContext.ProjectionSettings.ProjectionProfile,
		TEXT("magic120cell-4d-projection-distance-v1")
	);
	TestEqual(
		TEXT("The Magic120Cell interactive scene surface must preserve the dedicated render state profile."),
		Magic120CellSceneSurface.SceneContext.RenderStateProfile,
		TEXT("magic120cell-center-cell-focus-scene-runtime-v1")
	);
	TestEqual(
		TEXT("The Magic120Cell interactive scene surface must keep the family-owned encoding profile."),
		Magic120CellSceneSurface.SceneContext.PuzzleState.StateEncoding.EncodingProfile,
		TEXT("magic120cell-family-owned-scene-state-v1")
	);
	TestTrue(
		TEXT("The Magic120Cell interactive scene surface must carry the family-owned scene-state tag."),
		Magic120CellSceneSurface.SceneTags.Contains(TEXT("scene-state:family-owned-envelope"))
	);

	FHyperTwistTrainingMagic120CellInteractiveSceneStateEnvelope Magic120CellEnvelope;
	TestTrue(
		TEXT("The Magic120Cell interactive scene surface must decode to a family-owned scene-state envelope."),
		UHyperTwistTrainingRuntimeLibrary::TryDecodeMagic120CellInteractiveSceneStateEnvelope(
			Magic120CellSceneSurface.SceneContext,
			Magic120CellEnvelope
		)
	);
	TestEqual(
		TEXT("The Magic120Cell interactive scene-state envelope must preserve the persistence boundary."),
		Magic120CellEnvelope.PersistenceBoundaryId,
		TEXT("magic120cell-persistence-boundary")
	);
	TestEqual(
		TEXT("The Magic120Cell interactive scene-state envelope must preserve the view-profile contract."),
		Magic120CellEnvelope.ViewProfileContractId,
		TEXT("magic120cell-focus-view-profile")
	);
	TestEqual(
		TEXT("The Magic120Cell interactive scene-state envelope must keep the full puzzle mode."),
		Magic120CellEnvelope.PuzzleTypeModeId,
		TEXT("full-puzzle-default-mode")
	);

	FHyperTwistTrainingHigherDimensionalInteractiveSceneSurface MagicCube5DSceneSurface;
	TestTrue(
		TEXT("The MagicCube5D interactive scene surface must resolve from the bundled catalog."),
		UHyperTwistTrainingRuntimeLibrary::TryGetBundledHigherDimensionalInteractiveSceneSurfaceByPuzzleId(
			TEXT("hypercube/magiccube5d/order3"),
			MagicCube5DSceneSurface
		)
	);
	TestEqual(
		TEXT("The MagicCube5D interactive scene surface must preserve the session-surface linkage."),
		MagicCube5DSceneSurface.SessionSurfaceId,
		TEXT("phase6c/magiccube5d/dedicated-training-session-surface")
	);
	TestTrue(
		TEXT("The MagicCube5D interactive scene surface must remain renderable."),
		UHyperTwistSimulationLibrary::CanRenderSceneContext(MagicCube5DSceneSurface.SceneContext)
	);
	TestFalse(
		TEXT("The MagicCube5D interactive scene surface must no longer keep the placeholder-state posture."),
		MagicCube5DSceneSurface.bUsesPlaceholderStateEnvelope
	);
	TestEqual(
		TEXT("The MagicCube5D interactive scene surface must preserve the canonical puzzle id."),
		MagicCube5DSceneSurface.SceneContext.PuzzleState.Definition.PuzzleId,
		TEXT("hypercube/magiccube5d/order3")
	);
	TestEqual(
		TEXT("The MagicCube5D interactive scene surface must preserve the dedicated projection profile."),
		MagicCube5DSceneSurface.SceneContext.ProjectionSettings.ProjectionProfile,
		TEXT("magiccube5d-5d-projection-distance-v1")
	);
	TestEqual(
		TEXT("The MagicCube5D interactive scene surface must preserve the dedicated render state profile."),
		MagicCube5DSceneSurface.SceneContext.RenderStateProfile,
		TEXT("magiccube5d-order3-scene-runtime-v1")
	);
	TestEqual(
		TEXT("The MagicCube5D interactive scene surface must keep the family-owned encoding profile."),
		MagicCube5DSceneSurface.SceneContext.PuzzleState.StateEncoding.EncodingProfile,
		TEXT("magiccube5d-family-owned-scene-state-v1")
	);
	TestTrue(
		TEXT("The MagicCube5D interactive scene surface must carry the family-owned scene-state tag."),
		MagicCube5DSceneSurface.SceneTags.Contains(TEXT("scene-state:family-owned-envelope"))
	);

	FHyperTwistTrainingMagicCube5DInteractiveSceneStateEnvelope MagicCube5DEnvelope;
	TestTrue(
		TEXT("The MagicCube5D interactive scene surface must decode to a family-owned scene-state envelope."),
		UHyperTwistTrainingRuntimeLibrary::TryDecodeMagicCube5DInteractiveSceneStateEnvelope(
			MagicCube5DSceneSurface.SceneContext,
			MagicCube5DEnvelope
		)
	);
	TestEqual(
		TEXT("The MagicCube5D interactive scene-state envelope must preserve the persistence boundary."),
		MagicCube5DEnvelope.PersistenceBoundaryId,
		TEXT("magiccube5d-persistence-boundary")
	);
	TestEqual(
		TEXT("The MagicCube5D interactive scene-state envelope must preserve the macro format."),
		MagicCube5DEnvelope.MacroFormatId,
		TEXT("magiccube5d/macros-sidecar-v1")
	);
	TestEqual(
		TEXT("The MagicCube5D interactive scene-state envelope must preserve the order-three family ownership."),
		MagicCube5DEnvelope.PuzzleOrder,
		3
	);
	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistHigherDimensionalPhase6CMagic120CellActivationProfileTest,
	"HyperTwist.FirstParty.HigherDimensional.Phase6C.Magic120CellActivationProfile",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistHigherDimensionalPhase6CMagic120CellActivationProfileTest::RunTest(const FString& Parameters)
{
	FHyperTwistTrainingHigherDimensionalRuntimeActivationProfile Profile;
	TestTrue(
		TEXT("The Magic120Cell Phase 6C activation profile must resolve by puzzle id."),
		UHyperTwistTrainingRuntimeLibrary::TryGetBundledHigherDimensionalRuntimeActivationProfileByPuzzleId(
			TEXT("polychoron/magic120cell"),
			Profile
		)
	);
	TestEqual(TEXT("The Magic120Cell activation profile id must stay stable."), Profile.ActivationProfileId, TEXT("magic120cell-cleanroom-runtime-activation"));
	TestFalse(TEXT("The Magic120Cell activation must stay on the in-process Unreal clean-room lane."), Profile.bRequiresExternalProcess);
	TestEqual(TEXT("The Magic120Cell activation must remain anchored to retained Hyperspeedcube ownership."), Profile.RuntimeAnchorId, TEXT("retained/hyperspeedcube-runtime-anchor"));
	TestEqual(TEXT("The Magic120Cell definition must stay 4D."), Profile.ToDefinitionRef().Dimension, 4);
	TestEqual(TEXT("The Magic120Cell definition must stay in the Other puzzle family until a broader family enum lands."), Profile.ToDefinitionRef().PuzzleFamily, EHyperTwistPuzzleFamily::Other);
	TestTrue(TEXT("The Magic120Cell activation must keep the family-core package required."), Profile.RequiredPackageIds.Contains(TEXT("package/magic120cell-family-core")));
	TestTrue(TEXT("The Magic120Cell activation must preserve the full-color default runtime selection."), Profile.DefaultSelectionTags.Contains(TEXT("full-color puzzle type")));
	TestTrue(TEXT("The Magic120Cell activation must preserve center-cell recentering capability."), Profile.CapabilityTags.Contains(TEXT("center-cell recentering")));
	TestTrue(TEXT("The Magic120Cell activation must keep broad runtime replacement excluded."), Profile.ExplicitExclusions.Contains(TEXT("Hyperspeedcube runtime-base replacement")));
	TestEqual(TEXT("The Magic120Cell activation must remain first-party owned."), Profile.SourceAttribution.SourceMode, EHyperTwistTrainingSourceMode::FirstParty);
	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistHigherDimensionalPhase6CMagicCube5DActivationProfileTest,
	"HyperTwist.FirstParty.HigherDimensional.Phase6C.MagicCube5DActivationProfile",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistHigherDimensionalPhase6CMagicCube5DActivationProfileTest::RunTest(const FString& Parameters)
{
	FHyperTwistTrainingHigherDimensionalRuntimeActivationProfile Profile;
	TestTrue(
		TEXT("The MagicCube5D Phase 6C activation profile must resolve by profile id."),
		UHyperTwistTrainingRuntimeLibrary::TryGetBundledHigherDimensionalRuntimeActivationProfileById(
			TEXT("magiccube5d-cleanroom-runtime-activation"),
			Profile
		)
	);
	TestEqual(TEXT("The MagicCube5D activation must stay mapped to the order-three launch posture."), Profile.PuzzleId, TEXT("hypercube/magiccube5d/order3"));
	TestFalse(TEXT("The MagicCube5D activation must stay on the in-process Unreal clean-room lane."), Profile.bRequiresExternalProcess);
	TestEqual(TEXT("The MagicCube5D definition must stay 5D."), Profile.ToDefinitionRef().Dimension, 5);
	TestEqual(TEXT("The MagicCube5D definition must stay inside the hypercube family."), Profile.ToDefinitionRef().PuzzleFamily, EHyperTwistPuzzleFamily::Hypercube);
	TestEqual(TEXT("The MagicCube5D definition must preserve the order-three size vector."), Profile.ToDefinitionRef().SizeVector, TArray<int32>({3, 3, 3, 3, 3}));
	TestTrue(TEXT("The MagicCube5D activation must keep the state-transformer package required."), Profile.RequiredPackageIds.Contains(TEXT("package/magiccube5d-state-transformer")));
	TestTrue(TEXT("The MagicCube5D activation must preserve the order-three default selection."), Profile.DefaultSelectionTags.Contains(TEXT("order-three default family mode")));
	TestTrue(TEXT("The MagicCube5D activation must preserve fifth-axis focus capability."), Profile.CapabilityTags.Contains(TEXT("control-click fifth-axis view rotation")));
	TestTrue(TEXT("The MagicCube5D activation must keep broad runtime replacement excluded."), Profile.ExplicitExclusions.Contains(TEXT("Hyperspeedcube runtime-base replacement")));
	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistHigherDimensionalPhase6CTrainingRunDefinitionBridgeTest,
	"HyperTwist.FirstParty.HigherDimensional.Phase6C.TrainingRunDefinitionBridge",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistHigherDimensionalPhase6CTrainingRunDefinitionBridgeTest::RunTest(const FString& Parameters)
{
	const FHyperTwistTrainingRunState Magic120CellRun = UHyperTwistTrainingLibrary::StartTrainingRun(
		HyperTwistHigherDimensionalPhase6CTestInternal::MakeDeck(
			TEXT("phase6c/magic120cell"),
			TEXT("polychoron/magic120cell")
		),
		TEXT("phase6c-user"),
		TEXT("phase6c-magic120cell-session"),
		EHyperTwistTrainingDeliveryMode::VirtualCube
	);
	TestTrue(TEXT("The Magic120Cell activation deck must start a structurally valid run."), Magic120CellRun.IsStructurallyValid());
	TestEqual(TEXT("The Magic120Cell run must keep the canonical Phase 6C puzzle id."), Magic120CellRun.ReplayPacket.PuzzleDefinition.PuzzleId, TEXT("polychoron/magic120cell"));
	TestEqual(TEXT("The Magic120Cell run must keep the 4D dimension."), Magic120CellRun.ReplayPacket.PuzzleDefinition.Dimension, 4);
	TestEqual(TEXT("The Magic120Cell run must keep the dedicated notation profile."), Magic120CellRun.ReplayPacket.PuzzleDefinition.NotationProfile, TEXT("magic120cell-family"));

	const FHyperTwistTrainingRunState MagicCube5DRun = UHyperTwistTrainingLibrary::StartTrainingRun(
		HyperTwistHigherDimensionalPhase6CTestInternal::MakeDeck(
			TEXT("phase6c/magiccube5d"),
			TEXT("hypercube/magiccube5d/order3")
		),
		TEXT("phase6c-user"),
		TEXT("phase6c-magiccube5d-session"),
		EHyperTwistTrainingDeliveryMode::VirtualCube
	);
	TestTrue(TEXT("The MagicCube5D activation deck must start a structurally valid run."), MagicCube5DRun.IsStructurallyValid());
	TestEqual(TEXT("The MagicCube5D run must keep the canonical Phase 6C puzzle id."), MagicCube5DRun.ReplayPacket.PuzzleDefinition.PuzzleId, TEXT("hypercube/magiccube5d/order3"));
	TestEqual(TEXT("The MagicCube5D run must keep the 5D dimension."), MagicCube5DRun.ReplayPacket.PuzzleDefinition.Dimension, 5);
	TestEqual(TEXT("The MagicCube5D run must preserve the order-three size vector."), MagicCube5DRun.ReplayPacket.PuzzleDefinition.SizeVector, TArray<int32>({3, 3, 3, 3, 3}));
	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistHigherDimensionalPhase6CRunStateActivationResolutionTest,
	"HyperTwist.FirstParty.HigherDimensional.Phase6C.RunStateActivationResolution",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistHigherDimensionalPhase6CRunStateActivationResolutionTest::RunTest(const FString& Parameters)
{
	const FHyperTwistTrainingRunState Magic120CellRun = UHyperTwistTrainingLibrary::StartTrainingRun(
		HyperTwistHigherDimensionalPhase6CTestInternal::MakeDeck(
			TEXT("phase6c/magic120cell-resolution"),
			TEXT("polychoron/magic120cell")
		),
		TEXT("phase6c-user"),
		TEXT("phase6c-magic120cell-resolution-session"),
		EHyperTwistTrainingDeliveryMode::VirtualCube
	);
	TestTrue(TEXT("The Magic120Cell resolution run must start structurally valid."), Magic120CellRun.IsStructurallyValid());

	FHyperTwistTrainingHigherDimensionalRuntimeActivationProfile Magic120CellProfile;
	TestTrue(
		TEXT("The Magic120Cell run must resolve a higher-dimensional activation profile from its run state."),
		UHyperTwistTrainingRuntimeLibrary::TryGetHigherDimensionalRuntimeActivationProfileForRunState(
			Magic120CellRun,
			Magic120CellProfile
		)
	);
	TestEqual(TEXT("The Magic120Cell run must resolve the canonical activation profile id."), Magic120CellProfile.ActivationProfileId, TEXT("magic120cell-cleanroom-runtime-activation"));
	TestEqual(TEXT("The Magic120Cell run must resolve the canonical runtime mode id."), Magic120CellProfile.RuntimeModeId, TEXT("magic120cell-full-color-runtime-v1"));

	FHyperTwistTrainingRunState RuntimeModeFallbackRun = UHyperTwistTrainingLibrary::StartTrainingRun(
		HyperTwistHigherDimensionalPhase6CTestInternal::MakeDeck(
			TEXT("phase6c/runtime-mode-fallback"),
			TEXT("cube/3x3x3")
		),
		TEXT("phase6c-user"),
		TEXT("phase6c-runtime-mode-fallback-session"),
		EHyperTwistTrainingDeliveryMode::VirtualCube
	);
	TestTrue(TEXT("The runtime-mode fallback run must start structurally valid."), RuntimeModeFallbackRun.IsStructurallyValid());

	RuntimeModeFallbackRun.ImportedGeneratedModeLaunchRequest =
		HyperTwistHigherDimensionalPhase6CTestInternal::MakeGeneratedModeLaunchRequest(
			RuntimeModeFallbackRun.ActiveDeck.DeckId,
			RuntimeModeFallbackRun.Session.TrainingSessionId,
			TEXT("cube/3x3x3"),
			TEXT("magiccube5d-order3-runtime-v1")
		);
	TestTrue(
		TEXT("The runtime-mode fallback launch request must stay structurally valid."),
		RuntimeModeFallbackRun.ImportedGeneratedModeLaunchRequest.IsStructurallyValid()
	);

	FHyperTwistTrainingHigherDimensionalRuntimeActivationProfile RuntimeModeProfile;
	TestTrue(
		TEXT("The runtime-mode fallback run must resolve by runtime mode id even when the run puzzle is not higher-dimensional."),
		UHyperTwistTrainingRuntimeLibrary::TryGetHigherDimensionalRuntimeActivationProfileForRunState(
			RuntimeModeFallbackRun,
			RuntimeModeProfile
		)
	);
	TestEqual(TEXT("The runtime-mode fallback run must resolve the MagicCube5D activation profile."), RuntimeModeProfile.ActivationProfileId, TEXT("magiccube5d-cleanroom-runtime-activation"));
	TestEqual(TEXT("The runtime-mode fallback run must resolve the canonical MagicCube5D puzzle id."), RuntimeModeProfile.PuzzleId, TEXT("hypercube/magiccube5d/order3"));

	FHyperTwistPuzzleDefinitionRef RuntimeModeDefinition;
	TestTrue(
		TEXT("The bundled higher-dimensional resolver must also accept runtime mode ids directly."),
		UHyperTwistTrainingRuntimeLibrary::TryResolveBundledHigherDimensionalPuzzleDefinition(
			TEXT("magiccube5d-order3-runtime-v1"),
			RuntimeModeDefinition
		)
	);
	TestEqual(TEXT("The runtime-mode definition resolution must map back to the canonical MagicCube5D puzzle id."), RuntimeModeDefinition.PuzzleId, TEXT("hypercube/magiccube5d/order3"));

	FHyperTwistTrainingRunState ClassicRun = UHyperTwistTrainingLibrary::StartTrainingRun(
		HyperTwistHigherDimensionalPhase6CTestInternal::MakeDeck(
			TEXT("phase6c/classic-negative"),
			TEXT("cube/3x3x3")
		),
		TEXT("phase6c-user"),
		TEXT("phase6c-classic-negative-session"),
		EHyperTwistTrainingDeliveryMode::VirtualCube
	);
	TestTrue(TEXT("The classic negative-control run must start structurally valid."), ClassicRun.IsStructurallyValid());

	FHyperTwistTrainingHigherDimensionalRuntimeActivationProfile MissingProfile;
	TestFalse(
		TEXT("A classic run without a higher-dimensional imported launch request must not resolve an activation profile."),
		UHyperTwistTrainingRuntimeLibrary::TryGetHigherDimensionalRuntimeActivationProfileForRunState(
			ClassicRun,
			MissingProfile
		)
	);
	TestFalse(TEXT("The negative-control resolved profile must stay empty."), MissingProfile.IsStructurallyValid());
	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistHigherDimensionalPhase6CLaunchExecutionTest,
	"HyperTwist.FirstParty.HigherDimensional.Phase6C.LaunchExecution",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistHigherDimensionalPhase6CLaunchExecutionTest::RunTest(const FString& Parameters)
{
	UHyperTwistTrainingSubsystem* TrainingSubsystem =
		HyperTwistHigherDimensionalPhase6CTestInternal::MakeTrainingSubsystem();
	TestNotNull(
		TEXT("The Phase 6C launch-execution proof must allocate the training subsystem."),
		TrainingSubsystem
	);
	if (TrainingSubsystem == nullptr)
	{
		return false;
	}

	FHyperTwistTrainingRunState StartedRunState;
	FString BlockedReason;
	TestTrue(
		TEXT("The MagicCube5D launch surface must start and execute a generated-mode run."),
		TrainingSubsystem->TryStartHigherDimensionalLaunchSurface(
			TEXT("magiccube5d-cleanroom-runtime-activation"),
			TEXT("phase6c-user"),
			TEXT("phase6c-launch-execution-session"),
			EHyperTwistTrainingDeliveryMode::VirtualCube,
			true,
			StartedRunState,
			BlockedReason
		)
	);
	TestTrue(
		TEXT("The launch-execution proof must not report a blocked reason."),
		BlockedReason.IsEmpty()
	);
	TestTrue(
		TEXT("The launch-execution proof must return a structurally valid owned run."),
		StartedRunState.IsStructurallyValid()
	);
	TestTrue(
		TEXT("The launch-execution proof must persist a generated-mode launch request."),
		StartedRunState.ImportedGeneratedModeLaunchRequest.IsStructurallyValid()
	);
	TestEqual(
		TEXT("The launch-execution proof must preserve the generated runtime mode."),
		StartedRunState.ImportedGeneratedModeLaunchRequest.LaunchConfig.RuntimeModeId,
		TEXT("magiccube5d-order3-runtime-v1")
	);
	TestEqual(
		TEXT("The launch-execution proof must preserve the generated runtime surface id."),
		StartedRunState.ImportedGeneratedModeLaunchRequest.LaunchConfig.SurfaceId,
		TEXT("phase6c/magiccube5d/generated-runtime-surface")
	);
	TestEqual(
		TEXT("The launch-execution proof must persist the merged higher-dimensional selector posture."),
		StartedRunState.ImportedGeneratedModeLaunchRequest.LaunchConfig.SelectorChoices.Num(),
		5
	);
	TestTrue(
		TEXT("The launch-execution proof must preserve the generated-mode execution tag."),
		StartedRunState.ActiveDeck.Tags.Contains(TEXT("generated-mode:owned-execution"))
	);
	TestEqual(
		TEXT("The launch-execution proof must keep the merged runtime surface selector set on the active deck."),
		StartedRunState.ActiveDeck.ImportedRuntimeSurface.Selectors.Num(),
		5
	);
	TestEqual(
		TEXT("The launch-execution proof must keep the merged selector posture on the active run-state selection state."),
		StartedRunState.ImportedRuntimeSelectionState.SelectorChoices.Num(),
		5
	);

	FHyperTwistTrainingHigherDimensionalRuntimeActivationProfile ActivationProfile;
	TestTrue(
		TEXT("The launch-execution proof must resolve the active higher-dimensional activation profile."),
		UHyperTwistTrainingRuntimeLibrary::TryGetHigherDimensionalRuntimeActivationProfileForRunState(
			StartedRunState,
			ActivationProfile
		)
	);
	TestEqual(
		TEXT("The launch-execution proof must stay bound to the MagicCube5D activation profile."),
		ActivationProfile.ActivationProfileId,
		TEXT("magiccube5d-cleanroom-runtime-activation")
	);

	FHyperTwistTrainingHigherDimensionalRuntimeLaunchSurface LaunchSurface;
	TestTrue(
		TEXT("The launch-execution proof must resolve the active higher-dimensional launch surface."),
		UHyperTwistTrainingRuntimeLibrary::TryGetHigherDimensionalRuntimeLaunchSurfaceForRunState(
			StartedRunState,
			LaunchSurface
		)
	);
	TestEqual(
		TEXT("The launch-execution proof must preserve the dedicated host map route."),
		LaunchSurface.HostMapPath,
		TEXT("/Game/HyperTwistTraining/Maps/L_HyperTwist_MagicCube5DTraining")
	);
	TestFalse(
		TEXT("The launch-execution proof must no longer keep the shared-map fallback posture."),
		LaunchSurface.bUsesSharedTrainingMapFallback
	);
	TestEqual(
		TEXT("The launch-execution proof must preserve the launch surface persistence boundary."),
		LaunchSurface.PrimaryPersistenceBoundaryId,
		TEXT("magiccube5d-persistence-boundary")
	);
	TestEqual(
		TEXT("The launch-execution proof must preserve the resolved launch surface id."),
		LaunchSurface.LaunchSurfaceId,
		TEXT("phase6c/magiccube5d/dedicated-training-launch-surface")
	);
	TestEqual(
		TEXT("The launch-execution proof must preserve the resolved host surface id."),
		LaunchSurface.HostSurfaceId,
		TEXT("phase6c/magiccube5d/runtime-host-surface")
	);

	FHyperTwistTrainingHigherDimensionalRuntimeHostSurface HostSurface;
	TestTrue(
		TEXT("The launch-execution proof must resolve the active higher-dimensional host surface."),
		UHyperTwistTrainingRuntimeLibrary::TryGetHigherDimensionalRuntimeHostSurfaceForRunState(
			StartedRunState,
			HostSurface
		)
	);
	TestEqual(
		TEXT("The launch-execution proof must preserve the preferred dedicated host target."),
		HostSurface.PreferredHostMapPath,
		TEXT("/Game/HyperTwistTraining/Maps/L_HyperTwist_MagicCube5DTraining")
	);
	TestEqual(
		TEXT("The launch-execution proof must preserve the effective dedicated host route."),
		HostSurface.EffectiveHostMapRouteId,
		TEXT("phase6c/magiccube5d/dedicated-training-map-host")
	);
	TestFalse(
		TEXT("The launch-execution proof must no longer keep the shared-host fallback posture explicit."),
		HostSurface.bUsesSharedTrainingMapFallback
	);

	FHyperTwistTrainingHigherDimensionalRuntimeViewContextSurface ViewContextSurface;
	TestTrue(
		TEXT("The launch-execution proof must resolve the active higher-dimensional view-context surface."),
		UHyperTwistTrainingRuntimeLibrary::TryGetHigherDimensionalRuntimeViewContextSurfaceForRunState(
			StartedRunState,
			ViewContextSurface
		)
	);
	TestEqual(
		TEXT("The launch-execution proof must preserve the resolved view-context surface id."),
		ViewContextSurface.ViewContextSurfaceId,
		TEXT("phase6c/magiccube5d/dedicated-training-view-context-surface")
	);
	TestEqual(
		TEXT("The launch-execution proof must preserve the dedicated view-profile contract."),
		ViewContextSurface.PrimaryViewProfileContractId,
		TEXT("magiccube5d-projection-view-profile")
	);
	TestEqual(
		TEXT("The launch-execution proof must preserve four default view selector choices."),
		ViewContextSurface.DefaultSelectorChoices.Num(),
		4
	);

	FHyperTwistTrainingHigherDimensionalRuntimeSessionSurface SessionSurface;
	TestTrue(
		TEXT("The launch-execution proof must resolve the active higher-dimensional session surface."),
		UHyperTwistTrainingRuntimeLibrary::TryGetHigherDimensionalRuntimeSessionSurfaceForRunState(
			StartedRunState,
			SessionSurface
		)
	);
	TestEqual(
		TEXT("The launch-execution proof must preserve the resolved session surface id."),
		SessionSurface.SessionSurfaceId,
		TEXT("phase6c/magiccube5d/dedicated-training-session-surface")
	);
	TestEqual(
		TEXT("The launch-execution proof must preserve the merged session selector count."),
		SessionSurface.DefaultSelectorChoices.Num(),
		5
	);
	TestTrue(
		TEXT("The launch-execution proof must record the explicit higher-dimensional session surface in runtime lineage."),
		StartedRunState.ActiveDeck.ImportedRuntimeSurface.OriginPaths.Contains(
			TEXT("phase6c/magiccube5d/dedicated-training-session-surface")
		)
	);

	FHyperTwistTrainingHigherDimensionalInteractiveSceneSurface InteractiveSceneSurface;
	TestTrue(
		TEXT("The launch-execution proof must resolve the active higher-dimensional interactive scene surface."),
		UHyperTwistTrainingRuntimeLibrary::TryGetHigherDimensionalInteractiveSceneSurfaceForRunState(
			StartedRunState,
			InteractiveSceneSurface
		)
	);
	TestEqual(
		TEXT("The launch-execution proof must preserve the resolved interactive scene surface id."),
		InteractiveSceneSurface.SceneSurfaceId,
		TEXT("phase6c/magiccube5d/interactive-scene-surface")
	);
	TestTrue(
		TEXT("The launch-execution proof must keep the interactive scene renderable."),
		UHyperTwistSimulationLibrary::CanRenderSceneContext(InteractiveSceneSurface.SceneContext)
	);
	TestEqual(
		TEXT("The launch-execution proof must preserve the interactive-scene context id."),
		InteractiveSceneSurface.SceneContext.SceneContextId,
		TEXT("phase6c/magiccube5d/interactive-scene-context")
	);
	TestEqual(
		TEXT("The launch-execution proof must preserve the interactive-scene encoding profile."),
		InteractiveSceneSurface.SceneContext.PuzzleState.StateEncoding.EncodingProfile,
		TEXT("magiccube5d-family-owned-scene-state-v1")
	);
	TestFalse(
		TEXT("The launch-execution proof must no longer keep the placeholder interactive-scene posture."),
		InteractiveSceneSurface.bUsesPlaceholderStateEnvelope
	);
	TestTrue(
		TEXT("The launch-execution proof must record the explicit higher-dimensional interactive scene surface in runtime lineage."),
		StartedRunState.ActiveDeck.ImportedRuntimeSurface.OriginPaths.Contains(
			TEXT("phase6c/magiccube5d/interactive-scene-surface")
		)
	);
	TestTrue(
		TEXT("The launch-execution proof must record the interactive scene context in runtime lineage."),
		StartedRunState.ActiveDeck.ImportedRuntimeSurface.OriginPaths.Contains(
			TEXT("phase6c/magiccube5d/interactive-scene-context")
		)
	);

	FHyperTwistTrainingMagicCube5DInteractiveSceneStateEnvelope MagicCube5DEnvelope;
	TestTrue(
		TEXT("The launch-execution proof must decode the active MagicCube5D scene-state envelope."),
		UHyperTwistTrainingRuntimeLibrary::TryDecodeMagicCube5DInteractiveSceneStateEnvelope(
			InteractiveSceneSurface.SceneContext,
			MagicCube5DEnvelope
		)
	);
	TestEqual(
		TEXT("The launch-execution proof must keep the dedicated session linkage inside the decoded envelope."),
		MagicCube5DEnvelope.SessionSurfaceId,
		TEXT("phase6c/magiccube5d/dedicated-training-session-surface")
	);
	TestEqual(
		TEXT("The launch-execution proof must keep the compact twist-history format inside the decoded envelope."),
		MagicCube5DEnvelope.TwistHistoryFormatId,
		TEXT("magiccube5d/compact-twist-token-v1")
	);
	return true;
}

#endif
