// Copyright HyperTwist, Inc. All Rights Reserved.

#include "Misc/AutomationTest.h"

#include "HyperTwistBootstrap/HyperTwistContractLibrary.h"

#if WITH_AUTOMATION_TESTS

namespace HyperTwistMemoryPhase6RM5TestInternal
{
	const FHyperTwistMemoryKnowledgeObject* FindKnowledgeObjectByKind(
		const FHyperTwistMemoryKnowledgeNotesState& KnowledgeNotesState,
		const FString& ObjectKind
	)
	{
		for (const FHyperTwistMemoryKnowledgeObject& KnowledgeObject :
			KnowledgeNotesState.KnowledgeObjects)
		{
			if (KnowledgeObject.ObjectKind == ObjectKind)
			{
				return &KnowledgeObject;
			}
		}

		return nullptr;
	}
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistMemoryPhase6RM5KnowledgeObjectsTest,
	"HyperTwist.FirstParty.Memory.Phase6R.M5.KnowledgeObjects",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistMemoryPhase6RM5KnowledgeObjectsTest::RunTest(const FString& Parameters)
{
	const FHyperTwistMemoryKnowledgeNotesState KnowledgeNotesState =
		UHyperTwistContractLibrary::MakeSampleTrainingMemoryKnowledgeNotesState();

	TestTrue(
		TEXT("The Phase 6R-M5 knowledge and notes state must be structurally valid."),
		KnowledgeNotesState.IsStructurallyValid()
	);
	TestTrue(
		TEXT("The M5 state must expose knowledge objects."),
		KnowledgeNotesState.KnowledgeObjects.Num() > 0
	);
	TestTrue(
		TEXT("The M5 state must keep the knowledge lane enabled."),
		KnowledgeNotesState.bKnowledgeWikiEnabled
	);
	TestTrue(
		TEXT("The M5 state must expose curated reference objects."),
		KnowledgeNotesState.CuratedReferenceObjectCount > 0
	);

	const FHyperTwistMemoryKnowledgeObject* TaxonomyObject =
		HyperTwistMemoryPhase6RM5TestInternal::FindKnowledgeObjectByKind(
			KnowledgeNotesState,
			TEXT("taxonomy-node")
		);
	TestNotNull(TEXT("A taxonomy-node knowledge object must exist."), TaxonomyObject);
	if (TaxonomyObject != nullptr)
	{
		TestEqual(
			TEXT("Knowledge objects must stay in the knowledge/wiki lane."),
			TaxonomyObject->Lane,
			EHyperTwistMemoryLane::KnowledgeWiki
		);
		TestTrue(
			TEXT("Knowledge objects must preserve provenance links."),
			TaxonomyObject->ProvenanceLinks.Num() > 0
		);
	}

	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistMemoryPhase6RM5PromotionAndNotesTest,
	"HyperTwist.FirstParty.Memory.Phase6R.M5.PromotionAndNotes",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistMemoryPhase6RM5PromotionAndNotesTest::RunTest(const FString& Parameters)
{
	const FHyperTwistMemoryKnowledgeNotesState KnowledgeNotesState =
		UHyperTwistContractLibrary::MakeSampleTrainingMemoryKnowledgeNotesState();

	TestTrue(
		TEXT("The Phase 6R-M5 knowledge and notes state must be structurally valid."),
		KnowledgeNotesState.IsStructurallyValid()
	);
	TestTrue(
		TEXT("The M5 state must expose reviewable promotion flows."),
		KnowledgeNotesState.PromotionReviews.Num() > 0
	);
	TestTrue(
		TEXT("The M5 state must approve at least one stable promotion."),
		KnowledgeNotesState.ApprovedPromotionCount > 0
	);
	TestTrue(
		TEXT("The M5 state must keep at least one promotion blocked or deferred for review safety."),
		KnowledgeNotesState.BlockedPromotionCount > 0
			|| KnowledgeNotesState.DeferredPromotionCount > 0
	);
	TestFalse(
		TEXT("The M5 state must not silently claim an active user-authored note lane."),
		KnowledgeNotesState.bUserNotesLaneAvailable
	);
	TestFalse(
		TEXT("The user-notes posture must keep direct user-authored capture disabled."),
		KnowledgeNotesState.UserNotesPosture.bAcceptsUserAuthoredContent
	);
	TestEqual(
		TEXT("The user-notes posture must stay bound to the user-notes lane."),
		KnowledgeNotesState.UserNotesPosture.Lane,
		EHyperTwistMemoryLane::UserNotes
	);
	TestEqual(
		TEXT("The user-notes posture must point at the canonical user-notes gate."),
		KnowledgeNotesState.UserNotesPosture.GateId,
		TEXT("memory-gate/user-notes")
	);

	const FHyperTwistMemoryKnowledgeObject* PromotedInsightObject =
		HyperTwistMemoryPhase6RM5TestInternal::FindKnowledgeObjectByKind(
			KnowledgeNotesState,
			TEXT("promoted-cognitive-insight")
		);
	TestNotNull(
		TEXT("An approved promoted-cognitive-insight object must exist."),
		PromotedInsightObject
	);

	return true;
}

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

bool FHyperTwistMemoryPhase6RM5SerializationRoundTripTest::RunTest(
	const FString& Parameters
)
{
	const FHyperTwistMemoryKnowledgeNotesState KnowledgeNotesState =
		UHyperTwistContractLibrary::MakeSampleTrainingMemoryKnowledgeNotesState();
	TestTrue(
		TEXT("The Phase 6R-M5 knowledge and notes state must be structurally valid."),
		KnowledgeNotesState.IsStructurallyValid()
	);

	const FString Json =
		UHyperTwistContractLibrary::SerializeMemoryKnowledgeNotesStateToJson(
			KnowledgeNotesState
		);
	TestFalse(TEXT("The serialized M5 JSON must not be empty."), Json.IsEmpty());
	TestTrue(
		TEXT("The serialized M5 JSON must expose user-notes posture."),
		Json.Contains(TEXT("UserNotesPosture"))
	);

	FHyperTwistMemoryKnowledgeNotesState RoundTrippedState;
	TestTrue(
		TEXT("The M5 JSON must deserialize cleanly."),
		UHyperTwistContractLibrary::DeserializeMemoryKnowledgeNotesStateFromJson(
			Json,
			RoundTrippedState
		)
	);
	TestTrue(
		TEXT("The round-tripped M5 state must remain structurally valid."),
		RoundTrippedState.IsStructurallyValid()
	);
	TestEqual(
		TEXT("The round-tripped M5 state must preserve knowledge object counts."),
		RoundTrippedState.KnowledgeObjects.Num(),
		KnowledgeNotesState.KnowledgeObjects.Num()
	);
	TestEqual(
		TEXT("The round-tripped M5 state must preserve promotion-review counts."),
		RoundTrippedState.PromotionReviews.Num(),
		KnowledgeNotesState.PromotionReviews.Num()
	);
	TestEqual(
		TEXT("The round-tripped M5 state must preserve approved-promotion counts."),
		RoundTrippedState.ApprovedPromotionCount,
		KnowledgeNotesState.ApprovedPromotionCount
	);
	TestEqual(
		TEXT("The round-tripped M5 state must preserve blocked-promotion counts."),
		RoundTrippedState.BlockedPromotionCount,
		KnowledgeNotesState.BlockedPromotionCount
	);

	return true;
}

#endif
