// Copyright Epic Games, Inc. All Rights Reserved.
// UE5 Modular Game Framework — DA_GameTagRegistry Implementation

#include "Core/DA_GameTagRegistry.h"
#include "GameplayTagsManager.h"
#include "Engine/DataTable.h"


UDA_GameTagRegistry::UDA_GameTagRegistry()
{
	TagNamespace = FText::FromString(TEXT("Framework tag namespace documentation"));
}

// ============================================================================
// Query Functions
// ============================================================================

TArray<FGameplayTag> UDA_GameTagRegistry::GetAllRegisteredTags() const
{
	TArray<FGameplayTag> AllTags;

	// C++ direct access — eliminates the Data Table proxy workaround entirely.
	UGameplayTagsManager& TagManager = UGameplayTagsManager::Get();

	FGameplayTagContainer AllRegisteredTags;
	TagManager.RequestAllGameplayTags(AllRegisteredTags, true);

	AllTags = AllRegisteredTags.GetGameplayTagArray();

	UE_LOG(LogTemp, Verbose, TEXT("DA_GameTagRegistry::GetAllRegisteredTags — %d tags found"), AllTags.Num());

	return AllTags;
}

FText UDA_GameTagRegistry::GetTagDisplayName(const FGameplayTag& Tag) const
{
	if (!Tag.IsValid())
	{
		return FText::FromString(TEXT("Invalid Tag"));
	}

	return FText::FromName(Tag.GetTagName());
}

bool UDA_GameTagRegistry::ValidateTag(const FGameplayTag& Tag) const
{
	if (Tag.IsValid())
	{
		return true;
	}

	UE_LOG(LogTemp, Warning, TEXT("DA_GameTagRegistry::ValidateTag — Invalid Tag: %s"),
		*Tag.GetTagName().ToString());
	return false;
}

FGameplayTag UDA_GameTagRegistry::RequestTag(FName TagName, bool bLogWarning) const
{
	if (TagName.IsNone())
	{
		return FGameplayTag::EmptyTag;
	}

	UGameplayTagsManager& TagManager = UGameplayTagsManager::Get();
	TSharedPtr<FGameplayTagNode> TagNode = TagManager.FindTagNode(TagName);

	FGameplayTag OutTag = TagManager.RequestGameplayTag(TagName, false);
	if (OutTag.IsValid())
	{
		return OutTag;
	}

	if (bLogWarning)
	{
		UE_LOG(LogTemp, Warning, TEXT("DA_GameTagRegistry::RequestTag — Tag '%s' not found in any registered table"),
			*TagName.ToString());
	}

	return FGameplayTag::EmptyTag;
}

// ============================================================================
// Debug / Tooling
// ============================================================================

void UDA_GameTagRegistry::LogAllTags() const
{
#if !UE_BUILD_SHIPPING
	TArray<FGameplayTag> AllTags = GetAllRegisteredTags();

	UE_LOG(LogTemp, Log, TEXT("========== DA_GameTagRegistry: All Registered Tags (%d total) =========="),
		AllTags.Num());

	for (const FGameplayTag& Tag : AllTags)
	{
		UE_LOG(LogTemp, Log, TEXT("  %s"), *Tag.GetTagName().ToString());
	}

	UE_LOG(LogTemp, Log, TEXT("========== End Tag List =========="));
#endif
}

FString UDA_GameTagRegistry::ExportTagNamespace(const FString& NamespacePrefix) const
{
	TArray<FGameplayTag> AllTags = GetAllRegisteredTags();
	FString Output;

	for (const FGameplayTag& Tag : AllTags)
	{
		FString TagString = Tag.GetTagName().ToString();
		if (TagString.StartsWith(NamespacePrefix))
		{
			Output += TagString + TEXT("\n");
		}
	}

	return Output;
}

// ============================================================================
// Overrides
// ============================================================================

void UDA_GameTagRegistry::PostLoad()
{
	Super::PostLoad();

	// Validate on load — catch misconfigured projects early.
	TArray<FGameplayTag> AllTags = GetAllRegisteredTags();

	if (AllTags.Num() == 0)
	{
		UE_LOG(LogTemp, Warning, TEXT("DA_GameTagRegistry::PostLoad — No Gameplay Tags registered! "
			"Check Project Settings → GameplayTags → Gameplay Tag Table List. "
			"All 11 Data Tables must be added."));
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("DA_GameTagRegistry::PostLoad — %d tags registered"), AllTags.Num());
	}
}

#if WITH_EDITOR
void UDA_GameTagRegistry::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
	Super::PostEditChangeProperty(PropertyChangedEvent);

	// Re-validate when TagDataTables array changes in editor.
	FName PropertyName = PropertyChangedEvent.GetPropertyName();
	if (PropertyName == GET_MEMBER_NAME_CHECKED(UDA_GameTagRegistry, TagDataTables))
	{
		TArray<FGameplayTag> AllTags = GetAllRegisteredTags();
		UE_LOG(LogTemp, Log, TEXT("DA_GameTagRegistry: TagDataTables updated — %d tags now registered"), AllTags.Num());
	}
}
#endif
