// Copyright HyperTwist, Inc. All Rights Reserved.

#include "Misc/AutomationTest.h"

#include "HyperTwistBootstrap/HyperTwistContractLibrary.h"

#if WITH_AUTOMATION_TESTS

namespace HyperTwistMemoryPhase6RM4TestInternal
{
	const FHyperTwistMemoryCognitiveFact* FindFactByFamily(
		const FHyperTwistMemoryCognitiveConsolidationState& CognitiveState,
		const FString& FactFamily
	)
	{
		for (const FHyperTwistMemoryCognitiveFact& Fact : CognitiveState.Facts)
		{
			if (Fact.FactFamily == FactFamily)
			{
				return &Fact;
			}
		}

		return nullptr;
	}

	const FHyperTwistMemoryCognitiveFact* FindFactByKind(
		const FHyperTwistMemoryCognitiveConsolidationState& CognitiveState,
		const FString& FactKind
	)
	{
		for (const FHyperTwistMemoryCognitiveFact& Fact : CognitiveState.Facts)
		{
			if (Fact.FactKind == FactKind)
			{
				return &Fact;
			}
		}

		return nullptr;
	}
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistMemoryPhase6RM4FactExtractionTest,
	"HyperTwist.FirstParty.Memory.Phase6R.M4.FactExtraction",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistMemoryPhase6RM4FactExtractionTest::RunTest(const FString& Parameters)
{
	const FHyperTwistMemoryCognitiveConsolidationState CognitiveState =
		UHyperTwistContractLibrary::MakeSampleTrainingMemoryCognitiveConsolidationState();

	TestTrue(
		TEXT("The Phase 6R-M4 cognitive consolidation state must be structurally valid."),
		CognitiveState.IsStructurallyValid()
	);
	TestTrue(
		TEXT("The M4 state must expose bounded cognitive facts."),
		CognitiveState.Facts.Num() >= 5
	);
	TestTrue(
		TEXT("The M4 state must expose active cognitive facts."),
		CognitiveState.ActiveFactCount > 0
	);

	const FHyperTwistMemoryCognitiveFact* FollowUpFact =
		HyperTwistMemoryPhase6RM4TestInternal::FindFactByFamily(
			CognitiveState,
			TEXT("follow-up-posture")
		);
	TestNotNull(TEXT("A follow-up-posture cognitive fact must exist."), FollowUpFact);
	if (FollowUpFact != nullptr)
	{
		TestEqual(
			TEXT("The follow-up-posture fact must stay in the cognitive lane."),
			FollowUpFact->Lane,
			EHyperTwistMemoryLane::CognitiveConsolidated
		);
		TestTrue(
			TEXT("The follow-up-posture fact must preserve provenance links."),
			FollowUpFact->ProvenanceLinks.Num() > 0
		);
	}

	const FHyperTwistMemoryCognitiveFact* ArchiveFact =
		HyperTwistMemoryPhase6RM4TestInternal::FindFactByFamily(
			CognitiveState,
			TEXT("archive-posture")
		);
	TestNotNull(TEXT("An archive-posture cognitive fact must exist."), ArchiveFact);

	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistMemoryPhase6RM4ContradictionSupersessionTest,
	"HyperTwist.FirstParty.Memory.Phase6R.M4.ContradictionSupersession",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistMemoryPhase6RM4ContradictionSupersessionTest::RunTest(const FString& Parameters)
{
	const FHyperTwistMemoryCognitiveConsolidationState CognitiveState =
		UHyperTwistContractLibrary::MakeSampleTrainingMemoryCognitiveConsolidationState();

	TestTrue(
		TEXT("The Phase 6R-M4 cognitive consolidation state must be structurally valid."),
		CognitiveState.IsStructurallyValid()
	);
	TestTrue(
		TEXT("The M4 state must expose contradiction records."),
		CognitiveState.Contradictions.Num() > 0
	);
	TestTrue(
		TEXT("The M4 state must expose supersession records."),
		CognitiveState.Supersessions.Num() > 0
	);
	TestTrue(
		TEXT("The M4 state must expose confidence-decay records."),
		CognitiveState.ConfidenceDecays.Num() > 0
	);
	TestTrue(
		TEXT("The M4 state must report open cognitive review."),
		CognitiveState.bHasOpenCognitiveReview
	);

	bool bHasExplicitlyReviewedFact = false;
	for (const FHyperTwistMemoryCognitiveFact& Fact : CognitiveState.Facts)
	{
		if (Fact.bRequiresReview
			&& (Fact.ContradictionIds.Num() > 0 || !Fact.SupersededByFactId.IsEmpty()))
		{
			bHasExplicitlyReviewedFact = true;
			break;
		}
	}
	TestTrue(
		TEXT("At least one contradicted or superseded cognitive fact must be marked for explicit review."),
		bHasExplicitlyReviewedFact
	);

	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistMemoryPhase6RM4SerializationRoundTripTest,
	"HyperTwist.FirstParty.Memory.Phase6R.M4.SerializationRoundTrip",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistMemoryPhase6RM4SerializationRoundTripTest::RunTest(const FString& Parameters)
{
	const FHyperTwistMemoryCognitiveConsolidationState CognitiveState =
		UHyperTwistContractLibrary::MakeSampleTrainingMemoryCognitiveConsolidationState();
	TestTrue(
		TEXT("The Phase 6R-M4 cognitive consolidation state must be structurally valid."),
		CognitiveState.IsStructurallyValid()
	);

	const FString Json =
		UHyperTwistContractLibrary::SerializeMemoryCognitiveConsolidationStateToJson(
			CognitiveState
		);
	TestFalse(TEXT("The serialized M4 JSON must not be empty."), Json.IsEmpty());
	TestTrue(
		TEXT("The serialized M4 JSON must expose contradiction records."),
		Json.Contains(TEXT("Contradictions"))
	);

	FHyperTwistMemoryCognitiveConsolidationState RoundTrippedState;
	TestTrue(
		TEXT("The M4 JSON must deserialize cleanly."),
		UHyperTwistContractLibrary::DeserializeMemoryCognitiveConsolidationStateFromJson(
			Json,
			RoundTrippedState
		)
	);
	TestTrue(
		TEXT("The round-tripped M4 state must remain structurally valid."),
		RoundTrippedState.IsStructurallyValid()
	);
	TestEqual(
		TEXT("The round-tripped M4 state must preserve fact counts."),
		RoundTrippedState.Facts.Num(),
		CognitiveState.Facts.Num()
	);
	TestEqual(
		TEXT("The round-tripped M4 state must preserve contradiction counts."),
		RoundTrippedState.Contradictions.Num(),
		CognitiveState.Contradictions.Num()
	);
	TestEqual(
		TEXT("The round-tripped M4 state must preserve supersession counts."),
		RoundTrippedState.Supersessions.Num(),
		CognitiveState.Supersessions.Num()
	);
	TestEqual(
		TEXT("The round-tripped M4 state must preserve confidence-decay counts."),
		RoundTrippedState.ConfidenceDecays.Num(),
		CognitiveState.ConfidenceDecays.Num()
	);

	return true;
}

#endif
