// Copyright HyperTwist, Inc. All Rights Reserved.

#include "Misc/AutomationTest.h"

#include "HyperTwistBootstrap/HyperTwistContractLibrary.h"

#if WITH_AUTOMATION_TESTS

namespace HyperTwistSkillPhaseS4ATestInternal
{
	const FHyperTwistSkillExtractionSkill* FindSkillById(
		const FHyperTwistSkillExtractionState& ExtractionState,
		const FString& SkillId
	)
	{
		for (const FHyperTwistSkillExtractionSkill& Skill : ExtractionState.Skills)
		{
			if (Skill.SkillId == SkillId)
			{
				return &Skill;
			}
		}

		return nullptr;
	}
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistSkillPhaseS4AExtractionCoverageTest,
	"HyperTwist.FirstParty.Skill.PhaseS4A.ExtractionCoverage",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistSkillPhaseS4AExtractionCoverageTest::RunTest(const FString& Parameters)
{
	const FHyperTwistSkillExtractionState ExtractionState =
		UHyperTwistContractLibrary::MakeSampleSkillExtractionState();

	TestTrue(
		TEXT("The sample S4-A extraction skill state should be structurally valid."),
		ExtractionState.IsStructurallyValid()
	);
	TestEqual(
		TEXT("S4-A should expose two extraction skills."),
		ExtractionState.SkillCount,
		2
	);
	TestEqual(
		TEXT("S4-A should expose two live extraction skills."),
		ExtractionState.LiveSkillCount,
		2
	);
	TestEqual(
		TEXT("S4-A should expose one docs-extraction skill."),
		ExtractionState.DocsExtractionSkillCount,
		1
	);
	TestEqual(
		TEXT("S4-A should expose one design-spec-extraction skill."),
		ExtractionState.DesignSpecExtractionSkillCount,
		1
	);

	const FHyperTwistSkillExtractionSkill* DocsSkill =
		HyperTwistSkillPhaseS4ATestInternal::FindSkillById(
			ExtractionState,
			TEXT("skill/extract-docs")
		);
	TestNotNull(
		TEXT("The extract-docs skill should exist."),
		DocsSkill
	);
	if (DocsSkill != nullptr)
	{
		TestEqual(
			TEXT("The extract-docs skill should bind to the bounded docs extraction artifact."),
			DocsSkill->OutputArtifactKinds[0],
			FString(TEXT("artifact/docs-extraction-brief"))
		);
		TestTrue(
			TEXT("The extract-docs skill should declare documentation extraction."),
			DocsSkill->bExtractsDocumentation
		);
	}

	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistSkillPhaseS4ABoundedExtractionTest,
	"HyperTwist.FirstParty.Skill.PhaseS4A.BoundedExtraction",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistSkillPhaseS4ABoundedExtractionTest::RunTest(const FString& Parameters)
{
	const FHyperTwistSkillExtractionState ExtractionState =
		UHyperTwistContractLibrary::MakeSampleSkillExtractionState();

	TestTrue(
		TEXT("The sample S4-A extraction skill state should be structurally valid."),
		ExtractionState.IsStructurallyValid()
	);
	TestTrue(
		TEXT("Every live S4-A skill should read authoritative source surfaces."),
		ExtractionState.bEveryLiveSkillReadsAuthoritativeSourceSurfaces
	);
	TestTrue(
		TEXT("Every live S4-A skill should keep validation-harness coverage."),
		ExtractionState.bEveryLiveSkillHasValidationHarnessCoverage
	);
	TestTrue(
		TEXT("S4-A extraction should remain structurally bounded."),
		ExtractionState.bStructuredExtractionRemainsBounded
	);
	TestTrue(
		TEXT("S4-A extraction should not widen into browser diagnostics."),
		ExtractionState.bNoBrowserDiagnosticsWidening
	);
	TestTrue(
		TEXT("S4-A extraction should not widen into design translation."),
		ExtractionState.bNoDesignTranslationWidening
	);

	const FHyperTwistSkillExtractionSkill* DesignSpecSkill =
		HyperTwistSkillPhaseS4ATestInternal::FindSkillById(
			ExtractionState,
			TEXT("skill/extract-design-spec")
		);
	TestNotNull(
		TEXT("The extract-design-spec skill should exist."),
		DesignSpecSkill
	);
	if (DesignSpecSkill != nullptr)
	{
		TestTrue(
			TEXT("The extract-design-spec skill should declare design-spec extraction."),
			DesignSpecSkill->bExtractsDesignSpecs
		);
		TestTrue(
			TEXT("The extract-design-spec skill should explicitly avoid design translation widening."),
			DesignSpecSkill->bAvoidsDesignTranslationWidening
		);
		TestTrue(
			TEXT("The extract-design-spec skill should explicitly avoid browser diagnostics widening."),
			DesignSpecSkill->bAvoidsBrowserDiagnosticsWidening
		);
	}

	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistSkillPhaseS4ASerializationRoundTripTest,
	"HyperTwist.FirstParty.Skill.PhaseS4A.SerializationRoundTrip",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistSkillPhaseS4ASerializationRoundTripTest::RunTest(const FString& Parameters)
{
	const FHyperTwistSkillExtractionState ExtractionState =
		UHyperTwistContractLibrary::MakeSampleSkillExtractionState();

	TestTrue(
		TEXT("The sample S4-A extraction skill state should be structurally valid before serialization."),
		ExtractionState.IsStructurallyValid()
	);

	const FString Json =
		UHyperTwistContractLibrary::SerializeSkillExtractionStateToJson(
			ExtractionState
		);
	TestTrue(
		TEXT("Serialized S4-A JSON should include the browser-diagnostics widening guard field."),
		Json.Contains(TEXT("bNoBrowserDiagnosticsWidening"))
	);

	FHyperTwistSkillExtractionState RoundTrippedState;
	TestTrue(
		TEXT("Deserializing the S4-A extraction JSON should succeed."),
		UHyperTwistContractLibrary::DeserializeSkillExtractionStateFromJson(
			Json,
			RoundTrippedState
		)
	);
	TestTrue(
		TEXT("Round-tripped S4-A extraction state should remain structurally valid."),
		RoundTrippedState.IsStructurallyValid()
	);
	TestEqual(
		TEXT("Round-tripped S4-A skill count should match the original sample."),
		RoundTrippedState.SkillCount,
		ExtractionState.SkillCount
	);
	TestEqual(
		TEXT("Round-tripped S4-A live-skill count should match the original sample."),
		RoundTrippedState.LiveSkillCount,
		ExtractionState.LiveSkillCount
	);

	return true;
}

#endif
