#pragma once

#include "CoreMinimal.h"
#include "WingHandler.h"
#include "WingFetcher.h"
#include "WingTypes.h"
#include "WingUtils.h"
#include "WingServer.h"
#include "Engine/Blueprint.h"
#include "Kismet2/BlueprintEditorUtils.h"
#include "BlueprintInterface_Add.generated.h"


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

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

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

	UPROPERTY(EditAnywhere, meta=(Description="Native UInterface class name or Blueprint Interface package path"))
	FString Interface;

	virtual void Register() override
	{
		UWingServer::AddHandler(this,
			TEXT("Add an interface to a blueprint"));
	}
	virtual void Handle() override
	{
		WingFetcher F;
		UBlueprint* BP = F.Asset(Blueprint).Cast<UBlueprint>();
		if (!BP) return;

		// Resolve the interface class
		UWingTypes::Requirements Req;
		Req.BlueprintType = false;
		Req.Blueprintable = false;
		Req.AllowContainer = false;
		UClass* InterfaceClass = UWingTypes::TextToOneInterfaceType(Interface, Req);
		if (!InterfaceClass) return;

		// Check for duplicates
		for (const FBPInterfaceDescription& IfaceDesc : BP->ImplementedInterfaces)
		{
			if (IfaceDesc.Interface == InterfaceClass)
			{
				UWingServer::Printf(TEXT("ERROR: Interface '%s' is already implemented by this Blueprint.\n"),
					*WingUtils::FormatName(InterfaceClass));
				return;
			}
		}

		FTopLevelAssetPath InterfacePath = InterfaceClass->GetClassPathName();
		bool bAdded = FBlueprintEditorUtils::ImplementNewInterface(BP, InterfacePath);
		if (!bAdded)
		{
			UWingServer::Printf(TEXT("ERROR: ImplementNewInterface failed for '%s'.\n"),
				*WingUtils::FormatName(InterfaceClass));
			return;
		}

		// Collect stub function graph names from the newly added interface entry
		UWingServer::Printf(TEXT("Added interface %s\n"), *WingUtils::FormatName(InterfaceClass));
		for (const FBPInterfaceDescription& IfaceDesc : BP->ImplementedInterfaces)
		{
			if (IfaceDesc.Interface != InterfaceClass) continue;
			for (const UEdGraph* Graph : IfaceDesc.Graphs)
			{
				UWingServer::Printf(TEXT("New Graph: %s\n"), *WingUtils::FormatName(Graph));
			}
			break;
		}
	}
};
