// Copyright HyperTwist, Inc. All Rights Reserved.

#include "Misc/AutomationTest.h"

#include "HyperTwistTraining/HyperTwistTrainingRuntimeLibrary.h"

#if WITH_AUTOMATION_TESTS

namespace HyperTwistMagicTilePhase7CTestInternal
{
	FHyperTwistTrainingTilingStateEnvelope MakeSampleStateEnvelope()
	{
		FHyperTwistTrainingTilingStateEnvelope Envelope;
		Envelope.SessionId = TEXT("tiling-native-proof-session-001");
		Envelope.SharedScrambleNotation = TEXT("  R,  U\nm(3,4)\u2019 ; reflect-x  ");

		FHyperTwistPuzzleState& PuzzleState = Envelope.PuzzleState;
		PuzzleState.Definition.PuzzleId = TEXT("tiling/{5,4}/native-proof");
		PuzzleState.Definition.PuzzleFamily = EHyperTwistPuzzleFamily::Tiling;
		PuzzleState.Definition.Dimension = 2;
		PuzzleState.Definition.DefinitionVersion = TEXT("2026.06");
		PuzzleState.Definition.NotationProfile = TEXT("magictile-shared");
		PuzzleState.StateEncoding.EncodingProfile = TEXT("tiling-cells/v1");
		PuzzleState.StateEncoding.PayloadJson =
			TEXT("{\"cells\":[\"c17\",\"c18\"],\"selection\":\"face-17\"}");
		PuzzleState.CapturedAtUtc = TEXT("2026-06-19T04:05:00Z");

		FHyperTwistTrainingLiveTimerState& TimerState = Envelope.TimerState;
		TimerState.Phase = EHyperTwistTrainingLiveTimerPhase::Solving;
		TimerState.SolveElapsedMs = 24680;
		TimerState.DisplayedElapsedMs = 1000;

		return Envelope;
	}
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistMagicTilePhase7CNativeBehaviorProofContractTest,
	"HyperTwist.FirstParty.MagicTile.Phase7C.NativeBehaviorProofContract",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistMagicTilePhase7CNativeBehaviorProofContractTest::RunTest(
	const FString& Parameters
)
{
	const FHyperTwistTrainingTilingReferenceBundle Bundle =
		UHyperTwistTrainingRuntimeLibrary::GetBundledTilingReferenceBundle();

	TestTrue(
		TEXT("The tiling bundle must stay structurally valid after the native behavior proof lands."),
		Bundle.IsStructurallyValid()
	);
	TestEqual(
		TEXT("The primary native behavior proof contract id must stay stable."),
		Bundle.PrimaryNativeBehaviorProofContractId,
		TEXT("tiling-native-behavior-proof")
	);

	FHyperTwistTrainingTilingNativeBehaviorProofContract Contract;
	TestTrue(
		TEXT("The native behavior proof contract must resolve from the runtime library."),
		UHyperTwistTrainingRuntimeLibrary::TryGetBundledTilingNativeBehaviorProofContract(
			Bundle.PrimaryNativeBehaviorProofContractId,
			Contract
		)
	);
	TestEqual(
		TEXT("The native behavior proof contract must stay anchored to the browser host decision."),
		Contract.HostDecisionId,
		Bundle.PrimaryHostDecisionId
	);
	TestEqual(
		TEXT("The native behavior proof contract must stay anchored to the browser state bridge contract."),
		Contract.StateBridgeContractId,
		Bundle.PrimaryStateBridgeContractId
	);
	TestTrue(
		TEXT("The native behavior proof contract must preserve selected-cell focus."),
		Contract.NativeInputSurfaceTags.Contains(TEXT("selected cell focus"))
	);
	TestTrue(
		TEXT("The native behavior proof contract must preserve candidate-twist disambiguation."),
		Contract.NativeInputSurfaceTags.Contains(TEXT("candidate twist disambiguation"))
	);
	TestTrue(
		TEXT("The native behavior proof contract must preserve a native preview token."),
		Contract.NativeStateSurfaceTags.Contains(TEXT("native preview transform token"))
	);
	TestTrue(
		TEXT("The native behavior proof contract must explicitly exclude full renderer-port ownership."),
		Contract.ExplicitExclusions.Contains(TEXT("whole renderer port ownership"))
	);
	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistMagicTilePhase7CNativeBehaviorProofProbeCreationTest,
	"HyperTwist.FirstParty.MagicTile.Phase7C.NativeBehaviorProofProbeCreation",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistMagicTilePhase7CNativeBehaviorProofProbeCreationTest::RunTest(
	const FString& Parameters
)
{
	const FHyperTwistTrainingTilingNativeBehaviorProofProbe Probe =
		UHyperTwistTrainingRuntimeLibrary::CreateBundledTilingNativeBehaviorProofProbe(
			HyperTwistMagicTilePhase7CTestInternal::MakeSampleStateEnvelope(),
			TEXT("  cell-17  "),
			{TEXT(" twist/left "), TEXT(""), TEXT("twist/right"), TEXT("twist/left")},
			FString(),
			FString()
		);

	TestTrue(
		TEXT("The created native behavior proof probe must be structurally valid."),
		Probe.IsStructurallyValid()
	);
	TestEqual(
		TEXT("The proof probe must keep the canonical contract id."),
		Probe.ProofContractId,
		TEXT("tiling-native-behavior-proof")
	);
	TestEqual(
		TEXT("The proof probe must stay anchored to the browser-state bridge id."),
		Probe.StateBridgeContractId,
		TEXT("tiling-browser-state-bridge")
	);
	TestEqual(
		TEXT("The proof probe must normalize the selected cell id."),
		Probe.SelectedCellId,
		TEXT("cell-17")
	);
	TestEqual(
		TEXT("The proof probe must de-duplicate candidate twist ids."),
		Probe.CandidateTwistIds.Num(),
		2
	);
	if (Probe.CandidateTwistIds.Num() != 2)
	{
		return false;
	}
	TestEqual(
		TEXT("The proof probe must preserve the first normalized candidate twist id."),
		Probe.CandidateTwistIds[0],
		TEXT("twist/left")
	);
	TestEqual(
		TEXT("The proof probe must preserve the second normalized candidate twist id."),
		Probe.CandidateTwistIds[1],
		TEXT("twist/right")
	);
	TestEqual(
		TEXT("The proof probe must normalize the shared scramble notation."),
		Probe.SharedScrambleNotation,
		TEXT("R U m(3,4)' reflect-x")
	);
	TestEqual(
		TEXT("The proof probe must repair the timer session id from the proof session."),
		Probe.TimerState.TrainingSessionId,
		Probe.SessionId
	);
	TestEqual(
		TEXT("The proof probe must align displayed elapsed time with solve elapsed time."),
		Probe.TimerState.DisplayedElapsedMs,
		24680
	);
	TestEqual(
		TEXT("The proof probe must derive the preview token from the selected cell and committed twist when needed."),
		Probe.PreviewTransformToken,
		TEXT("native-preview::cell-17::twist/left")
	);
	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistMagicTilePhase7CNativeBehaviorProofProbeSerializationTest,
	"HyperTwist.FirstParty.MagicTile.Phase7C.NativeBehaviorProofProbeSerialization",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistMagicTilePhase7CNativeBehaviorProofProbeSerializationTest::RunTest(
	const FString& Parameters
)
{
	const FHyperTwistTrainingTilingNativeBehaviorProofProbe Probe =
		UHyperTwistTrainingRuntimeLibrary::CreateBundledTilingNativeBehaviorProofProbe(
			HyperTwistMagicTilePhase7CTestInternal::MakeSampleStateEnvelope(),
			TEXT("cell-99"),
			{TEXT("twist/up")},
			TEXT("twist/up"),
			TEXT("preview-token-99")
		);

	FString Json;
	TestTrue(
		TEXT("The native behavior proof probe must serialize to JSON."),
		UHyperTwistTrainingRuntimeLibrary::TrySerializeBundledTilingNativeBehaviorProofProbeToJson(
			Probe,
			Json
		)
	);
	TestFalse(TEXT("The serialized proof probe JSON must not be empty."), Json.IsEmpty());

	FHyperTwistTrainingTilingNativeBehaviorProofProbe RoundTrippedProbe;
	TestTrue(
		TEXT("The native behavior proof probe must deserialize from JSON."),
		UHyperTwistTrainingRuntimeLibrary::TryDeserializeBundledTilingNativeBehaviorProofProbeFromJson(
			Json,
			RoundTrippedProbe
		)
	);
	TestEqual(
		TEXT("The round-tripped proof probe must preserve the puzzle definition id."),
		RoundTrippedProbe.PuzzleDefinitionId,
		TEXT("tiling/{5,4}/native-proof")
	);
	TestEqual(
		TEXT("The round-tripped proof probe must preserve the committed twist id."),
		RoundTrippedProbe.CommitTwistId,
		TEXT("twist/up")
	);
	TestEqual(
		TEXT("The round-tripped proof probe must preserve the preview token."),
		RoundTrippedProbe.PreviewTransformToken,
		TEXT("preview-token-99")
	);
	TestEqual(
		TEXT("The round-tripped proof probe must preserve the native source runtime."),
		RoundTrippedProbe.SourceRuntime,
		TEXT("native-unreal-proof")
	);
	return true;
}

#endif
