// Copyright Epic Games, Inc. All Rights Reserved.
// UE5 Modular Game Framework — DA_GameTagRegistry (01)
// Central gameplay tag registry Data Asset. Eliminates the 3 C++-only API workarounds
// (RequestAllGameplayTags, RequestGameplayTag, UGameplayTagsManager singleton access).

#pragma once

#include "CoreMinimal.h"
#include "Engine/DataAsset.h"
#include "GameplayTagContainer.h"
#include "Engine/DataTable.h"
#include "DA_GameTagRegistry.generated.h"

/**
 * DA_GameTagRegistry — Central GameplayTag namespace registry.
 *
 * In C++, this directly wraps UGameplayTagsManager APIs instead of using the
 * Data Table proxy workaround required in Blueprint. Maintains the Data Table
 * references for the Blueprint implementation guide, but the C++ functions
 * bypass them entirely for performance and correctness.
 */
UCLASS(BlueprintType, Blueprintable, meta = (DisplayName = "DA_GameTagRegistry"))
class PG_FRAMEWORK_API UDA_GameTagRegistry : public UPrimaryDataAsset
{
	GENERATED_BODY()

public:
	UDA_GameTagRegistry();

	// ========================================================================
	// Configuration
	// ========================================================================

	/** Human-readable description of the tag namespace (e.g. "Player.State"). */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Documentation")
	FText TagNamespace;

	/** True for framework-defined tags, false for project-specific overrides. */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Documentation")
	bool bIsFrameworkTag = true;

	/**
	 * Array of 11 per-category Data Tables used by Blueprint implementations.
	 * C++ functions use UGameplayTagsManager directly and ignore this array.
	 * Maintained for the Blueprint Manual Implementation Guide.
	 */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Config")
	TArray<TObjectPtr<UDataTable>> TagDataTables;

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

	/**
	 * Returns ALL registered gameplay tags from the engine's tag manager.
	 * C++ implementation: single call to UGameplayTagsManager.
	 * Blueprint equivalent: nested ForEachLoop over 11 Data Tables (workaround).
	 */
	UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Framework|Tags|Query")
	TArray<FGameplayTag> GetAllRegisteredTags() const;

	/**
	 * Returns the human-readable display name of a gameplay tag.
	 */
	UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Framework|Tags|Query")
	FText GetTagDisplayName(const FGameplayTag& Tag) const;

	/**
	 * Validates whether a gameplay tag is registered in the engine's tag table.
	 * Returns false + logs warning for unregistered tags.
	 */
	UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Framework|Tags|Validation")
	bool ValidateTag(const FGameplayTag& Tag) const;

	/**
	 * Validates that a tag exists AND returns it. Fails gracefully with warning.
	 */
	UFUNCTION(BlueprintCallable, Category = "Framework|Tags|Validation")
	FGameplayTag RequestTag(FName TagName, bool bLogWarning = true) const;

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

	/** Prints all registered tags to the output log. Editor-only. */
	UFUNCTION(BlueprintCallable, Category = "Framework|Tags|Debug")
	void LogAllTags() const;

	/**
	 * Exports all tags matching a namespace prefix as a formatted string.
	 * Useful for auditing discrepancies between Data Tables and DefaultGameplayTags.ini.
	 */
	UFUNCTION(BlueprintCallable, Category = "Framework|Tags|Tooling")
	FString ExportTagNamespace(const FString& NamespacePrefix) const;

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

	virtual void PostLoad() override;

#if WITH_EDITOR
	virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
#endif
};
