// Copyright HyperTwist, Inc. All Rights Reserved.

#include "Misc/AutomationTest.h"

#include "HyperTwistBootstrap/HyperTwistContractLibrary.h"

#if WITH_AUTOMATION_TESTS

namespace HyperTwistSkillPhaseS3ATestInternal
{
	const FHyperTwistSkillContinuityResumeSkill* FindSkillById(
		const FHyperTwistSkillContinuityResumeState& ContinuityState,
		const FString& SkillId
	)
	{
		for (const FHyperTwistSkillContinuityResumeSkill& Skill : ContinuityState.Skills)
		{
			if (Skill.SkillId == SkillId)
			{
				return &Skill;
			}
		}

		return nullptr;
	}
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistSkillPhaseS3AContinuityResumeCoverageTest,
	"HyperTwist.FirstParty.Skill.PhaseS3A.ContinuityResumeCoverage",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistSkillPhaseS3AContinuityResumeCoverageTest::RunTest(const FString& Parameters)
{
	const FHyperTwistSkillContinuityResumeState ContinuityState =
		UHyperTwistContractLibrary::MakeSampleSkillContinuityResumeState();

	TestTrue(
		TEXT("The sample S3-A continuity/resume skill state should be structurally valid."),
		ContinuityState.IsStructurallyValid()
	);
	TestEqual(
		TEXT("S3-A should expose three continuity-family skills."),
		ContinuityState.SkillCount,
		3
	);
	TestEqual(
		TEXT("S3-A should expose two live continuity-family skills."),
		ContinuityState.LiveSkillCount,
		2
	);
	TestEqual(
		TEXT("S3-A should keep one pending continuity-family skill."),
		ContinuityState.PendingSkillCount,
		1
	);
	TestEqual(
		TEXT("S3-A should expose two currently available continuity-family skills in the sample state."),
		ContinuityState.AvailableNowCount,
		2
	);

	const FHyperTwistSkillContinuityResumeSkill* ResumeSkill =
		HyperTwistSkillPhaseS3ATestInternal::FindSkillById(
			ContinuityState,
			TEXT("skill/resume-session")
		);
	TestNotNull(
		TEXT("The resume-session skill should exist."),
		ResumeSkill
	);
	if (ResumeSkill != nullptr)
	{
		TestEqual(
			TEXT("The resume-session skill should bind to the bounded resume brief artifact."),
			ResumeSkill->OutputArtifactKinds[0],
			FString(TEXT("artifact/resume-session-brief"))
		);
	}

	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistSkillPhaseS3AAuthoritativeStoreReadTest,
	"HyperTwist.FirstParty.Skill.PhaseS3A.AuthoritativeStoreRead",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistSkillPhaseS3AAuthoritativeStoreReadTest::RunTest(const FString& Parameters)
{
	const FHyperTwistSkillContinuityResumeState ContinuityState =
		UHyperTwistContractLibrary::MakeSampleSkillContinuityResumeState();

	TestTrue(
		TEXT("The sample S3-A continuity/resume skill state should be structurally valid."),
		ContinuityState.IsStructurallyValid()
	);
	TestTrue(
		TEXT("Every live S3-A skill should read authoritative stores."),
		ContinuityState.bEveryLiveSkillReadsAuthoritativeStores
	);
	TestTrue(
		TEXT("Every live S3-A skill should keep validation-harness coverage."),
		ContinuityState.bEveryLiveSkillHasValidationHarnessCoverage
	);
	TestTrue(
		TEXT("S3-A must not claim active user-authored note capture without separate owner activation."),
		ContinuityState.bNoSkillClaimsActiveUserNoteCaptureWithoutOwnerActivation
	);

	const FHyperTwistSkillContinuityResumeSkill* CaptureNoteSkill =
		HyperTwistSkillPhaseS3ATestInternal::FindSkillById(
			ContinuityState,
			TEXT("skill/capture-note")
		);
	TestNotNull(
		TEXT("The capture-note skill should exist."),
		CaptureNoteSkill
	);
	if (CaptureNoteSkill != nullptr)
	{
		TestFalse(
			TEXT("The capture-note skill should not claim live availability yet."),
			CaptureNoteSkill->bAvailableNow
		);
		TestFalse(
			TEXT("The capture-note skill should not claim live runtime behavior yet."),
			CaptureNoteSkill->bLiveSkill
		);
		TestTrue(
			TEXT("The capture-note skill should require separate owner activation."),
			CaptureNoteSkill->bRequiresOwnerActivation
		);
	}

	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistSkillPhaseS3ASerializationRoundTripTest,
	"HyperTwist.FirstParty.Skill.PhaseS3A.SerializationRoundTrip",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistSkillPhaseS3ASerializationRoundTripTest::RunTest(const FString& Parameters)
{
	const FHyperTwistSkillContinuityResumeState ContinuityState =
		UHyperTwistContractLibrary::MakeSampleSkillContinuityResumeState();

	TestTrue(
		TEXT("The sample S3-A continuity/resume skill state should be structurally valid before serialization."),
		ContinuityState.IsStructurallyValid()
	);

	const FString Json =
		UHyperTwistContractLibrary::SerializeSkillContinuityResumeStateToJson(
			ContinuityState
		);
	TestTrue(
		TEXT("Serialized S3-A JSON should include the user-note-capture owner-activation guard field."),
		Json.Contains(TEXT("bNoSkillClaimsActiveUserNoteCaptureWithoutOwnerActivation"))
	);

	FHyperTwistSkillContinuityResumeState RoundTrippedState;
	TestTrue(
		TEXT("Deserializing the S3-A continuity/resume JSON should succeed."),
		UHyperTwistContractLibrary::DeserializeSkillContinuityResumeStateFromJson(
			Json,
			RoundTrippedState
		)
	);
	TestTrue(
		TEXT("Round-tripped S3-A continuity/resume state should remain structurally valid."),
		RoundTrippedState.IsStructurallyValid()
	);
	TestEqual(
		TEXT("Round-tripped S3-A skill count should match the original sample."),
		RoundTrippedState.SkillCount,
		ContinuityState.SkillCount
	);
	TestEqual(
		TEXT("Round-tripped S3-A live-skill count should match the original sample."),
		RoundTrippedState.LiveSkillCount,
		ContinuityState.LiveSkillCount
	);

	return true;
}

#endif
