#pragma once

#include "CoreMinimal.h"
#include "CommonButtonBase.h"
#include "UIButton_Base.generated.h"

class UImage;
class UCommonTextBlock;
class UMaterialInterface;
class UMaterialInstanceDynamic;

struct FUIStyle;
struct FUIStyleButton;

/** Tipo de borda do botão (fixo por instância; a COR acende por estado). */
UENUM(BlueprintType)
enum class EUIButtonBorderStyle : uint8
{
	None     UMETA(DisplayName = "Sem borda"),
	Simple   UMETA(DisplayName = "Linha simples (Slate)"),
	Frame    UMETA(DisplayName = "Frame (material)")
};

/**
 * Snapshot visual de UM estado do botão (Default / Hover / Pressed / Disabled).
 * As cores de gradient/glow vão pro material (UI_M_Button via MID); a borda usa
 * o RoundedBox nativo do Slate (OutlineSettings) e o scale/opacity são
 * RenderTransform do widget. Transições entre estados interpolam esta struct
 * inteira (ver UUIButton_Base::NativeTick).
 */
USTRUCT(BlueprintType)
struct ZMMO_API FUIButtonStateVisual
{
	GENERATED_BODY()

	/** Topo do gradient vertical do fundo (param TopColour do material). */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Button|State")
	FLinearColor TopColour = FLinearColor(0.910f, 0.753f, 0.376f, 0.18f);

	/** Base do gradient vertical (param BottomColour). */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Button|State")
	FLinearColor BottomColour = FLinearColor(0.659f, 0.471f, 0.188f, 0.10f);

	/** Cor do halo externo (camada GlowFx, material UI_M_Button_Glow). */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Button|State")
	FLinearColor GlowColour = FLinearColor(0.910f, 0.753f, 0.376f, 1.f);

	/** Intensidade do halo externo (GlowFx). 0 = sem glow; hover acende (sai pra fora). */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Button|State",
		meta = (ClampMin = "0", ClampMax = "1"))
	float GlowIntensity = 0.f;

	/** Cor da borda/cantos (Slate outline no modo Simple, ou material no modo Corners). */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Button|State")
	FLinearColor BorderColour = FLinearColor(0.831f, 0.659f, 0.314f, 0.28f);

	/** Espessura da borda em pixels (Slate OutlineSettings.Width). */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Button|State",
		meta = (ClampMin = "0", ClampMax = "6"))
	float BorderWidth = 1.f;

	/** Cor do texto (ButtonText->SetColorAndOpacity). */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Button|State")
	FLinearColor TextColour = FLinearColor(1.f, 0.847f, 0.533f, 1.f);

	/** Scale do botão (CSS transform: scale). 1 = normal, 1.02 = hover, 0.98 = pressed. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Button|State",
		meta = (ClampMin = "0.5", ClampMax = "1.5"))
	float Scale = 1.f;

	/** Opacidade geral do botão (CSS opacity — disabled usa 0.6). */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Button|State",
		meta = (ClampMin = "0", ClampMax = "1"))
	float RenderOpacity = 1.f;
};

/**
 * Botão base do ZMMO (CommonUI). Mesmo padrão do UUIProgressBar_Base: um UImage
 * (`Bg`) com material custom (UI_M_Button) controlado por MID + RoundedBox nativo
 * do Slate pra borda/canto. Os estados do UCommonButtonBase (Hover/Pressed/
 * Disabled/Selected) trocam o FUIButtonStateVisual alvo; a transição interpola
 * suave no Tick (estilo CSS `transition`).
 *
 * Modo atual = manual (os 4 FUIButtonStateVisual editáveis no Details, já com
 * defaults do `btn-primary`). A leitura via DT_UI_Styles (bUseTheme + Variant)
 * entra na fase final, reusando esta struct.
 *
 * WBP filho (UI_Button_Master_New): `Bg` (UImage, obrigatório, material no brush)
 * + `ButtonText` (UCommonTextBlock, opcional).
 */
UCLASS(Abstract, Blueprintable)
class ZMMO_API UUIButton_Base : public UCommonButtonBase
{
	GENERATED_BODY()

public:
	UUIButton_Base(const FObjectInitializer& ObjectInitializer);

