#include "Misc/AutomationTest.h"

#include "HyperTwistBootstrap/HyperTwistContractLibrary.h"

namespace HyperTwistSkillPhaseS1DTestInternal
{
	const FHyperTwistSkillAuthoringTemplateSection* FindSectionById(
		const FHyperTwistSkillAuthoringHarnessState& HarnessState,
		const FString& SectionId
	)
	{
		for (const FHyperTwistSkillAuthoringTemplateSection& Section : HarnessState.TemplateSections)
		{
			if (Section.SectionId == SectionId)
			{
				return &Section;
			}
		}

		return nullptr;
	}

	const FHyperTwistSkillValidationContractCase* FindValidationCase(
		const FHyperTwistSkillAuthoringHarnessState& HarnessState,
		const FString& SkillId,
		const EHyperTwistSkillValidationContractKind Kind
	)
	{
		for (const FHyperTwistSkillValidationContractCase& ValidationCase : HarnessState.ValidationCases)
		{
			if (ValidationCase.SkillId == SkillId && ValidationCase.Kind == Kind)
			{
				return &ValidationCase;
			}
		}

		return nullptr;
	}
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistSkillPhaseS1DAuthoringTemplateTest,
	"HyperTwist.FirstParty.Skill.PhaseS1D.AuthoringTemplate",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistSkillPhaseS1DAuthoringTemplateTest::RunTest(const FString& Parameters)
{
	const FHyperTwistSkillAuthoringHarnessState HarnessState =
		UHyperTwistContractLibrary::MakeSampleSkillAuthoringHarnessState();

	TestTrue(
		TEXT("Sample skill authoring harness state should be structurally valid."),
		HarnessState.IsStructurallyValid()
	);
	TestTrue(
		TEXT("New skills should be addable without inventing structure."),
		HarnessState.bNewSkillsCanBeAddedWithoutInventingStructure
	);
	TestEqual(
		TEXT("The sample authoring harness should have one example per current skill."),
		HarnessState.ExampleCount,
		HarnessState.SkillCount
	);
	TestTrue(
		TEXT("Examples should stay grounded in the first-party registry."),
		HarnessState.bExamplesGroundedInFirstPartyRegistry
	);

	const FHyperTwistSkillAuthoringTemplateSection* ValidationSection =
		HyperTwistSkillPhaseS1DTestInternal::FindSectionById(
			HarnessState,
			TEXT("section/skill-validation-contract")
		);
	TestNotNull(
		TEXT("The sample authoring harness should expose the validation-contract section."),
		ValidationSection
	);
	if (ValidationSection != nullptr)
	{
		TestEqual(
			TEXT("The validation-contract section should carry the expected number of required fields."),
			ValidationSection->Fields.Num(),
			2
		);
	}

	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistSkillPhaseS1DValidationHarnessCoverageTest,
	"HyperTwist.FirstParty.Skill.PhaseS1D.ValidationHarnessCoverage",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistSkillPhaseS1DValidationHarnessCoverageTest::RunTest(const FString& Parameters)
{
	const FHyperTwistSkillAuthoringHarnessState HarnessState =
		UHyperTwistContractLibrary::MakeSampleSkillAuthoringHarnessState();

	TestTrue(
		TEXT("Sample skill authoring harness state should be structurally valid."),
		HarnessState.IsStructurallyValid()
	);
	TestTrue(
		TEXT("Every skill should have a smoke contract."),
		HarnessState.bEverySkillHasSmokeContract
	);
	TestTrue(
		TEXT("Every skill should have an eval contract."),
		HarnessState.bEverySkillHasEvalContract
	);
	TestTrue(
		TEXT("Live validation contracts should use audit-ledger evidence."),
		HarnessState.bValidationHarnessUsesAuditLedgerWhenLive
	);

	const FHyperTwistSkillValidationContractCase* GovernanceSmoke =
		HyperTwistSkillPhaseS1DTestInternal::FindValidationCase(
			HarnessState,
			TEXT("skill/skillization-governance"),
			EHyperTwistSkillValidationContractKind::Smoke
		);
	TestNotNull(
		TEXT("The governance skill should have a smoke validation contract."),
		GovernanceSmoke
	);
	if (GovernanceSmoke != nullptr)
	{
		TestEqual(
			TEXT("The governance skill smoke contract should run in live mode."),
			GovernanceSmoke->ExecutionMode,
			EHyperTwistSkillValidationExecutionMode::LiveContract
		);
	}

	const FHyperTwistSkillValidationContractCase* ReviewEval =
		HyperTwistSkillPhaseS1DTestInternal::FindValidationCase(
			HarnessState,
			TEXT("skill/review-architecture"),
			EHyperTwistSkillValidationContractKind::Eval
		);
	TestNotNull(
		TEXT("The review skill should have an eval validation contract."),
		ReviewEval
	);
	if (ReviewEval != nullptr)
	{
		TestEqual(
			TEXT("The review skill eval contract should now run live after S2-A lands."),
			ReviewEval->ExecutionMode,
			EHyperTwistSkillValidationExecutionMode::LiveContract
		);
	}

	const FHyperTwistSkillValidationContractCase* SearchHistoryEval =
		HyperTwistSkillPhaseS1DTestInternal::FindValidationCase(
			HarnessState,
			TEXT("skill/search-history"),
			EHyperTwistSkillValidationContractKind::Eval
		);
	TestNotNull(
		TEXT("The search-history skill should have an eval validation contract."),
		SearchHistoryEval
	);
	if (SearchHistoryEval != nullptr)
	{
		TestEqual(
			TEXT("The search-history skill eval contract should now run live after S3-A lands."),
			SearchHistoryEval->ExecutionMode,
			EHyperTwistSkillValidationExecutionMode::LiveContract
		);
	}

	const FHyperTwistSkillValidationContractCase* RecallMemoryEval =
		HyperTwistSkillPhaseS1DTestInternal::FindValidationCase(
			HarnessState,
			TEXT("skill/recall-memory"),
			EHyperTwistSkillValidationContractKind::Eval
		);
	TestNotNull(
		TEXT("The recall-memory skill should have an eval validation contract."),
		RecallMemoryEval
	);
	if (RecallMemoryEval != nullptr)
	{
		TestEqual(
			TEXT("The recall-memory skill eval contract should now run live after S3-B lands."),
			RecallMemoryEval->ExecutionMode,
			EHyperTwistSkillValidationExecutionMode::LiveContract
		);
	}

	const FHyperTwistSkillValidationContractCase* CompactViewEval =
		HyperTwistSkillPhaseS1DTestInternal::FindValidationCase(
			HarnessState,
			TEXT("skill/generate-compact-view"),
			EHyperTwistSkillValidationContractKind::Eval
		);
	TestNotNull(
		TEXT("The generate-compact-view skill should have an eval validation contract."),
		CompactViewEval
	);
	if (CompactViewEval != nullptr)
	{
		TestEqual(
			TEXT("The generate-compact-view skill eval contract should now run live after S3-B lands."),
			CompactViewEval->ExecutionMode,
			EHyperTwistSkillValidationExecutionMode::LiveContract
		);
	}

	const FHyperTwistSkillValidationContractCase* CaptureTemplateEval =
		HyperTwistSkillPhaseS1DTestInternal::FindValidationCase(
			HarnessState,
			TEXT("skill/capture-session-template"),
			EHyperTwistSkillValidationContractKind::Eval
		);
	TestNotNull(
		TEXT("The capture-session-template skill should have an eval validation contract."),
		CaptureTemplateEval
	);
	if (CaptureTemplateEval != nullptr)
	{
		TestEqual(
			TEXT("The capture-session-template skill eval contract should now run live after S3-C lands."),
			CaptureTemplateEval->ExecutionMode,
			EHyperTwistSkillValidationExecutionMode::LiveContract
		);
	}

	const FHyperTwistSkillValidationContractCase* CaptureFollowUpEval =
		HyperTwistSkillPhaseS1DTestInternal::FindValidationCase(
			HarnessState,
			TEXT("skill/capture-follow-up-routine"),
			EHyperTwistSkillValidationContractKind::Eval
		);
	TestNotNull(
		TEXT("The capture-follow-up-routine skill should have an eval validation contract."),
		CaptureFollowUpEval
	);
	if (CaptureFollowUpEval != nullptr)
	{
		TestEqual(
			TEXT("The capture-follow-up-routine skill eval contract should now run live after S3-C lands."),
			CaptureFollowUpEval->ExecutionMode,
			EHyperTwistSkillValidationExecutionMode::LiveContract
		);
	}

	const FHyperTwistSkillValidationContractCase* DocsExtractionEval =
		HyperTwistSkillPhaseS1DTestInternal::FindValidationCase(
			HarnessState,
			TEXT("skill/extract-docs"),
			EHyperTwistSkillValidationContractKind::Eval
		);
	TestNotNull(
		TEXT("The extract-docs skill should have an eval validation contract."),
		DocsExtractionEval
	);
	if (DocsExtractionEval != nullptr)
	{
		TestEqual(
			TEXT("The extract-docs skill eval contract should run live after S4-A lands."),
			DocsExtractionEval->ExecutionMode,
			EHyperTwistSkillValidationExecutionMode::LiveContract
		);
	}

	const FHyperTwistSkillValidationContractCase* DesignSpecExtractionEval =
		HyperTwistSkillPhaseS1DTestInternal::FindValidationCase(
			HarnessState,
			TEXT("skill/extract-design-spec"),
			EHyperTwistSkillValidationContractKind::Eval
		);
	TestNotNull(
		TEXT("The extract-design-spec skill should have an eval validation contract."),
		DesignSpecExtractionEval
	);
	if (DesignSpecExtractionEval != nullptr)
	{
		TestEqual(
			TEXT("The extract-design-spec skill eval contract should run live after S4-A lands."),
			DesignSpecExtractionEval->ExecutionMode,
			EHyperTwistSkillValidationExecutionMode::LiveContract
		);
	}

	const FHyperTwistSkillValidationContractCase* BrowserTraceEval =
		HyperTwistSkillPhaseS1DTestInternal::FindValidationCase(
			HarnessState,
			TEXT("skill/capture-browser-trace"),
			EHyperTwistSkillValidationContractKind::Eval
		);
	TestNotNull(
		TEXT("The capture-browser-trace skill should have an eval validation contract."),
		BrowserTraceEval
	);
	if (BrowserTraceEval != nullptr)
	{
		TestEqual(
			TEXT("The capture-browser-trace skill eval contract should run live after S4-B lands."),
			BrowserTraceEval->ExecutionMode,
			EHyperTwistSkillValidationExecutionMode::LiveContract
		);
	}

	const FHyperTwistSkillValidationContractCase* DesignShellEval =
		HyperTwistSkillPhaseS1DTestInternal::FindValidationCase(
			HarnessState,
			TEXT("skill/translate-design-shell"),
			EHyperTwistSkillValidationContractKind::Eval
		);
	TestNotNull(
		TEXT("The translate-design-shell skill should have an eval validation contract."),
		DesignShellEval
	);
	if (DesignShellEval != nullptr)
	{
		TestEqual(
			TEXT("The translate-design-shell skill eval contract should run live after S4-C lands."),
			DesignShellEval->ExecutionMode,
			EHyperTwistSkillValidationExecutionMode::LiveContract
		);
	}

	const FHyperTwistSkillValidationContractCase* WorkflowReviewEval =
		HyperTwistSkillPhaseS1DTestInternal::FindValidationCase(
			HarnessState,
			TEXT("skill/review-proposal"),
			EHyperTwistSkillValidationContractKind::Eval
		);
	TestNotNull(
		TEXT("The review-proposal skill should have an eval validation contract."),
		WorkflowReviewEval
	);
	if (WorkflowReviewEval != nullptr)
	{
		TestEqual(
			TEXT("The review-proposal skill eval contract should run live after S5-A lands."),
			WorkflowReviewEval->ExecutionMode,
			EHyperTwistSkillValidationExecutionMode::LiveContract
		);
	}

	const FHyperTwistSkillValidationContractCase* ImplementationReviewEval =
		HyperTwistSkillPhaseS1DTestInternal::FindValidationCase(
			HarnessState,
			TEXT("skill/review-implementation"),
			EHyperTwistSkillValidationContractKind::Eval
		);
	TestNotNull(
		TEXT("The review-implementation skill should have an eval validation contract."),
		ImplementationReviewEval
	);
	if (ImplementationReviewEval != nullptr)
	{
		TestEqual(
			TEXT("The review-implementation skill eval contract should run live after S5-B lands."),
			ImplementationReviewEval->ExecutionMode,
			EHyperTwistSkillValidationExecutionMode::LiveContract
		);
	}

	const FHyperTwistSkillValidationContractCase* PlanSynthesisEval =
		HyperTwistSkillPhaseS1DTestInternal::FindValidationCase(
			HarnessState,
			TEXT("skill/synthesize-plan"),
			EHyperTwistSkillValidationContractKind::Eval
		);
	TestNotNull(
		TEXT("The synthesize-plan skill should have an eval validation contract."),
		PlanSynthesisEval
	);
	if (PlanSynthesisEval != nullptr)
	{
		TestEqual(
			TEXT("The synthesize-plan skill eval contract should run live after S5-C lands."),
			PlanSynthesisEval->ExecutionMode,
			EHyperTwistSkillValidationExecutionMode::LiveContract
		);
	}

	const FHyperTwistSkillValidationContractCase* ProviderProfileEval =
		HyperTwistSkillPhaseS1DTestInternal::FindValidationCase(
			HarnessState,
			TEXT("skill/inspect-provider-profile"),
			EHyperTwistSkillValidationContractKind::Eval
		);
	TestNotNull(
		TEXT("The inspect-provider-profile skill should have an eval validation contract."),
		ProviderProfileEval
	);
	if (ProviderProfileEval != nullptr)
	{
		TestEqual(
			TEXT("The inspect-provider-profile skill eval contract should run live after S6-A lands."),
			ProviderProfileEval->ExecutionMode,
			EHyperTwistSkillValidationExecutionMode::LiveContract
		);
	}

	const FHyperTwistSkillValidationContractCase* UsageAuditEval =
		HyperTwistSkillPhaseS1DTestInternal::FindValidationCase(
			HarnessState,
			TEXT("skill/audit-provider-usage"),
			EHyperTwistSkillValidationContractKind::Eval
		);
	TestNotNull(
		TEXT("The audit-provider-usage skill should have an eval validation contract."),
		UsageAuditEval
	);
	if (UsageAuditEval != nullptr)
	{
		TestEqual(
			TEXT("The audit-provider-usage skill eval contract should run live after S6-B lands."),
			UsageAuditEval->ExecutionMode,
			EHyperTwistSkillValidationExecutionMode::LiveContract
		);
	}

	const FHyperTwistSkillValidationContractCase* DomainPackagingEval =
		HyperTwistSkillPhaseS1DTestInternal::FindValidationCase(
			HarnessState,
			TEXT("skill/specify-domain-packaging"),
			EHyperTwistSkillValidationContractKind::Eval
		);
	TestNotNull(
		TEXT("The specify-domain-packaging skill should have an eval validation contract."),
		DomainPackagingEval
	);
	if (DomainPackagingEval != nullptr)
	{
		TestEqual(
			TEXT("The specify-domain-packaging skill eval contract should run live after S7-A lands."),
			DomainPackagingEval->ExecutionMode,
			EHyperTwistSkillValidationExecutionMode::LiveContract
		);
	}

	const FHyperTwistSkillValidationContractCase* TrainingReplayPackEval =
		HyperTwistSkillPhaseS1DTestInternal::FindValidationCase(
			HarnessState,
			TEXT("skill/review-training-replay-pack"),
			EHyperTwistSkillValidationContractKind::Eval
		);
	TestNotNull(
		TEXT("The review-training-replay-pack skill should have an eval validation contract."),
		TrainingReplayPackEval
	);
	if (TrainingReplayPackEval != nullptr)
	{
		TestEqual(
			TEXT("The review-training-replay-pack skill eval contract should run live after S7-B lands."),
			TrainingReplayPackEval->ExecutionMode,
			EHyperTwistSkillValidationExecutionMode::LiveContract
		);
	}

	const FHyperTwistSkillValidationContractCase* ReplayExplainerEval =
		HyperTwistSkillPhaseS1DTestInternal::FindValidationCase(
			HarnessState,
			TEXT("skill/compose-replay-explainer-pack"),
			EHyperTwistSkillValidationContractKind::Eval
		);
	TestNotNull(
		TEXT("The compose-replay-explainer-pack skill should have an eval validation contract."),
		ReplayExplainerEval
	);
	if (ReplayExplainerEval != nullptr)
	{
		TestEqual(
			TEXT("The compose-replay-explainer-pack skill eval contract should run live after S7-C lands."),
			ReplayExplainerEval->ExecutionMode,
			EHyperTwistSkillValidationExecutionMode::LiveContract
		);
	}

	const FHyperTwistSkillValidationContractCase* RouxEval =
		HyperTwistSkillPhaseS1DTestInternal::FindValidationCase(
			HarnessState,
			TEXT("skill/roux-session-review"),
			EHyperTwistSkillValidationContractKind::Eval
		);
	TestNotNull(
		TEXT("The Roux skill should have an eval validation contract."),
		RouxEval
	);
	if (RouxEval != nullptr)
	{
		TestEqual(
			TEXT("The Roux skill eval contract should now be structurally declared because the clean-room skill spec has landed."),
			RouxEval->ExecutionMode,
			EHyperTwistSkillValidationExecutionMode::DeclarationOnly
		);
	}

	const FHyperTwistSkillValidationContractCase* CaptureNoteEval =
		HyperTwistSkillPhaseS1DTestInternal::FindValidationCase(
			HarnessState,
			TEXT("skill/capture-note"),
			EHyperTwistSkillValidationContractKind::Eval
		);
	TestNotNull(
		TEXT("The capture-note skill should have an eval validation contract."),
		CaptureNoteEval
	);
	if (CaptureNoteEval != nullptr)
	{
		TestEqual(
			TEXT("The capture-note skill eval contract should remain deferred until a later live wrapper or owner activation lands."),
			CaptureNoteEval->ExecutionMode,
			EHyperTwistSkillValidationExecutionMode::DeferredUntilWrapper
		);
	}

	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistSkillPhaseS1DSerializationRoundTripTest,
	"HyperTwist.FirstParty.Skill.PhaseS1D.SerializationRoundTrip",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistSkillPhaseS1DSerializationRoundTripTest::RunTest(const FString& Parameters)
{
	const FHyperTwistSkillAuthoringHarnessState HarnessState =
		UHyperTwistContractLibrary::MakeSampleSkillAuthoringHarnessState();

	TestTrue(
		TEXT("Sample skill authoring harness state should be structurally valid before serialization."),
		HarnessState.IsStructurallyValid()
	);

	const FString Json =
		UHyperTwistContractLibrary::SerializeSkillAuthoringHarnessStateToJson(HarnessState);
	TestTrue(
		TEXT("Serialized skill authoring harness JSON should include the structural-addition guard field."),
		Json.Contains(TEXT("bNewSkillsCanBeAddedWithoutInventingStructure"))
	);

	FHyperTwistSkillAuthoringHarnessState RoundTrippedState;
	TestTrue(
		TEXT("Deserializing the skill authoring harness JSON should succeed."),
		UHyperTwistContractLibrary::DeserializeSkillAuthoringHarnessStateFromJson(
			Json,
			RoundTrippedState
		)
	);
	TestTrue(
		TEXT("Round-tripped skill authoring harness state should remain structurally valid."),
		RoundTrippedState.IsStructurallyValid()
	);
	TestEqual(
		TEXT("Round-tripped example count should match the original sample."),
		RoundTrippedState.ExampleCount,
		HarnessState.ExampleCount
	);
	TestEqual(
		TEXT("Round-tripped validation-case count should match the original sample."),
		RoundTrippedState.ValidationCaseCount,
		HarnessState.ValidationCaseCount
	);
	TestEqual(
		TEXT("Round-tripped smoke coverage should match the original sample."),
		RoundTrippedState.SkillsWithSmokeContractCount,
		HarnessState.SkillsWithSmokeContractCount
	);

	return true;
}
