// Copyright HyperTwist, Inc. All Rights Reserved.

#include "Misc/AutomationTest.h"

#include "HyperTwistBootstrap/HyperTwistContractLibrary.h"

#if WITH_AUTOMATION_TESTS

namespace HyperTwistSkillPhaseS4BTestInternal
{
	const FHyperTwistSkillBrowserDiagnosticSkill* FindSkillById(
		const FHyperTwistSkillBrowserDiagnosticsState& DiagnosticsState,
		const FString& SkillId
	)
	{
		for (const FHyperTwistSkillBrowserDiagnosticSkill& Skill : DiagnosticsState.Skills)
		{
			if (Skill.SkillId == SkillId)
			{
				return &Skill;
			}
		}

		return nullptr;
	}
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistSkillPhaseS4BBrowserDiagnosticsCoverageTest,
	"HyperTwist.FirstParty.Skill.PhaseS4B.BrowserDiagnosticsCoverage",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistSkillPhaseS4BBrowserDiagnosticsCoverageTest::RunTest(const FString& Parameters)
{
	const FHyperTwistSkillBrowserDiagnosticsState DiagnosticsState =
		UHyperTwistContractLibrary::MakeSampleSkillBrowserDiagnosticsState();

	TestTrue(
		TEXT("The sample S4-B browser-diagnostics state should be structurally valid."),
		DiagnosticsState.IsStructurallyValid()
	);
	TestEqual(
		TEXT("S4-B should expose two browser-diagnostics skills."),
		DiagnosticsState.SkillCount,
		2
	);
	TestEqual(
		TEXT("S4-B should expose two live browser-diagnostics skills."),
		DiagnosticsState.LiveSkillCount,
		2
	);
	TestEqual(
		TEXT("S4-B should expose one browser-trace-capture skill."),
		DiagnosticsState.BrowserTraceCaptureSkillCount,
		1
	);
	TestEqual(
		TEXT("S4-B should expose one browser/API discovery skill."),
		DiagnosticsState.BrowserApiDiscoverySkillCount,
		1
	);

	const FHyperTwistSkillBrowserDiagnosticSkill* BrowserTraceSkill =
		HyperTwistSkillPhaseS4BTestInternal::FindSkillById(
			DiagnosticsState,
			TEXT("skill/capture-browser-trace")
		);
	TestNotNull(
		TEXT("The capture-browser-trace skill should exist."),
		BrowserTraceSkill
	);
	if (BrowserTraceSkill != nullptr)
	{
		TestEqual(
			TEXT("The capture-browser-trace skill should bind to the bounded browser-trace artifact."),
			BrowserTraceSkill->OutputArtifactKinds[0],
			FString(TEXT("artifact/browser-trace-capture-brief"))
		);
		TestTrue(
			TEXT("The capture-browser-trace skill should declare browser trace capture."),
			BrowserTraceSkill->bCapturesBrowserTrace
		);
	}

	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistSkillPhaseS4BBoundedBrowserDiagnosticsTest,
	"HyperTwist.FirstParty.Skill.PhaseS4B.BoundedBrowserDiagnostics",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistSkillPhaseS4BBoundedBrowserDiagnosticsTest::RunTest(const FString& Parameters)
{
	const FHyperTwistSkillBrowserDiagnosticsState DiagnosticsState =
		UHyperTwistContractLibrary::MakeSampleSkillBrowserDiagnosticsState();

	TestTrue(
		TEXT("The sample S4-B browser-diagnostics state should be structurally valid."),
		DiagnosticsState.IsStructurallyValid()
	);
	TestTrue(
		TEXT("Every live S4-B skill should read authoritative browser and docs surfaces."),
		DiagnosticsState.bEveryLiveSkillReadsAuthoritativeBrowserAndDocSurfaces
	);
	TestTrue(
		TEXT("Every live S4-B skill should keep validation-harness coverage."),
		DiagnosticsState.bEveryLiveSkillHasValidationHarnessCoverage
	);
	TestTrue(
		TEXT("S4-B browser diagnostics should remain structurally bounded."),
		DiagnosticsState.bDiagnosticsRemainBounded
	);
	TestTrue(
		TEXT("S4-B browser diagnostics should require the landed extraction substrate."),
		DiagnosticsState.bEverySkillRequiresExtractionSubstrate
	);
	TestTrue(
		TEXT("S4-B browser diagnostics should not widen into design translation."),
		DiagnosticsState.bNoDesignTranslationWidening
	);

	const FHyperTwistSkillBrowserDiagnosticSkill* BrowserApiSkill =
		HyperTwistSkillPhaseS4BTestInternal::FindSkillById(
			DiagnosticsState,
			TEXT("skill/discover-browser-api")
		);
	TestNotNull(
		TEXT("The discover-browser-api skill should exist."),
		BrowserApiSkill
	);
	if (BrowserApiSkill != nullptr)
	{
		TestTrue(
			TEXT("The discover-browser-api skill should declare browser/API discovery."),
			BrowserApiSkill->bPerformsBrowserApiDiscovery
		);
		TestTrue(
			TEXT("The discover-browser-api skill should depend on the extraction substrate."),
			BrowserApiSkill->bRequiresExtractionSubstrate
		);
		TestTrue(
			TEXT("The discover-browser-api skill should explicitly avoid design translation widening."),
			BrowserApiSkill->bAvoidsDesignTranslationWidening
		);
	}

	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistSkillPhaseS4BSerializationRoundTripTest,
	"HyperTwist.FirstParty.Skill.PhaseS4B.SerializationRoundTrip",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistSkillPhaseS4BSerializationRoundTripTest::RunTest(const FString& Parameters)
{
	const FHyperTwistSkillBrowserDiagnosticsState DiagnosticsState =
		UHyperTwistContractLibrary::MakeSampleSkillBrowserDiagnosticsState();

	TestTrue(
		TEXT("The sample S4-B browser-diagnostics state should be structurally valid before serialization."),
		DiagnosticsState.IsStructurallyValid()
	);

	const FString Json =
		UHyperTwistContractLibrary::SerializeSkillBrowserDiagnosticsStateToJson(
			DiagnosticsState
		);
	TestTrue(
		TEXT("Serialized S4-B JSON should include the extraction-substrate guard field."),
		Json.Contains(TEXT("bEverySkillRequiresExtractionSubstrate"))
	);

	FHyperTwistSkillBrowserDiagnosticsState RoundTrippedState;
	TestTrue(
		TEXT("Deserializing the S4-B browser-diagnostics JSON should succeed."),
		UHyperTwistContractLibrary::DeserializeSkillBrowserDiagnosticsStateFromJson(
			Json,
			RoundTrippedState
		)
	);
	TestTrue(
		TEXT("Round-tripped S4-B browser-diagnostics state should remain structurally valid."),
		RoundTrippedState.IsStructurallyValid()
	);
	TestEqual(
		TEXT("Round-tripped S4-B skill count should match the original sample."),
		RoundTrippedState.SkillCount,
		DiagnosticsState.SkillCount
	);
	TestEqual(
		TEXT("Round-tripped S4-B live-skill count should match the original sample."),
		RoundTrippedState.LiveSkillCount,
		DiagnosticsState.LiveSkillCount
	);

	return true;
}

#endif
