// Copyright ExByte Studios. Item Interaction Ecosystem.

#pragma once

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "GameplayTagContainer.h"
#include "ItemInstanceData.h"
#include "EquipmentComponent.generated.h"

/**
 * One equipped slot (section 11.2 Equipped). The item itself stays in the
 * inventory; only the visual actor is spawned and replicated.
 */
USTRUCT(BlueprintType)
struct FEquippedItemEntry
{
	GENERATED_BODY()

	UPROPERTY(BlueprintReadOnly, Category = "Equipment")
	FGameplayTag SlotTag;

	UPROPERTY(BlueprintReadOnly, Category = "Equipment")
	FGuid InstanceId;

	UPROPERTY(BlueprintReadOnly, Category = "Equipment")
	FName ItemId;

	UPROPERTY(BlueprintReadOnly, Category = "Equipment")
	TObjectPtr<AActor> EquippedActor = nullptr;
};

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnEquipmentChanged);

/**
 * Spawns/attaches the visual actors for equipped items (section 7, 11.2, 31.5).
 *
 * Equip keeps the item in the inventory and only manages the EquippedActorClass
 * visual - distinct from carry (UHeldItemComponent), which physically removes the
 * item from storage. Owner-only item truth, everyone sees the visual (section 22/25).
 */
UCLASS(ClassGroup = (Inventory), meta = (BlueprintSpawnableComponent))
class ITEMWORLD_API UEquipmentComponent : public UActorComponent
{
	GENERATED_BODY()

public:
	UEquipmentComponent();

	virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
	virtual void OnUnregister() override;

	/** Socket per slot tag; falls back to DefaultEquipSocket. */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Equipment")
	TMap<FGameplayTag, FName> SlotSockets;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Equipment")
	FName DefaultEquipSocket = FName("hand_rSocket");

	UPROPERTY(BlueprintAssignable, Category = "Equipment")
	FOnEquipmentChanged OnEquipmentChanged;

	/** Server: equip an inventory item into a slot (Inventory -> Equipped). */
	bool ServerEquip(FGuid InstanceId, FGameplayTag SlotTag);

	/** Server: remove the equipped visual from a slot. */
	bool ServerUnequip(FGameplayTag SlotTag);

	UFUNCTION(BlueprintPure, Category = "Equipment")
	bool IsSlotEquipped(FGameplayTag SlotTag) const;

	UFUNCTION(BlueprintPure, Category = "Equipment")
	void GetEquippedEntries(TArray<FEquippedItemEntry>& OutEntries) const { OutEntries = Equipped; }

protected:
	UPROPERTY(ReplicatedUsing = OnRep_Equipped)
	TArray<FEquippedItemEntry> Equipped;

	UFUNCTION()
	void OnRep_Equipped();

	FName ResolveSocket(const FGameplayTag& SlotTag) const;
	USceneComponent* GetAttachTarget() const;
	bool HasAuthority() const;
};
