// Copyright Epic Games, Inc. All Rights Reserved.
// UE5 Modular Game Framework — DA_ItemData (07)
// Base item Data Asset. Single source of truth for every item.
// C++ gives us UPROPERTY metadata (EditCondition, EditConditionHides, ClampMin/Max)
// that make the Data Asset editor usable for designers — impossible in Blueprint.

#pragma once

#include "CoreMinimal.h"
#include "Engine/DataAsset.h"
#include "GameplayTagContainer.h"
#include "Engine/Texture2D.h"
#include "Engine/StaticMesh.h"
#include "DA_ItemData.generated.h"

/**
 * Item type classification.
 */
UENUM(BlueprintType)
enum class EItemType : uint8
{
	Weapon     UMETA(DisplayName = "Weapon"),
	Ammo       UMETA(DisplayName = "Ammo"),
	Consumable UMETA(DisplayName = "Consumable"),
	KeyItem    UMETA(DisplayName = "Key Item"),
	Document   UMETA(DisplayName = "Document"),
	Collectible UMETA(DisplayName = "Collectible"),
	Tool       UMETA(DisplayName = "Tool"),
	Resource   UMETA(DisplayName = "Resource"),
	Misc       UMETA(DisplayName = "Misc"),
};

/**
 * Equipment slot type.
 */
UENUM(BlueprintType)
enum class EEquipmentSlot : uint8
{
	None        UMETA(DisplayName = "None"),
	PrimaryWeapon UMETA(DisplayName = "Primary Weapon"),
	SecondaryWeapon UMETA(DisplayName = "Secondary Weapon"),
	Melee       UMETA(DisplayName = "Melee"),
	Tool        UMETA(DisplayName = "Tool"),
	Armor       UMETA(DisplayName = "Armor"),
	Accessory   UMETA(DisplayName = "Accessory"),
};

/**
 * Equipment-specific data (shown when ItemType is Weapon or Tool).
 */
USTRUCT(BlueprintType)
struct PG_FRAMEWORK_API FItemEquipmentData
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	EEquipmentSlot Slot = EEquipmentSlot::None;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float Damage = 0.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float FireRate = 0.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float Range = 0.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	int32 MagazineSize = 0;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float ReloadTime = 0.0f;
};

/**
 * Consumable-specific data (shown when ItemType is Consumable).
 */
USTRUCT(BlueprintType)
struct PG_FRAMEWORK_API FItemConsumableData
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ClampMin = "0", ClampMax = "100"))
	float HealthRestore = 0.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ClampMin = "0", ClampMax = "100"))
	float StressReduce = 0.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float UseDuration = 1.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	bool bConsumedOnUse = true;
};

/**
 * Inspect-specific data (shown when bHasInspectMode is true).
 */
USTRUCT(BlueprintType)
struct PG_FRAMEWORK_API FItemInspectData
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FVector AnchorPoint = FVector::ZeroVector;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FRotator DefaultRotation = FRotator::ZeroRotator;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float ZoomDistance = 50.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	bool bCanRotate = true;
};

/**
 * DA_ItemData — Base Item Data Asset.
 *
 * Every item in the game is one DA_ItemData asset. No item data lives in
 * Blueprint logic. C++ gives us EditCondition metadata so the editor only
 * shows relevant sub-structs based on ItemType — a massive UX win for designers.
 */
UCLASS(BlueprintType, Blueprintable, meta = (DisplayName = "Item Data"))
class PG_FRAMEWORK_API UDA_ItemData : public UPrimaryDataAsset
{
	GENERATED_BODY()

public:
	UDA_ItemData();

	// ========================================================================
	// Core Properties (Every Item Has These)
	// ========================================================================

	/** Unique GameplayTag identifier. Must be registered in DA_GameTagRegistry. */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Core")
	FGameplayTag ItemTag;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Core")
	FText DisplayName;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Core", meta = (MultiLine = true))
	FText Description;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Core")
	TSoftObjectPtr<UTexture2D> Icon;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Core")
	TSoftObjectPtr<UStaticMesh> WorldMesh;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Core", meta = (ClampMin = "0", ClampMax = "1000"))
	float Weight = 0.0f;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Core", meta = (ClampMin = "1", ClampMax = "999"))
	int32 StackLimit = 1;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Core")
	EItemType ItemType = EItemType::Misc;

	// ========================================================================
	// Conditional Sub-Data (Shown Based on ItemType via EditCondition)
	// ========================================================================

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Equipment",
		meta = (EditCondition = "ItemType == EItemType::Weapon || ItemType == EItemType::Tool", EditConditionHides))
	FItemEquipmentData EquipmentData;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Consumable",
		meta = (EditCondition = "ItemType == EItemType::Consumable", EditConditionHides))
	FItemConsumableData ConsumableData;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Inspect",
		meta = (EditCondition = "bHasInspectMode", EditConditionHides))
	FItemInspectData InspectData;

	// ========================================================================
	// Flags
	// ========================================================================

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Flags")
	bool bIsKeyItem = false;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Flags")
	bool bCanBeDropped = true;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Flags")
	bool bHasInspectMode = false;

	// ========================================================================
	// Combination / Crafting
	// ========================================================================

	/** Tags of items this can combine with. */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Combination")
	TArray<FGameplayTag> CombinesWith;

	/** The resulting item tag when combined with CombinesWith item. */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Combination")
	FGameplayTag CombineResult;

	// ========================================================================
	// Extensibility
	// ========================================================================

	/** Custom per-project properties — no need to modify the base class. */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Custom")
	TMap<FName, FString> CustomProperties;

	// ========================================================================
	// Validation (Editor-Only)
	// ========================================================================

#if WITH_EDITOR
	/**
	 * Validates the item data asset for common errors.
	 * Called by editor utilities or pre-save validation.
	 */
	UFUNCTION(BlueprintCallable, Category = "Item|Validation")
	bool ValidateItemData(FString& OutErrors) const;
#endif

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

	virtual void PostLoad() override;

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