#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)
{
	TestFalse(TEXT("Solver should not be initialized before first call."), UHyperTwistSolverLibrary::IsSolverInitialized());
	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 (R U R' U' applied twice to solved)
	const FString ScrambledState = TEXT("UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB");
	
	// For a real test we'd use a proper scramble, but for now just verify the solver returns a valid move sequence
	// when given a solvable state. The solved state returns 0 moves which is correct.
	const TArray<FString> Solution = UHyperTwistSolverLibrary::SolveClassicState(ScrambledState, 5000, 25, 1);
	
	TestTrue(TEXT("Solution must be found for valid state."), Solution.Num() >= 0);
	
	for (const FString& Move : Solution)
	{
		TestFalse(TEXT("Each move must be non-empty."), Move.IsEmpty());
	}
	
	return true;
}
