#include "ZMMOHudWidget.h"

#include "CommonInputTypeEnum.h"  // ECommonInputMode
#include "Engine/World.h"
#include "GameFramework/PlayerController.h"
#include "GameFramework/PlayerState.h"
#include "ZMMO.h"
#include "ZMMOAttributeComponent.h"
#include "ZMMOHudHpSpWidget.h"

UZMMOHudWidget::UZMMOHudWidget(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	// HUD nao bloqueia "back" (Esc / B no controller). Menus reais (StatusWindow,
	// EscapeMenu) sim — eles setam bIsBackHandler=true.
	bIsBackHandler = false;
	// HUD nao reativa stack ao virar topo (e' sempre fundo). Garante que o
	// UCommonActivatableWidgetStack do Layer.Game nao force activate/deactivate.
	bAutoActivate = true;
}

TOptional<FUIInputConfig> UZMMOHudWidget::GetDesiredInputConfig() const
{
	// Modo Game: input flui pro PlayerController/Pawn, mouse capturado (3a pessoa).
	// Sem isso, CommonUI assume Menu config (mostra cursor + bloqueia movimento).
	return FUIInputConfig(ECommonInputMode::Game, EMouseCaptureMode::CapturePermanently);
}

void UZMMOHudWidget::NativeOnActivated()
{
	Super::NativeOnActivated();
	// HUD nao intercepta cliques — mouse passa direto pro Pawn (camera, etc.).
	// Sub-widgets que precisam de click (futuro: hotkeys) podem override.
	SetVisibility(ESlateVisibility::HitTestInvisible);
	BindToLocalPlayer();
	UE_LOG(LogZMMO, Log, TEXT("ZMMOHudWidget activated (HpSpBar=%s)"),
		HpSpBar ? *HpSpBar->GetName() : TEXT("none"));
}

void UZMMOHudWidget::NativeOnDeactivated()
{
	UnbindFromComponent();
	Super::NativeOnDeactivated();
}

void UZMMOHudWidget::NativeDestruct()
{
	UnbindFromComponent();
	Super::NativeDestruct();
}

void UZMMOHudWidget::BindToLocalPlayer()
{
	UWorld* World = GetWorld();
	if (!World) { return; }

	APlayerController* PC = World->GetFirstPlayerController();
	if (!PC) { return; }
	APlayerState* PS = PC->PlayerState;
	if (!PS)
	{
		// PlayerState pode nao existir ainda — race com GameMode setup.
		// AZMMOPlayerCharacter::HandleLocalSpawnReady chama BindToAttributeComponent
		// manualmente como fallback (seed do EntityId).
		UE_LOG(LogZMMO, Log, TEXT("ZMMOHudWidget: PlayerState ausente no activate (race fix via HandleLocalSpawnReady esperado)"));
		return;
	}
	UZMMOAttributeComponent* Comp = PS->FindComponentByClass<UZMMOAttributeComponent>();
	if (!Comp) { return; }
	if (Comp == BoundComponent.Get()) { return; }  // idempotente

	UnbindFromComponent();
	BoundComponent = Comp;

	Comp->OnAttributesChanged.AddDynamic(this, &UZMMOHudWidget::HandleAttributesChanged);
	Comp->OnHpSpChanged.AddDynamic(this, &UZMMOHudWidget::HandleHpSpChanged);
	Comp->OnLevelUp.AddDynamic(this, &UZMMOHudWidget::HandleLevelUp);

	// Refresh imediato — caso o snapshot ja' tenha chegado.
	HandleAttributesChanged(Comp->GetSnapshot());
}

void UZMMOHudWidget::UnbindFromComponent()
{
	if (UZMMOAttributeComponent* Old = BoundComponent.Get())
	{
		Old->OnAttributesChanged.RemoveDynamic(this, &UZMMOHudWidget::HandleAttributesChanged);
		Old->OnHpSpChanged.RemoveDynamic(this, &UZMMOHudWidget::HandleHpSpChanged);
		Old->OnLevelUp.RemoveDynamic(this, &UZMMOHudWidget::HandleLevelUp);
	}
	BoundComponent.Reset();
}

void UZMMOHudWidget::HandleAttributesChanged(const FZMMOAttributesSnapshot& Snapshot)
{
	// Propaga snapshot aos sub-widgets que ja existem. Em V1 so' HpSpBar.
	if (HpSpBar)
	{
		HpSpBar->ApplySnapshot(Snapshot);
	}
	// Futuros: PlayerInfo->ApplySnapshot, Buffs->RefreshIcons, etc.
}

void UZMMOHudWidget::HandleHpSpChanged(int32 Hp, int32 Sp)
{
	if (UZMMOAttributeComponent* Comp = BoundComponent.Get())
	{
		const FZMMOAttributesSnapshot& Snap = Comp->GetSnapshot();
		if (HpSpBar)
		{
			HpSpBar->ApplyHpSp(Hp, Snap.MaxHp, Sp, Snap.MaxSp);
		}
	}
}

void UZMMOHudWidget::HandleLevelUp(int32 NewBaseLevel, int32 StatusPointDelta)
{
	// Snapshot subsequente do AttributeSystem vai disparar HandleAttributesChanged
	// e atualizar HpSpBar->LevelText. Aqui e' o ponto pra efeitos visuais
	// instantaneos (toast "LEVEL UP", confetti, sound). V1 noop — UI pode
	// hook via Blueprint depois.
}
