// Copyright ExByte Studios. Item Interaction Ecosystem.

#pragma once

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "ItemPlacementRules.h"
#include "PlacementPreviewComponent.generated.h"

class UStaticMeshComponent;
struct FItemDefinitionRow;

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPlacementStateChanged, bool, bIsValid);

/**
 * Drives the local ghost-mesh preview and the server-validated confirm for
 * placeable items (section 13). The client shows a green/red ghost; the server
 * re-runs every rule before committing (collision, slope, distance, surface).
 */
UCLASS(ClassGroup = (Placement), meta = (BlueprintSpawnableComponent))
class ITEMPLACEMENT_API UPlacementPreviewComponent : public UActorComponent
{
	GENERATED_BODY()

public:
	UPlacementPreviewComponent();

	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
	virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;

	UPROPERTY(BlueprintReadOnly, Category = "Placement")
	bool bIsPlacing = false;

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

	UPROPERTY(BlueprintReadOnly, Category = "Placement")
	FGuid ItemInstanceId;

	UPROPERTY(BlueprintReadOnly, Category = "Placement")
	FTransform PreviewTransform = FTransform::Identity;

	UPROPERTY(BlueprintReadOnly, Category = "Placement")
	bool bCurrentValid = false;

	UPROPERTY(BlueprintAssignable, Category = "Placement")
	FOnPlacementStateChanged OnPlacementStateChanged;

	/** Client: begin placing an inventory item. */
	UFUNCTION(BlueprintCallable, Category = "Placement")
	void StartPlacement(FGuid InstanceId);

	/** Client: confirm at the current preview transform (sends a server request). */
	UFUNCTION(BlueprintCallable, Category = "Placement")
	void ConfirmPlacement();

	/** Client: abort placement. */
	UFUNCTION(BlueprintCallable, Category = "Placement")
	void CancelPlacement();

	UFUNCTION(BlueprintCallable, Category = "Placement")
	void RotatePreview(float DeltaYawDegrees);

	/** Pure rule check used by both the client preview and the server (section 13.3). */
	static bool ValidatePlacement(const UObject* WorldContext, const FItemDefinitionRow& Def,
		const FTransform& Transform, AActor* Instigator, FString& OutReason);

protected:
	UFUNCTION(Server, Reliable)
	void Server_ConfirmPlacement(FGuid InstanceId, FTransform Transform);

private:
	UPROPERTY(Transient)
	TObjectPtr<UStaticMeshComponent> Ghost = nullptr;

	float PreviewYaw = 0.f;

	bool ComputePreviewTransform(FTransform& OutTransform) const;
	void DestroyGhost();
	void SetValidity(bool bNewValid);
	bool GetViewPoint(FVector& OutLoc, FRotator& OutRot) const;
};
