#pragma once

#include "CommonActivatableWidget.h"
#include "CoreMinimal.h"
#include "Engine/TimerHandle.h"
#include "ZMMOAttributeTypes.h"
#include "ZMMOHudWidget.generated.h"

class UTextBlock;
class UWidget;
class UZMMOAttributeComponent;
class UZMMOHudHpSpWidget;
class UZMMOHudPlayerVitalsWidget;

/**
 *  Root da HUD de gameplay. UCommonActivatableWidget pushed pelo
 *  UUIInGameFlowSubsystem em UI.Layer.Game quando o estado vira `Playing`.
 *
 *  **Vive em ZMMO core** (UI/InGame/) porque o HUD root e' generico pra
 *  qualquer GameType — sub-widgets vem dos modulos especializados
 *  (HpSpBar do sub-modulo ZMMOAttributes, Minimap de ZMMOMap futuro,
 *  Chat de ZMMOChat futuro, etc.).
 *
 *  Padrao **composite**: o WBP_HUD (filho) declara as PECAS visuais como
 *  sub-widgets BindWidgetOptional, e este C++ orquestra:
 *   1. Em NativeOnActivated: auto-binda no UZMMOAttributeComponent do
 *      player local (vive no PlayerState via Component Registry)
 *   2. Subscreve aos delegates do componente (OnAttributesChanged,
 *      OnHpSpChanged, OnLevelUp)
 *   3. Propaga os deltas pros sub-widgets via metodos publicos
 *      (HpSpBar->ApplySnapshot, HpSpBar->ApplyHpSp, etc.)
 *
 *  Composicao prevista (sub-widgets — todos `BindWidgetOptional` pra
 *  permitir GameTypes sem modulos opcionais — ex.: Survival sem stats RO):
 *   - HpSpBar     (UZMMOHudHpSpWidget — sub-modulo ZMMOAttributes) — impl
 *   - PlayerInfo  (futuro — nome/job/level/exp bar)
 *   - Minimap     (futuro)
 *   - QuickBar    (futuro — hotkeys de skills)
 *   - Buffs       (futuro — icones SC ativos)
 *   - Chat        (futuro)
 *   - TargetInfo  (futuro — HP/SP/nome do mob/player targetado)
 *
 *  Adicionar novo sub-widget = adicionar campo BindWidgetOptional aqui +
 *  setup no NativeOnActivated/handlers + adicionar no WBP_HUD.
 *
 *  Pra mudar o LAYOUT visual ou skin do HUD: edita o WBP_HUD (filho)
 *  no Designer — sem tocar este C++.
 */
UCLASS(Abstract, Blueprintable, BlueprintType)
class ZMMO_API UZMMOHudWidget : public UCommonActivatableWidget
{
	GENERATED_BODY()

public:
	UZMMOHudWidget(const FObjectInitializer& ObjectInitializer);

protected:
	virtual void NativeOnActivated() override;
	virtual void NativeOnDeactivated() override;
	virtual void NativeDestruct() override;

	/**
	 *  HUD passa input direto pro Pawn — sem capturar mouse/teclado. Override
	 *  retorna `TOptional<FUIInputConfig>(unset)`. Sem isso, UCommonActivatableWidget
	 *  default usa Menu config (`SetInputMode_GameAndUI` + mouse cursor), o que
	 *  desativa input de gameplay.
	 *
	 *  Menus (StatusWindow, Inventory, etc.) override e' diferente — eles
	 *  retornam GameAndMenu/Menu pra mostrar cursor + bloquear movement.
	 */
	virtual TOptional<FUIInputConfig> GetDesiredInputConfig() const override;

	/// Sub-widget HP/SP/level (sub-modulo ZMMOAttributes). BindWidgetOptional
	/// — WBP_HUD pode omitir se o GameType nao usa Attributes (Survival, etc.).
	UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
	UZMMOHudHpSpWidget* HpSpBar = nullptr;

	/// Painel de vitais novo (portrait + nome/job/level + HP/SP/EXP/JOB bars).
	/// Substitui o HpSpBar legado. BindWidgetOptional — coexiste durante a
	/// migração; o WBP_HUD pode ter um ou outro.
	UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
	UZMMOHudPlayerVitalsWidget* PlayerVitals = nullptr;

	/// Container do toast "LEVEL UP!" (Fase 3). Hidden por default; em
	/// `HandleLevelUp` vira visivel por `LevelUpToastDurationSec` segundos
	/// (ver `Show/HideLevelUpToast`). WBP_HUD coloca um Border + Image + TextBlock
	/// dentro deste container; este C++ controla apenas o lifecycle visivel/hidden.
	UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD|LevelUp")
	UWidget* LevelUpToastContainer = nullptr;

	/// Texto exibido no toast — formato "LEVEL UP!  Lv X" (X = novo level).
	/// Tambem BindWidgetOptional; WBP_HUD pode usar texto estatico no design.
	UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD|LevelUp")
	UTextBlock* LevelUpToastText = nullptr;

	/// Duracao do toast em segundos. Configuravel no BP filho.
	UPROPERTY(EditDefaultsOnly, Category = "Zeus|HUD|LevelUp")
	float LevelUpToastDurationSec = 2.5f;

	// === Futuros sub-widgets ===
	// UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional)) UZMMOHudPlayerInfoWidget* PlayerInfo = nullptr;
	// UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional)) UZMMOHudMinimapWidget* Minimap = nullptr;
	// UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional)) UZMMOHudQuickBarWidget* QuickBar = nullptr;
	// UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional)) UZMMOHudBuffsWidget* Buffs = nullptr;
	// UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional)) UZMMOHudChatWidget* Chat = nullptr;
	// UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional)) UZMMOHudTargetInfoWidget* TargetInfo = nullptr;

	UFUNCTION(BlueprintPure, Category = "Zeus|HUD")
	UZMMOAttributeComponent* GetBoundComponent() const { return BoundComponent.Get(); }

private:
	/// Tenta achar o UZMMOAttributeComponent do player local + subscrever
	/// nos delegates. Idempotente.
	void BindToLocalPlayer();
	void UnbindFromComponent();

	UFUNCTION()
	void HandleAttributesChanged(const FZMMOAttributesSnapshot& Snapshot);

	UFUNCTION()
	void HandleHpSpChanged(int32 Hp, int32 Sp);

	UFUNCTION()
	void HandleLevelUp(int32 NewBaseLevel, int32 StatusPointDelta);

	UPROPERTY(Transient)
	TWeakObjectPtr<UZMMOAttributeComponent> BoundComponent;

	void ShowLevelUpToast(int32 NewBaseLevel);
	void HideLevelUpToast();

	FTimerHandle LevelUpToastHideTimer;
};