	/** Define o texto do botão (ButtonText). */
	UFUNCTION(BlueprintCallable, Category = "UI Button")
	void SetButtonText(const FText& InText);

	// === Visual por estado (modo manual; defaults = btn-primary) ===

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "UI Button|Visual")
	FUIButtonStateVisual DefaultVisual;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "UI Button|Visual")
	FUIButtonStateVisual HoveredVisual;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "UI Button|Visual")
	FUIButtonStateVisual PressedVisual;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "UI Button|Visual")
	FUIButtonStateVisual DisabledVisual;

	/** Estado "selecionado" (tabs/toggles). Default = igual ao Hovered. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "UI Button|Visual")
	FUIButtonStateVisual SelectedVisual;

	/** Raio do canto em pixels (Slate RoundedBox). Comum a todos os estados. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "UI Button|Visual",
		meta = (ClampMin = "0", ClampMax = "32"))
	float CornerRadius = 2.f;

	/** Tipo de borda (independente dos cantos): sem borda, linha Slate ou frame material. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "UI Button|Visual")
	EUIButtonBorderStyle BorderStyle = EUIButtonBorderStyle::Frame;

	/** Liga os cantos (corner brackets) — INDEPENDENTE da borda. Pode ter os dois,
	 *  só um, ou nenhum. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "UI Button|Visual")
	bool bShowCorners = true;

	/** Material do fundo (UI_M_Button). Fallback quando o brush do Bg não traz
	 *  material próprio. Defaults resolvidos no construtor. */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Button|Visual")
	TObjectPtr<UMaterialInterface> BgMaterial;

	/** Material do halo externo (UI_M_Button_Glow), aplicado no GlowFx. */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Button|Visual")
	TObjectPtr<UMaterialInterface> GlowMaterial;

	/** Material dos cantos (UI_M_CornerBrackets), aplicado no Corners. */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Button|Visual")
	TObjectPtr<UMaterialInterface> CornerMaterial;

	/** Material da moldura (UI_M_Button_Frame), aplicado no BorderFx. */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Button|Visual")
	TObjectPtr<UMaterialInterface> FrameMaterial;

	/** Padding do conteúdo (texto) dentro do botão. btn-primary = 28px horiz /
	 *  12px vert. Aplicado no slot do ButtonText em PreConstruct (o texto fica
	 *  centralizado). */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "UI Button|Visual")
	FMargin ContentPadding = FMargin(28.f, 12.f, 28.f, 12.f);

	/** Quanto o halo externo (GlowFx) vaza pra fora do botão, em pixels. Aplicado
	 *  como padding negativo no slot do GlowFx em PreConstruct. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "UI Button|Visual",
		meta = (ClampMin = "0", ClampMax = "64"))
	float GlowExtent = 16.f;

	/** Desloca os cantos. Negativo = pra FORA (abraçando o botão, estilo CSS);
	 *  positivo = pra dentro. Aplicado no slot do Corners em PreConstruct. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "UI Button|Visual",
		meta = (ClampMin = "-32", ClampMax = "32"))
	float CornerInset = -5.f;

	/** Comprimento de cada braço do "L" (fração da altura). Maior = L mais longo. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "UI Button|Visual",
		meta = (ClampMin = "0.05", ClampMax = "1.0"))
	float CornerLength = 0.35f;

	/** Espessura/peso do traço dos cantos (fração da altura). Menor = mais fino. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "UI Button|Visual",
		meta = (ClampMin = "0.005", ClampMax = "0.3"))
	float CornerThickness = 0.04f;

	/** Deslocamento da sombra (GlowFx) pra baixo, em px — dá o look de drop shadow. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "UI Button|Visual",
		meta = (ClampMin = "0", ClampMax = "32"))
	float GlowOffsetY = 4.f;

	/** Duração da transição entre estados (s). 0 = troca instantânea. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "UI Button|Animation",
		meta = (ClampMin = "0", ClampMax = "1"))
	float TransitionSeconds = 0.12f;

protected:
	virtual void NativePreConstruct() override;
	virtual void NativeConstruct() override;
	virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override;
	virtual int32 NativePaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry,
		const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements,
		int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const override;

	// === Hooks de estado do UCommonButtonBase ===
	virtual void NativeOnHovered() override;
	virtual void NativeOnUnhovered() override;
	virtual void NativeOnPressed() override;
	virtual void NativeOnReleased() override;
	virtual void NativeOnEnabled() override;
	virtual void NativeOnDisabled() override;
	virtual void NativeOnSelected(bool bBroadcast) override;
	virtual void NativeOnDeselected(bool bBroadcast) override;

	// === BindWidget (espelham a árvore do UI_Button_Master_New) ===
	// Todos BindWidgetOptional pra não quebrar WBPs que herdam UUIButton_Base sem
	// essas peças — sem elas o visual degrada (não pinta), mas não quebra.

	/** Halo externo (atrás do Bg, com padding negativo pra vazar pra fora). */
	UPROPERTY(BlueprintReadOnly, Category = "UI Button", meta = (BindWidgetOptional))
	TObjectPtr<UImage> GlowFx;

	/** Fundo (gradient). */
	UPROPERTY(BlueprintReadOnly, Category = "UI Button", meta = (BindWidgetOptional))
	TObjectPtr<UImage> Bg;

	/** Moldura/frame (material), visível só no BorderStyle = Frame. */
	UPROPERTY(BlueprintReadOnly, Category = "UI Button", meta = (BindWidgetOptional))
	TObjectPtr<UImage> BorderFx;

	/** Cantos (corner brackets), visível só no BorderStyle = Corners. */
	UPROPERTY(BlueprintReadOnly, Category = "UI Button", meta = (BindWidgetOptional))
	TObjectPtr<UImage> Corners;

	UPROPERTY(BlueprintReadOnly, Category = "UI Button", meta = (BindWidgetOptional))
	TObjectPtr<UCommonTextBlock> ButtonText;

	// === Acesso ao estilo ativo (DT_UI_Styles) — usado na fase final ===

	/** Carrega DT_UI_Styles e devolve o FUIStyle da row pedida (default "Default"). */
	const FUIStyle* GetActiveUIStyle(FName ThemeId = TEXT("Default")) const;

	/** Atalho: devolve só o bloco Button do FUIStyle ativo. */
	const FUIStyleButton* GetActiveButtonStyle(FName ThemeId = TEXT("Default")) const;

