#pragma once

#include "CoreMinimal.h"
#include "WingServer.h"
#include "WingBasics.h"
#include "WingFetcher.h"
#include "WingUtils.h"
#include "Engine/Blueprint.h"
#include "EdGraphSchema_K2.h"
#include "Kismet2/BlueprintEditorUtils.h"
#include "BlueprintOverride_Add.generated.h"


// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------

UCLASS()
class UWing_BlueprintOverride_Add : public UWingHandler
{
	GENERATED_BODY()

public:
	UPROPERTY(EditAnywhere, meta=(Description="Blueprint path"))
	FString BlueprintPath;

	UPROPERTY(EditAnywhere, meta=(Description="Function to override, in Class|Function format"))
	FString Function;

	virtual void Register() override
	{
		UWingServer::AddHandler(this,
			TEXT("Add a function override to a Blueprint."));
	}

	virtual void Handle() override
	{
		WingFetcher F(WingOut::Stdout);
		UBlueprint* BP = F.Walk(BlueprintPath).Cast<UBlueprint>();
		if (!BP) return;

		// Find the function by matching against the menu string format (Class|Function)
		TArray<UFunction*> Overridable = WingUtils::GetOverridableFunctions(BP);
		UFunction* OverrideFunc = nullptr;
		for (UFunction* Candidate : Overridable)
		{
			FString MenuString = WingUtils::GetFunctionMenuString(Candidate);
			if (MenuString.Equals(Function, ESearchCase::IgnoreCase))
			{
				OverrideFunc = Candidate;
				break;
			}
		}

		if (!OverrideFunc)
		{
			WingOut::Stdout.Printf(TEXT("ERROR: '%s' is not an overridable function in this Blueprint.\n"), *Function);
			return;
		}

		// Check if it already exists
		FName FuncName = OverrideFunc->GetFName();
		TSet<FName> ExistingNames;
		FBlueprintEditorUtils::GetAllGraphNames(BP, ExistingNames);
		if (ExistingNames.Contains(FuncName))
		{
			WingOut::Stdout.Printf(TEXT("ERROR: Override graph '%s' already exists.\n"), *Function);
			return;
		}

		UClass* OverrideFuncClass = WingUtils::GetFunctionClass(OverrideFunc);

		UEdGraph* NewGraph = FBlueprintEditorUtils::CreateNewGraph(BP, FuncName,
			UEdGraph::StaticClass(), UEdGraphSchema_K2::StaticClass());
		if (!NewGraph)
		{
			WingOut::Stdout.Print(TEXT("ERROR: Failed to create graph.\n"));
			return;
		}

		FBlueprintEditorUtils::AddFunctionGraph(BP, NewGraph, /*bIsUserCreated=*/false, OverrideFuncClass);

		WingOut::Stdout.Printf(TEXT("Created override: %s\n"), *WingUtils::FormatName(NewGraph));
	}
};
