#pragma once

#include "CoreMinimal.h"
#include "CommonUserWidget.h"
#include "UI/UIStyleTokens.h"
#include "UI/UIStyleTypes.h"
#include "UIInput_Base.generated.h"

class UEditableTextBox;
class USizeBox;
class UImage;

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FUIInputTextChanged, const FText&, Text);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FUIInputTextCommitted, const FText&, Text, ETextCommit::Type, CommitMethod);

/**
 * Campo de texto SÓ-INPUT (sem label). Padrão visual inspirado no UI_Search do
 * Hyper: SizeBox raiz → Overlay → Background (UImage) + Stroke (UImage) +
 * Input (UEditableTextBox). Os UImages recebem a aparência (cor ou textura
 * 9-slice via DT_UI_Styles); o EditableTextBox fica transparente e só
 * recebe fonte/cor de texto — assim a cor magenta default (brush vazio) é
 * eliminada.
 *
 * Variantes visuais são data-driven via FUIStyle.Input (Backgrounds/Strokes/
 * Typography) — chave FName (Box/Outline/Underline/Search/custom). Para
 * compor com rótulo + layout (Stacked/Inline), use UUILabel_Base.
 */
UCLASS(Abstract, Blueprintable)
class ZMMO_API UUIInput_Base : public UCommonUserWidget
{
	GENERATED_BODY()

public:
	/** Re-resolve os tokens do tema ativo e reaplica. */
	UFUNCTION(BlueprintCallable, Category = "UI Style")
	void RefreshUIStyle();

	UFUNCTION(BlueprintPure, Category = "Input")
	FText GetText() const;

	UFUNCTION(BlueprintCallable, Category = "Input")
	void SetText(FText InText);

	UFUNCTION(BlueprintCallable, Category = "Input")
	void SetHintTextRuntime(FText InHint);

	UFUNCTION(BlueprintCallable, Category = "Input")
	void SetIsPasswordRuntime(bool bInIsPassword);

	UPROPERTY(BlueprintAssignable, Category = "Input")
	FUIInputTextChanged OnTextChanged;

	UPROPERTY(BlueprintAssignable, Category = "Input")
	FUIInputTextCommitted OnTextCommitted;

	/**
	 * Tamanho da fonte do campo. 0 = usa o padrão do DT_UI_Styles
	 * (FUIStyleInputTypography.Size). > 0 = sobrescreve aqui no Designer.
	 */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input", meta = (ClampMin = "0"))
	float FontSize = 0.f;

	/** Placeholder exibido quando vazio. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input")
	FText HintText;

	/**
	 * Variante visual do input (dropdown vem de FUIStyle.Input.Variants no
	 * DT_UI_Styles + as 4 clássicas como fallback). Data-driven, sem enum.
	 */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input",
		meta = (GetOptions = "GetVariantOptions"))
	FName Variant = TEXT("Box");

	/** Opções do dropdown de Variant (data-driven do DT_UI_Styles). */
	UFUNCTION()
	TArray<FString> GetVariantOptions() const;

	/** Helper compartilhado p/ UUILabel_Base (mesma lista de variantes). */
	static TArray<FString> CollectVariantOptions();

	/**
	 * Largura preferida do campo (px). 0 = usa o padrão do DT
	 * (FUIStyle.Input.MinWidth). > 0 = sobrescreve aqui no Designer.
	 */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input|Size", meta = (ClampMin = "0"))
	float PreferredWidth = 0.f;

	/**
	 * Altura preferida do campo (px). 0 = usa o padrão do DT
	 * (FUIStyle.Input.MinHeight). > 0 = sobrescreve aqui no Designer.
	 */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input|Size", meta = (ClampMin = "0"))
	float PreferredHeight = 0.f;

	/** Campo de senha (oculta os caracteres). */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input")
	bool bIsPassword = false;

protected:
	virtual void NativePreConstruct() override;
	virtual void NativeConstruct() override;
	virtual void NativeDestruct() override;
	virtual void SynchronizeProperties() override;

	/** Hook opcional: o WBP pode refinar além do que o C++ aplica. */
	UFUNCTION(BlueprintImplementableEvent, Category = "UI Style",
		meta = (DisplayName = "Apply Input Style"))
	void BP_ApplyInputStyle(const FUIStyleInput& InputStyle);

	// SizeBox raiz (controla PreferredWidth/MinHeight). Opcional: se o WBP
	// não tiver, fallback fica ileso (sem set de tamanho).
	UPROPERTY(meta = (BindWidgetOptional))
	TObjectPtr<USizeBox> Size_Root;

	// Background pintável (cor + textura 9-slice opcional).
	UPROPERTY(meta = (BindWidgetOptional))
	TObjectPtr<UImage> Background;

	// Stroke / borda (cor + textura 9-slice opcional via FUIStyleInputStroke).
	UPROPERTY(meta = (BindWidgetOptional))
	TObjectPtr<UImage> Stroke;

	// Campo de texto cru. Fica transparente — Background/Stroke pintam atrás.
	UPROPERTY(meta = (BindWidgetOptional))
	TObjectPtr<UEditableTextBox> Input;

private:
	FUIStyleInputVariant ResolveVariant(const FUIStyleInput& I) const;
	void ApplyStyle(const FUIStyleInputVariant& V, float InPadding,
		const FSlateFontInfo& ThemeFont, float FontSizePx);

	UFUNCTION()
	void HandleThemeChanged(FName NewThemeId);

	UFUNCTION()
	void HandleTextChanged(const FText& Text);

	UFUNCTION()
	void HandleTextCommitted(const FText& Text, ETextCommit::Type CommitMethod);

	bool bThemeBound = false;
	bool bInputBound = false;

	/**
	 * Último valor que o C++ aplicou no Size_Root->WidthOverride a partir do
	 * tema. Se o valor atual do SizeBox for diferente, presume-se que o user
	 * editou manualmente (no Designer) — C++ deixa intacto. -1 = não aplicado
	 * (próxima chamada aplica do tema).
	 */
	UPROPERTY(Transient)
	float LastThemeWidthApplied = -1.f;

	UPROPERTY(Transient)
	float LastThemeHeightApplied = -1.f;
};
