// Copyright HyperTwist, Inc. All Rights Reserved.

#include "Misc/AutomationTest.h"

#include "HyperTwistBootstrap/HyperTwistContractLibrary.h"

#if WITH_AUTOMATION_TESTS

namespace HyperTwistSkillPhaseS2BTestInternal
{
	const FHyperTwistSkillCleanRoomCommandContractSpec* FindSpecBySkillId(
		const FHyperTwistSkillCleanRoomCommandContractState& ContractState,
		const FString& SkillId
	)
	{
		for (const FHyperTwistSkillCleanRoomCommandContractSpec& Spec : ContractState.Specs)
		{
			if (Spec.SkillId == SkillId)
			{
				return &Spec;
			}
		}

		return nullptr;
	}
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistSkillPhaseS2BCommandContractSpecTest,
	"HyperTwist.FirstParty.Skill.PhaseS2B.CommandContractSpec",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistSkillPhaseS2BCommandContractSpecTest::RunTest(const FString& Parameters)
{
	const FHyperTwistSkillCleanRoomCommandContractState ContractState =
		UHyperTwistContractLibrary::MakeSampleSkillCleanRoomCommandContractState();

	TestTrue(
		TEXT("The sample S2-B clean-room command-contract state should be structurally valid."),
		ContractState.IsStructurallyValid()
	);
	TestEqual(
		TEXT("S2-B should land one restrictive clean-room command spec for the current skill family."),
		ContractState.SkillCount,
		1
	);
	TestEqual(
		TEXT("S2-B should expose one clean-room command spec."),
		ContractState.SpecCount,
		1
	);

	const FHyperTwistSkillCleanRoomCommandContractSpec* RouxSpec =
		HyperTwistSkillPhaseS2BTestInternal::FindSpecBySkillId(
			ContractState,
			TEXT("skill/roux-session-review")
		);
	TestNotNull(
		TEXT("The Roux clean-room command spec should exist."),
		RouxSpec
	);
	if (RouxSpec != nullptr)
	{
		TestEqual(
			TEXT("The Roux clean-room command spec should use the first-party contract service id."),
			RouxSpec->ServiceBindingId,
			FString(TEXT("service/specs/training-review/roux-session-review"))
		);
		TestEqual(
			TEXT("The Roux clean-room command spec should use the first-party training-review contract pattern."),
			RouxSpec->InvocationPattern,
			FString(TEXT("contract/training-review-brief"))
		);
	}

	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistSkillPhaseS2BSafetyModelTest,
	"HyperTwist.FirstParty.Skill.PhaseS2B.SafetyModel",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistSkillPhaseS2BSafetyModelTest::RunTest(const FString& Parameters)
{
	const FHyperTwistSkillCleanRoomCommandContractState ContractState =
		UHyperTwistContractLibrary::MakeSampleSkillCleanRoomCommandContractState();

	TestTrue(
		TEXT("The sample S2-B clean-room command-contract state should be structurally valid."),
		ContractState.IsStructurallyValid()
	);
	TestTrue(
		TEXT("Every S2-B spec should stay in first-party terms."),
		ContractState.bEverySpecUsesFirstPartyTerms
	);
	TestTrue(
		TEXT("Every S2-B spec should avoid donor wording."),
		ContractState.bEverySpecAvoidsDonorWording
	);
	TestTrue(
		TEXT("Every S2-B spec should preserve the optional-assistive off-state."),
		ContractState.bEverySpecPreservesOptionalAssistiveOffState
	);
	TestTrue(
		TEXT("Every S2-B spec should stay derived-assistive only."),
		ContractState.bEverySpecRestrictsToDerivedAssistiveOutput
	);
	TestTrue(
		TEXT("Every S2-B spec should keep provenance-ledger requirements."),
		ContractState.bEverySpecRequiresProvenanceLedger
	);
	TestTrue(
		TEXT("Every S2-B spec should avoid product-truth mutation."),
		ContractState.bEverySpecAvoidsProductTruthMutation
	);
	TestTrue(
		TEXT("Every S2-B spec should allow a future wrapper to bind without rewriting the contract."),
		ContractState.bEverySpecMayBindFutureWrapperWithoutContractRewrite
	);
	TestTrue(
		TEXT("Every S2-B spec should already have authoring-harness coverage."),
		ContractState.bEverySpecHasAuthoringHarnessCoverage
	);
	TestTrue(
		TEXT("Every S2-B spec should defer eval only until the clean-room skill spec phase."),
		ContractState.bEverySpecDefersEvalUntilCleanRoomSkillSpec
	);

	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistSkillPhaseS2BSerializationRoundTripTest,
	"HyperTwist.FirstParty.Skill.PhaseS2B.SerializationRoundTrip",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistSkillPhaseS2BSerializationRoundTripTest::RunTest(const FString& Parameters)
{
	const FHyperTwistSkillCleanRoomCommandContractState ContractState =
		UHyperTwistContractLibrary::MakeSampleSkillCleanRoomCommandContractState();

	TestTrue(
		TEXT("The sample S2-B clean-room command-contract state should be structurally valid before serialization."),
		ContractState.IsStructurallyValid()
	);

	const FString Json =
		UHyperTwistContractLibrary::SerializeSkillCleanRoomCommandContractStateToJson(
			ContractState
		);
	TestTrue(
		TEXT("Serialized S2-B JSON should include the future-wrapper binding guard field."),
		Json.Contains(TEXT("bEverySpecMayBindFutureWrapperWithoutContractRewrite"))
	);

	FHyperTwistSkillCleanRoomCommandContractState RoundTrippedState;
	TestTrue(
		TEXT("Deserializing the S2-B clean-room command-contract JSON should succeed."),
		UHyperTwistContractLibrary::DeserializeSkillCleanRoomCommandContractStateFromJson(
			Json,
			RoundTrippedState
		)
	);
	TestTrue(
		TEXT("Round-tripped S2-B clean-room command-contract state should remain structurally valid."),
		RoundTrippedState.IsStructurallyValid()
	);
	TestEqual(
		TEXT("Round-tripped S2-B spec count should match the original sample."),
		RoundTrippedState.SpecCount,
		ContractState.SpecCount
	);
	TestEqual(
		TEXT("Round-tripped S2-B safety-rule count should match the original sample."),
		RoundTrippedState.SafetyRuleCount,
		ContractState.SafetyRuleCount
	);

	return true;
}

#endif