private:
	/** Cria os MIDs a partir do material no brush de cada imagem (idempotente). */
	void EnsureMID();

	/** Passa a proporção W/H de CADA camada (cantos/frame/glow) pro respectivo
	 *  material que compensa aspect. Chamado no NativePaint — roda no Designer E
	 *  em runtime (o Tick NÃO roda no Designer, por isso o traço esticava lá). */
	void ApplyAspectToLayers() const;

	/** Recalcula o estado-alvo (disabled>pressed>hovered>selected>default) e transiciona. */
	void RefreshState();

	/** Inicia transição pro visual alvo (ou aplica direto se TransitionSeconds≈0). */
	void GoToState(const FUIButtonStateVisual& Target);

	/** Empurra um visual pros widgets (MID + borda Slate + scale/opacity + texto). */
	void ApplyVisual(const FUIButtonStateVisual& V);

	static FUIButtonStateVisual LerpVisual(const FUIButtonStateVisual& A, const FUIButtonStateVisual& B, float T);

	UPROPERTY(Transient)
	TObjectPtr<UMaterialInstanceDynamic> BgMID;

	UPROPERTY(Transient)
	TObjectPtr<UMaterialInstanceDynamic> GlowMID;

	UPROPERTY(Transient)
	TObjectPtr<UMaterialInstanceDynamic> CornerMID;

	UPROPERTY(Transient)
	TObjectPtr<UMaterialInstanceDynamic> BorderMID;

	bool bHoveredState = false;
	bool bPressedState = false;
	bool bDisabledState = false;
	bool bSelectedState = false;

	FUIButtonStateVisual FromVisual;
	FUIButtonStateVisual ToVisual;
	FUIButtonStateVisual CurrentVisual;
	float TransitionElapsed = 0.f;
	bool bTransitioning = false;
};
