#include "HyperTwistSolverLibrary.h"
#include "Misc/AutomationTest.h"

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistSolverInitializationTest,
	"HyperTwist.Solver.Initialization",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistSolverInitializationTest::RunTest(const FString& Parameters)
{
	const bool bInit = UHyperTwistSolverLibrary::InitializeSolver();
	TestTrue(TEXT("Solver initialization must succeed."), bInit);
	TestTrue(TEXT("Solver should be initialized after InitializeSolver."), UHyperTwistSolverLibrary::IsSolverInitialized());
	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistSolverSolveTest,
	"HyperTwist.Solver.SolveSolvedState",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistSolverSolveTest::RunTest(const FString& Parameters)
{
	// Solved-state facelet string: UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB
	const FString SolvedState = TEXT("UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB");
	
	TestTrue(TEXT("Solved-state facelet string must be valid."), UHyperTwistSolverLibrary::VerifyFaceletString(SolvedState));
	
	const TArray<FString> Solution = UHyperTwistSolverLibrary::SolveClassicState(SolvedState, 100, 25, 1);
	TestTrue(TEXT("Solved-state solution must be found."), Solution.Num() == 0); // already solved = zero moves
	
	return true;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(
	FHyperTwistSolverSolveScrambledTest,
	"HyperTwist.Solver.SolveScrambledState",
	EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)

bool FHyperTwistSolverSolveScrambledTest::RunTest(const FString& Parameters)
{
	// A known scrambled state produced by applying:
	// R U R' U' R U R' U'
	// to the solved cube using the classic-cube actor's own move semantics.
	const FString ScrambledState =
		TEXT("UURUUUFFFUFBRRRDRRLRRFFUFFRDDFDDDDDDLLULLLLLLUBBBBBBBB");

	TestTrue(
		TEXT("The known scrambled facelet string must be recognized as a valid classic-cube state."),
		UHyperTwistSolverLibrary::VerifyFaceletString(ScrambledState)
	);

	const TArray<FString> Solution = UHyperTwistSolverLibrary::SolveClassicState(ScrambledState, 5000, 25, 1);

	TestTrue(
		TEXT("The solver must return at least one move for the known scrambled state."),
		Solution.Num() > 0
	);
	TestTrue(
		TEXT("The known scrambled state must solve within the 25-move bound tracked in the roadmap."),
		Solution.Num() < 25
	);

	for (const FString& Move : Solution)
	{
		TestFalse(TEXT("Each move must be non-empty."), Move.IsEmpty());
	}

	return true;
}
