#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "HyperTwistIPC/HyperTwistIPCProcessManager.h"
#include "HyperTwistSolverOracleLibrary.generated.h"

UCLASS()
class UNREALHYPERTWIST_API UHyperTwistSolverOracleLibrary : public UBlueprintFunctionLibrary
{
    GENERATED_BODY()

public:
    /**
     * Solve a cube using the brownan GPL solver oracle (IPC).
     * The solver runs as an external process; no GPL code is linked into Unreal.
     * Returns the solution move sequence in WCA notation.
     */
    UFUNCTION(BlueprintCallable, Category = "HyperTwist|Solver|Oracle")
    static TArray<FString> SolveWithBrownanOracle(const FString& FaceletString);

    /**
     * Verify a solution using the brownan GPL solver oracle (IPC).
     * The solver runs as an external process; no GPL code is linked into Unreal.
     */
    UFUNCTION(BlueprintCallable, Category = "HyperTwist|Solver|Oracle")
    static bool VerifySolutionWithBrownanOracle(const FString& CubeState, const TArray<FString>& Moves);

    /**
     * Solve a cube using the cahidenes Python solver oracle (IPC).
     * Returns the solution move sequence.
     */
    UFUNCTION(BlueprintCallable, Category = "HyperTwist|Solver|Oracle")
    static TArray<FString> SolveWithCahidenesOracle(const FString& FaceletString);

    /**
     * Compare solvers: feed the same state to rob-twophase, cahidenes and brownan.
     * Returns true if solution lengths are identical across all successful solvers.
     */
    UFUNCTION(BlueprintCallable, Category = "HyperTwist|Solver|Oracle")
    static bool CompareSolvers(const FString& FaceletString);

    /**
     * Check if all solver oracle executables are present in the expected paths.
     */
    UFUNCTION(BlueprintPure, Category = "HyperTwist|Solver|Oracle")
    static bool AreSolverOraclesAvailable();

    /** Get path to the brownan solver executable */
    static FString GetBrownanSolverPath();

    /** Get path to the brownan Python wrapper script */
    static FString GetBrownanWrapperPath();

    /** Get path to the cahidenes Python wrapper script */
    static FString GetCahidenesWrapperPath();
};
