// Copyright ExByte Studios. Item Interaction Ecosystem.

#pragma once

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

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnWorldSlotChanged);

/** Replicated state of a world slot's contents (section 14). */
USTRUCT()
struct FWorldSlotInstalledState
{
	GENERATED_BODY()

	UPROPERTY()
	bool bHasItem = false;

	UPROPERTY()
	FItemInstanceData Item;
};

/**
 * A socket on a world object that accepts an installed item (section 14):
 * Vehicle.Socket.Battery, Generator.Socket.Fuel, Door.Socket.BarricadePlank,
 * Trap.Socket.Bait, etc. One component per slot.
 */
UCLASS(ClassGroup = (Interaction), meta = (BlueprintSpawnableComponent))
class ITEMWORLD_API UWorldItemSlotComponent : public UActorComponent
{
	GENERATED_BODY()

public:
	UWorldItemSlotComponent();

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

	/** This slot's identity; items list it in CompatibleWorldSlots to fit. */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "World Slot")
	FGameplayTag SlotTag;

	/** Optional extra gate; empty = accept anything whose CompatibleWorldSlots has SlotTag. */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "World Slot")
	FGameplayTagContainer AcceptedItemTags;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "World Slot")
	FName AttachSocketName = NAME_None;

	UPROPERTY(BlueprintAssignable, Category = "World Slot")
	FOnWorldSlotChanged OnSlotChanged;

	UFUNCTION(BlueprintPure, Category = "World Slot")
	bool IsOccupied() const { return InstalledItem.bHasItem; }

	UFUNCTION(BlueprintPure, Category = "World Slot")
	bool CanInstall(const FItemInstanceData& Item) const;

	UFUNCTION(BlueprintPure, Category = "World Slot")
	FItemInstanceData GetInstalledItem() const { return InstalledItem.Item; }

	/** Server: install an item. ProvidedVisual (e.g. a carried actor) is reused if given. */
	bool InstallItem(const FItemInstanceData& Item, AActor* ProvidedVisual = nullptr);

	/** Server: remove and return the installed item. */
	bool RemoveItem(FItemInstanceData& OutItem);

protected:
	UPROPERTY(ReplicatedUsing = OnRep_InstalledItem)
	FWorldSlotInstalledState InstalledItem;

	/** Server-spawned visual for the installed item (if not provided externally). */
	UPROPERTY(Replicated)
	TObjectPtr<AActor> InstalledVisual = nullptr;

	UFUNCTION()
	void OnRep_InstalledItem();

	USceneComponent* GetAttachTarget() const;
	bool HasAuthority() const;
};
