#include "Misc/AutomationTest.h"

#include "HyperTwistBootstrap/HyperTwistContractLibrary.h"

namespace HyperTwistSkillPhaseS2ATestInternal
{
	const FHyperTwistSkillAnalyzerWrapperOutput* FindOutputByKind(
		const FHyperTwistSkillAnalyzerWrapperState& WrapperState,
		const FString& OutputKindId
	)
	{
		for (const FHyperTwistSkillAnalyzerWrapperOutput& Output : WrapperState.Outputs)
		{
			if (Output.OutputKindId == OutputKindId)
			{
				return &Output;
			}
		}

		return nullptr;
	}
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistSkillPhaseS2AWrapperCoverageTest,
	"HyperTwist.FirstParty.Skill.PhaseS2A.WrapperCoverage",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistSkillPhaseS2AWrapperCoverageTest::RunTest(const FString& Parameters)
{
	const FHyperTwistSkillAnalyzerWrapperState WrapperState =
		UHyperTwistContractLibrary::MakeSampleSkillAnalyzerWrapperState();

	TestTrue(
		TEXT("The sample S2-A analyzer wrapper state should be structurally valid."),
		WrapperState.IsStructurallyValid()
	);
	TestEqual(
		TEXT("S2-A should land three implemented permissive wrapper skills."),
		WrapperState.SkillCount,
		3
	);
	TestEqual(
		TEXT("S2-A should expose four structured wrapper outputs."),
		WrapperState.OutputCount,
		4
	);
	TestEqual(
		TEXT("S2-A should expose one architecture scan output."),
		WrapperState.ArchitectureScanCount,
		1
	);
	TestEqual(
		TEXT("S2-A should expose one policy scan output."),
		WrapperState.PolicyScanCount,
		1
	);
	TestEqual(
		TEXT("S2-A should expose one route inspection output."),
		WrapperState.RouteInspectionCount,
		1
	);
	TestEqual(
		TEXT("S2-A should expose one watch-and-recheck output."),
		WrapperState.WatchAndRecheckCount,
		1
	);

	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistSkillPhaseS2AStableInvocationPatternTest,
	"HyperTwist.FirstParty.Skill.PhaseS2A.StableInvocationPatterns",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistSkillPhaseS2AStableInvocationPatternTest::RunTest(const FString& Parameters)
{
	const FHyperTwistSkillAnalyzerWrapperState WrapperState =
		UHyperTwistContractLibrary::MakeSampleSkillAnalyzerWrapperState();

	TestTrue(
		TEXT("The sample S2-A analyzer wrapper state should be structurally valid."),
		WrapperState.IsStructurallyValid()
	);
	TestTrue(
		TEXT("Every S2-A wrapper should map to a stable invocation pattern."),
		WrapperState.bEveryWrapperMapsToStableInvocationPattern
	);
	TestTrue(
		TEXT("Every S2-A wrapper should emit structured output."),
		WrapperState.bEveryWrapperEmitsStructuredOutput
	);
	TestTrue(
		TEXT("S2-A should only include implemented permissive wrappers."),
		WrapperState.bOnlyImplementedPermissiveWrappersIncluded
	);

	const FHyperTwistSkillAnalyzerWrapperOutput* ArchitectureOutput =
		HyperTwistSkillPhaseS2ATestInternal::FindOutputByKind(
			WrapperState,
			TEXT("wrapper-output/architecture-scan")
		);
	TestNotNull(
		TEXT("The architecture scan output should exist."),
		ArchitectureOutput
	);
	if (ArchitectureOutput != nullptr)
	{
		TestEqual(
			TEXT("Architecture scan should be emitted by the review-architecture wrapper."),
			ArchitectureOutput->SkillId,
			FString(TEXT("skill/review-architecture"))
		);
		TestEqual(
			TEXT("Architecture scan should use the live review wrapper service."),
			ArchitectureOutput->ServiceBindingId,
			FString(TEXT("service/skills/review-architecture"))
		);
	}

	const FHyperTwistSkillAnalyzerWrapperOutput* RouteOutput =
		HyperTwistSkillPhaseS2ATestInternal::FindOutputByKind(
			WrapperState,
			TEXT("wrapper-output/route-inspection")
		);
	TestNotNull(
		TEXT("The route inspection output should exist."),
		RouteOutput
	);
	if (RouteOutput != nullptr)
	{
		TestEqual(
			TEXT("Route inspection should be emitted by the provider-routing-inspector wrapper."),
			RouteOutput->SkillId,
			FString(TEXT("skill/provider-routing-inspector"))
		);
	}

	const FHyperTwistSkillAnalyzerWrapperOutput* WatchOutput =
		HyperTwistSkillPhaseS2ATestInternal::FindOutputByKind(
			WrapperState,
			TEXT("wrapper-output/watch-and-recheck")
		);
	TestNotNull(
		TEXT("The watch-and-recheck output should exist."),
		WatchOutput
	);
	if (WatchOutput != nullptr)
	{
		TestEqual(
			TEXT("Watch-and-recheck should be emitted by the memory-resume-briefing wrapper."),
			WatchOutput->SkillId,
			FString(TEXT("skill/memory-resume-briefing"))
		);
	}

	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistSkillPhaseS2ASerializationRoundTripTest,
	"HyperTwist.FirstParty.Skill.PhaseS2A.SerializationRoundTrip",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistSkillPhaseS2ASerializationRoundTripTest::RunTest(const FString& Parameters)
{
	const FHyperTwistSkillAnalyzerWrapperState WrapperState =
		UHyperTwistContractLibrary::MakeSampleSkillAnalyzerWrapperState();

	TestTrue(
		TEXT("The sample S2-A analyzer wrapper state should be structurally valid before serialization."),
		WrapperState.IsStructurallyValid()
	);

	const FString Json =
		UHyperTwistContractLibrary::SerializeSkillAnalyzerWrapperStateToJson(WrapperState);
	TestTrue(
		TEXT("Serialized S2-A wrapper JSON should include the structured-output guard field."),
		Json.Contains(TEXT("bEveryWrapperEmitsStructuredOutput"))
	);

	FHyperTwistSkillAnalyzerWrapperState RoundTrippedState;
	TestTrue(
		TEXT("Deserializing the S2-A wrapper JSON should succeed."),
		UHyperTwistContractLibrary::DeserializeSkillAnalyzerWrapperStateFromJson(
			Json,
			RoundTrippedState
		)
	);
	TestTrue(
		TEXT("Round-tripped S2-A wrapper state should remain structurally valid."),
		RoundTrippedState.IsStructurallyValid()
	);
	TestEqual(
		TEXT("Round-tripped S2-A skill count should match the original sample."),
		RoundTrippedState.SkillCount,
		WrapperState.SkillCount
	);
	TestEqual(
		TEXT("Round-tripped S2-A output count should match the original sample."),
		RoundTrippedState.OutputCount,
		WrapperState.OutputCount
	);

	return true;
}
