// Copyright HyperTwist, Inc. All Rights Reserved.

#include "Misc/AutomationTest.h"

#include "HyperTwistBootstrap/HyperTwistContractLibrary.h"

#if WITH_AUTOMATION_TESTS

namespace HyperTwistSkillPhaseS6BTestInternal
{
	const FHyperTwistSkillProviderUsageOperationsAuditSkill* FindSkillById(
		const FHyperTwistSkillProviderUsageOperationsAuditState& AuditState,
		const FString& SkillId
	)
	{
		for (const FHyperTwistSkillProviderUsageOperationsAuditSkill& Skill :
			AuditState.Skills)
		{
			if (Skill.SkillId == SkillId)
			{
				return &Skill;
			}
		}

		return nullptr;
	}
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistSkillPhaseS6BUsageOperationsAuditCoverageTest,
	"HyperTwist.FirstParty.Skill.PhaseS6B.UsageOperationsAuditCoverage",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistSkillPhaseS6BUsageOperationsAuditCoverageTest::RunTest(
	const FString& Parameters
)
{
	const FHyperTwistSkillProviderUsageOperationsAuditState AuditState =
		UHyperTwistContractLibrary::MakeSampleSkillProviderUsageOperationsAuditState();

	TestTrue(
		TEXT("The sample S6-B usage/operations audit state should be structurally valid."),
		AuditState.IsStructurallyValid()
	);
	TestEqual(
		TEXT("S6-B should expose three bounded provider usage/operations audit skills."),
		AuditState.SkillCount,
		3
	);
	TestEqual(
		TEXT("S6-B should expose one usage-audit skill."),
		AuditState.UsageAuditSkillCount,
		1
	);
	TestEqual(
		TEXT("S6-B should expose one topology-inspection skill."),
		AuditState.TopologyInspectionSkillCount,
		1
	);
	TestEqual(
		TEXT("S6-B should expose one route/service diagnostic skill."),
		AuditState.RouteServiceDiagnosticSkillCount,
		1
	);

	const FHyperTwistSkillProviderUsageOperationsAuditSkill* UsageAuditSkill =
		HyperTwistSkillPhaseS6BTestInternal::FindSkillById(
			AuditState,
			TEXT("skill/audit-provider-usage")
		);
	TestNotNull(
		TEXT("The audit-provider-usage skill should exist."),
		UsageAuditSkill
	);
	if (UsageAuditSkill != nullptr)
	{
		TestEqual(
			TEXT("The audit-provider-usage skill should bind to the first-party provider-usage audit service."),
			UsageAuditSkill->ServiceBindingId,
			FString(TEXT("service/skills/audit-provider-usage"))
		);
		TestTrue(
			TEXT("The audit-provider-usage skill should declare usage-audit mode."),
			UsageAuditSkill->bAuditsUsage
		);
	}

	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistSkillPhaseS6BNormalizedStateAcceptanceGateTest,
	"HyperTwist.FirstParty.Skill.PhaseS6B.NormalizedStateAcceptanceGate",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistSkillPhaseS6BNormalizedStateAcceptanceGateTest::RunTest(
	const FString& Parameters
)
{
	const FHyperTwistSkillProviderUsageOperationsAuditState AuditState =
		UHyperTwistContractLibrary::MakeSampleSkillProviderUsageOperationsAuditState();

	TestTrue(
		TEXT("The sample S6-B usage/operations audit state should be structurally valid."),
		AuditState.IsStructurallyValid()
	);
	TestTrue(
		TEXT("S6-B should ensure every live skill reads normalized first-party state."),
		AuditState.bEveryLiveSkillReadsNormalizedFirstPartyState
	);
	TestTrue(
		TEXT("S6-B should preserve normalized first-party accounting ownership."),
		AuditState.bNormalizedFirstPartyAccountingOwnershipPreserved
	);
	TestTrue(
		TEXT("S6-B should avoid settlement-execution widening."),
		AuditState.bNoSettlementExecutionWidening
	);
	TestTrue(
		TEXT("S6-B should avoid provider-portal widening."),
		AuditState.bNoProviderPortalWidening
	);

	const FHyperTwistSkillProviderUsageOperationsAuditSkill* RouteServiceSkill =
		HyperTwistSkillPhaseS6BTestInternal::FindSkillById(
			AuditState,
			TEXT("skill/diagnose-route-service")
		);
	TestNotNull(
		TEXT("The diagnose-route-service skill should exist."),
		RouteServiceSkill
	);
	if (RouteServiceSkill != nullptr)
	{
		TestEqual(
			TEXT("The diagnose-route-service skill should depend on the three landed S6-A provider-profile/routing skills."),
			RouteServiceSkill->RequiredProviderProfileRoutingSkillCount,
			3
		);
		TestTrue(
			TEXT("The diagnose-route-service skill should declare route/service diagnostic mode."),
			RouteServiceSkill->bDiagnosesRouteService
		);
	}

	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistSkillPhaseS6BSerializationRoundTripTest,
	"HyperTwist.FirstParty.Skill.PhaseS6B.SerializationRoundTrip",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistSkillPhaseS6BSerializationRoundTripTest::RunTest(
	const FString& Parameters
)
{
	const FHyperTwistSkillProviderUsageOperationsAuditState AuditState =
		UHyperTwistContractLibrary::MakeSampleSkillProviderUsageOperationsAuditState();

	TestTrue(
		TEXT("The sample S6-B usage/operations audit state should be structurally valid before serialization."),
		AuditState.IsStructurallyValid()
	);

	const FString Json =
		UHyperTwistContractLibrary::SerializeSkillProviderUsageOperationsAuditStateToJson(
			AuditState
		);
	TestTrue(
		TEXT("Serialized S6-B JSON should include the normalized-first-party-state field."),
		Json.Contains(TEXT("bEveryLiveSkillReadsNormalizedFirstPartyState"))
	);

	FHyperTwistSkillProviderUsageOperationsAuditState RoundTrippedState;
	TestTrue(
		TEXT("Deserializing the S6-B usage/operations audit JSON should succeed."),
		UHyperTwistContractLibrary::DeserializeSkillProviderUsageOperationsAuditStateFromJson(
			Json,
			RoundTrippedState
		)
	);
	TestTrue(
		TEXT("Round-tripped S6-B usage/operations audit state should remain structurally valid."),
		RoundTrippedState.IsStructurallyValid()
	);
	TestEqual(
		TEXT("Round-tripped S6-B skill count should match the original sample."),
		RoundTrippedState.SkillCount,
		AuditState.SkillCount
	);
	TestEqual(
		TEXT("Round-tripped S6-B route/service diagnostic count should match the original sample."),
		RoundTrippedState.RouteServiceDiagnosticSkillCount,
		AuditState.RouteServiceDiagnosticSkillCount
	);

	return true;
}

#endif
