#pragma once

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "ZMMOAttributeTypes.h"
#include "ZMMOAttributeComponent.generated.h"

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FZMMOOnAttributesChanged, const FZMMOAttributesSnapshot&, Snapshot);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FZMMOOnHpSpChanged, int32, Hp, int32, Sp);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FZMMOOnLevelUp, int32, NewBaseLevel, int32, StatusPointDelta);

/// Resposta server ao C_STAT_ALLOC. Reason e' EAllocRejectReason (None=0,
/// InvalidStat=1, InvalidAmount=2, NotEnoughPoints=3, StatCapped=4, NoSession=5).
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FZMMOOnStatAllocReply, bool, bAccepted, int32, Reason);

/**
 *  Componente de atributos do MMO ligado ao ator que o representa em-jogo
 *  (player local, proxies remotos, NPCs futuros).
 *
 *  Estado authoritative vive no servidor (CharRuntimeStatus em
 *  Game/MMO/Modules/AttributeSystem). Cliente apenas armazena o ultimo
 *  snapshot recebido e expoe delegates para UI/HUD reagir.
 *
 *  Roteamento server → componente: `UZMMOAttributeNetworkHandler`
 *  (UWorldSubsystem) liga em `UZeusNetworkSubsystem::OnAttributeSnapshotFull`,
 *  resolve `EntityId -> AActor*` via `UZMMOWorldSubsystem` e chama
 *  `ApplySnapshot` no componente do ator.
 */
UCLASS(ClassGroup=(ZMMO), meta=(BlueprintSpawnableComponent),
       hidecategories=(Activation, Collision, Cooking, Object, Replication))
class ZMMOATTRIBUTES_API UZMMOAttributeComponent : public UActorComponent
{
	GENERATED_BODY()

public:
	UZMMOAttributeComponent();

	/// Aplica snapshot full recebido do servidor. Substitui `Current` e
	/// dispara `OnAttributesChanged` + `OnHpSpChanged` (se hp/sp mudaram).
	UFUNCTION(BlueprintCallable, Category = "Zeus|Attributes")
	void ApplySnapshot(const FZMMOAttributesSnapshot& InSnapshot);

	/// Aplica apenas delta de HP/SP (sem mexer em outros campos).
	UFUNCTION(BlueprintCallable, Category = "Zeus|Attributes")
	void ApplyHpSpUpdate(int32 NewHp, int32 NewSp);

	/// Notifica level up — o snapshot subsequente atualiza demais campos.
	UFUNCTION(BlueprintCallable, Category = "Zeus|Attributes")
	void NotifyLevelUp(int32 NewBaseLevel, int32 StatusPointDelta);

	/// Notifica resposta server ao C_STAT_ALLOC. UI pode reagir (toast/SFX
	/// quando aceito, erro vermelho quando rejeitado).
	UFUNCTION(BlueprintCallable, Category = "Zeus|Attributes")
	void NotifyStatAllocReply(bool bAccepted, int32 Reason);

	/// Envia C_STAT_ALLOC pro server. Wrapper conveniente — busca o
	/// UZeusNetworkSubsystem via GameInstance + chama SendStatAlloc.
	/// `StatId`: 0=STR, 1=AGI, 2=VIT, 3=INT, 4=DEX, 5=LUK. `Amount`: 1..10.
	UFUNCTION(BlueprintCallable, Category = "Zeus|Attributes")
	void RequestStatAlloc(int32 StatId, int32 Amount = 1);

	/// Seed do EntityId vindo de S_SPAWN_PLAYER local. Chamado pelo
	/// `AZMMOPlayerCharacter` antes do primeiro S_ATTRIBUTE_SNAPSHOT_FULL
	/// chegar, garantindo que o NetworkHandler consiga rotear via lookup
	/// por EntityId desde o inicio.
	UFUNCTION(BlueprintCallable, Category = "Zeus|Attributes")
	void SeedEntityId(int32 InEntityId) { Current.EntityId = InEntityId; }

	UFUNCTION(BlueprintPure, Category = "Zeus|Attributes")
	const FZMMOAttributesSnapshot& GetSnapshot() const { return Current; }

	UFUNCTION(BlueprintPure, Category = "Zeus|Attributes")
	float GetHpRatio() const
	{
		return Current.MaxHp > 0 ? static_cast<float>(Current.Hp) / static_cast<float>(Current.MaxHp) : 0.f;
	}

	UFUNCTION(BlueprintPure, Category = "Zeus|Attributes")
	float GetSpRatio() const
	{
		return Current.MaxSp > 0 ? static_cast<float>(Current.Sp) / static_cast<float>(Current.MaxSp) : 0.f;
	}

	// === Delegates Blueprint ===

	/** Snapshot novo aplicado. Use isto na UI para refresh geral. */
	UPROPERTY(BlueprintAssignable, Category = "Zeus|Attributes")
	FZMMOOnAttributesChanged OnAttributesChanged;

	/** HP ou SP mudou (efêmero ou via snapshot). Para barras animadas. */
	UPROPERTY(BlueprintAssignable, Category = "Zeus|Attributes")
	FZMMOOnHpSpChanged OnHpSpChanged;

	/** Subiu de nível. Para efeitos visuais ("LEVEL UP!" toast). */
	UPROPERTY(BlueprintAssignable, Category = "Zeus|Attributes")
	FZMMOOnLevelUp OnLevelUp;

	/** Resposta ao C_STAT_ALLOC (aceito ou rejeitado). UI reage. */
	UPROPERTY(BlueprintAssignable, Category = "Zeus|Attributes")
	FZMMOOnStatAllocReply OnStatAllocReply;

protected:
	UPROPERTY(BlueprintReadOnly, Category = "Zeus|Attributes")
	FZMMOAttributesSnapshot Current;
};
