#pragma once

#include "CoreMinimal.h"
#include "WingServer.h"
#include "WingHandler.h"
#include "WingFetcher.h"
#include "WingProperty.h"
#include "WingUtils.h"
#include "WingGraphActions.h"
#include "EdGraph/EdGraph.h"
#include "EdGraph/EdGraphNode.h"
#include "EdGraph/EdGraphSchema.h"
#include "GraphNode_Create.generated.h"


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

USTRUCT()
struct FSpawnNodeEntry
{
	GENERATED_BODY()

	UPROPERTY()
	FString ActionName;

	UPROPERTY()
	int32 PosX = 0;

	UPROPERTY()
	int32 PosY = 0;
};


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

public:
	UPROPERTY(EditAnywhere, meta=(Description="Target graph"))
	FString Graph;

	UPROPERTY(EditAnywhere, meta=(Description="Array of {Type, posX, posY} objects. Use GraphNode_SearchTypes to find types."))
	FWingJsonArray Nodes;

	virtual void Register() override
	{
		UWingServer::AddHandler(this,
			TEXT("Create nodes using the editor's action database. "
			"Use GraphNode_SearchTypes to find types."));
	}
	virtual void Handle() override
	{
		WingFetcher F;
		UEdGraph* TargetGraph = F.Walk(Graph).Cast<UEdGraph>();
		if (!TargetGraph) return;

		int32 SuccessCount = 0;
		int32 TotalCount = Nodes.Array.Num();
		FWingGraphActions GraphActions(TargetGraph);
		
		for (const TSharedPtr<FJsonValue>& NodeVal : Nodes.Array)
		{
			FSpawnNodeEntry Entry;
			if (!FWingProperty::PopulateFromJson(FSpawnNodeEntry::StaticStruct(), &Entry, NodeVal))
				continue;

			// Find the action by exact full name
			TArray<FWingGraphAction*> Results = GraphActions.Search(Entry.ActionName, 2, true);
			if (Results.Num() == 0)
			{
				UWingServer::Printf(TEXT("ERROR: No action found matching '%s'. Use GraphNode_SearchTypes to find available actions.\n"),
					*Entry.ActionName);
				continue;
			}
			if (Results.Num() > 1)
			{
				UWingServer::Printf(TEXT("ERROR: More than one action matches '%s'.\n"), *Entry.ActionName);
				continue;
			}

			// Perform the action
			UEdGraphNode* NewNode = Results[0]->Execute(FVector2D(Entry.PosX, Entry.PosY));
			if (!NewNode)
			{
				UWingServer::Printf(TEXT("ERROR: Execute returned null for '%s'.\n"), *Entry.ActionName);
				continue;
			}

			if (!NewNode->NodeGuid.IsValid())
				NewNode->CreateNewGuid();

			UWingServer::Printf(TEXT("Spawned: %s (%s)\n"),
				*WingUtils::FormatName(NewNode), *WingUtils::FormatName(NewNode->GetClass()));
			SuccessCount++;
		}

		UWingServer::Printf(TEXT("Spawned %d/%d nodes.\n"), SuccessCount, TotalCount);
	}
};
