// Copyright ExByte Studios. Item Interaction Ecosystem.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "ItemInstanceData.h"
#include "ItemInteractionInterfaces.h"
#include "PickupItemActor.generated.h"

class UStaticMeshComponent;
class UInteractableComponent;

/**
 * The world representation of an item lying on the ground / a surface (section 12).
 *
 * One actor per world item only (never one per inventory item - section 32/34).
 * Implements IWorldItemProvider so the interaction layer can pick it up, carry it
 * or take part of its stack without ItemWorld <-> ItemInteraction coupling.
 */
UCLASS()
class ITEMWORLD_API APickupItemActor : public AActor, public IWorldItemProvider
{
	GENERATED_BODY()

public:
	APickupItemActor();

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

	/** Server: stamp this pickup with an item and refresh its visuals. */
	UFUNCTION(BlueprintCallable, Category = "Item|World")
	void InitializeFromItem(const FItemInstanceData& InItem);

	/** Server convenience: spawn a fresh pickup for ItemId at a transform. */
	UFUNCTION(BlueprintCallable, Category = "Item|World", meta = (WorldContext = "WorldContext"))
	static APickupItemActor* SpawnPickup(UObject* WorldContext, FName ItemId, int32 Quantity, const FTransform& Transform);

	/** Server convenience: spawn a pickup carrying an existing instance (e.g. on drop). */
	static APickupItemActor* SpawnPickupFromInstance(UObject* WorldContext, const FItemInstanceData& Item, const FTransform& Transform);

	//~ IWorldItemProvider
	virtual bool GetProvidedItem(FItemInstanceData& OutItem) const override;
	virtual bool IsItemAvailable() const override;
	virtual void NotifyItemTaken(AActor* Taker) override;
	virtual void UpdateProvidedItem(const FItemInstanceData& RemainingItem) override;
	virtual void SetCarried(AActor* Holder, bool bCarried) override;

	/** Server: drop this carried actor back into the world at a transform. */
	void ReleaseToWorld(const FTransform& WorldTransform);

	UStaticMeshComponent* GetMeshComponent() const { return Mesh; }

	UFUNCTION(BlueprintPure, Category = "Item|World")
	const FItemInstanceData& GetItemData() const { return ItemData; }

protected:
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Item|World")
	TObjectPtr<USceneComponent> Root;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Item|World")
	TObjectPtr<UStaticMeshComponent> Mesh;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Item|World")
	TObjectPtr<UInteractableComponent> Interactable;

	UPROPERTY(ReplicatedUsing = OnRep_ItemData, BlueprintReadOnly, Category = "Item|World")
	FItemInstanceData ItemData;

	UPROPERTY(Replicated, BlueprintReadOnly, Category = "Item|World")
	bool bIsLocked = false;

	UPROPERTY(Replicated, BlueprintReadOnly, Category = "Item|World")
	TObjectPtr<AActor> CurrentHolder = nullptr;

	UFUNCTION()
	void OnRep_ItemData();

	/** Resolves the definition and applies WorldMesh + interactable display name. */
	void RefreshVisuals();
};
