#include "UIProgressBar_Base.h"

#include "Components/Image.h"
#include "Components/OverlaySlot.h"
#include "Engine/DataTable.h"
#include "Engine/GameInstance.h"
#include "Materials/MaterialInstanceDynamic.h"
#include "Materials/MaterialInterface.h"
#include "Styling/SlateBrush.h"
#include "Styling/SlateTypes.h"
#include "UI/UIStyleRow.h"
#include "UI/UIStyleTokens.h"
#include "ZMMOThemeSubsystem.h"

namespace
{
	constexpr float MinAnimSeconds = 0.001f;

	// Fill material params
	static const FName P_PrimaryLevel("PrimaryLevel");
	static const FName P_SecondaryLevel("SecondaryLevel");
	static const FName P_PrimaryColour("PrimaryColour");
	static const FName P_PrimaryColourBottom("PrimaryColourBottom");
	static const FName P_SecondaryColour("SecondaryColour");
	static const FName P_SecondaryColourBottom("SecondaryColourBottom");
	static const FName P_EmptyColour("EmptyColour");
	static const FName P_EnableGradient("EnableGradient");
	static const FName P_GradientSplit("GradientSplit");

	// BG material params
	static const FName P_BackgroundColour("BackgroundColour");

	// TrackGrid material params
	static const FName P_GridColour("GridColour");
	static const FName P_GridDivisions("GridDivisions");
	static const FName P_GridLineThickness("GridLineThickness");

	// Shimmer material params
	static const FName P_ShimmerColour("ShimmerColour");
	static const FName P_ShimmerWidth("ShimmerWidth");
	static const FName P_ShimmerSpeed("ShimmerSpeed");
	static const FName P_ShimmerSoftness("ShimmerSoftness");

	// Edge material params
	static const FName P_EdgeColour("EdgeColour");
	static const FName P_EdgeWidth("EdgeWidth");
	static const FName P_EdgeGlowWidth("EdgeGlowWidth");
	static const FName P_EdgeGlowIntensity("EdgeGlowIntensity");

	FORCEINLINE float EaseOutCubic(float Alpha)
	{
		return 1.f - FMath::Pow(1.f - Alpha, 3.f);
	}

	/** Resolve a FUIStyle ativa — runtime via ThemeSubsystem, design-time via DT direto. */
	FUIStyle ResolveProgressBarStyle(const UUserWidget* Widget)
	{
		if (Widget)
		{
			if (const UGameInstance* GI = Widget->GetGameInstance())
			{
				if (const UZMMOThemeSubsystem* Theme = GI->GetSubsystem<UZMMOThemeSubsystem>())
				{
					return Theme->GetActiveUIStyle();
				}
			}
		}
		// Design-time fallback: lê DT_UI_Styles row "Default" direto do disk.
		if (const UDataTable* DT = LoadObject<UDataTable>(nullptr,
			TEXT("/Game/ZMMO/Data/UI/DT_UI_Styles.DT_UI_Styles")))
		{
			if (const FUIStyleRow* Row = DT->FindRow<FUIStyleRow>(
				FName(TEXT("Default")), TEXT("UIProgressBarDesign"), false))
			{
				return Row->Style;
			}
		}
		return FUIStyle();
	}

	TArray<FString> CollectVariantOptions()
	{
		TArray<FString> Options;
		Options.Add(FString()); // entrada vazia = sem theme
		const UDataTable* DT = LoadObject<UDataTable>(nullptr,
			TEXT("/Game/ZMMO/Data/UI/DT_UI_Styles.DT_UI_Styles"));
		if (!DT) return Options;
		const FUIStyleRow* Row = DT->FindRow<FUIStyleRow>(
			FName(TEXT("Default")), TEXT("UIProgressBarGetOptions"), false);
		if (!Row) return Options;
		for (const TPair<FName, FUIStyleProgressBarVariant>& Pair : Row->Style.ProgressBar.Variants)
		{
			Options.Add(Pair.Key.ToString());
		}
		Options.Sort();
		return Options;
	}
}

void UUIProgressBar_Base::NativePreConstruct()
{
	Super::NativePreConstruct();

	CurrentPrimaryLevel = InitialPrimaryLevel;
	TargetPrimaryLevel = InitialPrimaryLevel;
	PrimaryStart = InitialPrimaryLevel;
	PrimaryElapsed = 0.f;
	bAnimatingPrimary = false;

	CurrentSecondaryLevel = InitialSecondaryLevel;
	TargetSecondaryLevel = InitialSecondaryLevel;
	SecondaryStart = InitialSecondaryLevel;
	SecondaryElapsed = 0.f;
	bAnimatingSecondary = false;

	if (bUseTheme)
	{
		RefreshUIStyle();
	}
	else
	{
		ApplyBrushStyle();
		EnsureMIDs();
		ApplyMaterialOverrides();
	}
	ApplyPrimaryToMID(CurrentPrimaryLevel);
	ApplySecondaryToMID(CurrentSecondaryLevel);
}

void UUIProgressBar_Base::NativeConstruct()
{
	Super::NativeConstruct();

	if (!bThemeBound)
	{
		if (const UGameInstance* GI = GetGameInstance())
		{
			if (UZMMOThemeSubsystem* Theme = GI->GetSubsystem<UZMMOThemeSubsystem>())
			{
				Theme->OnThemeChanged.AddDynamic(this, &UUIProgressBar_Base::HandleThemeChanged);
				bThemeBound = true;
			}
		}
	}

	if (bUseTheme)
	{
		RefreshUIStyle();
	}
	else
	{
		ApplyBrushStyle();
		EnsureMIDs();
		ApplyMaterialOverrides();
	}
	ApplyPrimaryToMID(CurrentPrimaryLevel);
	ApplySecondaryToMID(CurrentSecondaryLevel);
}

void UUIProgressBar_Base::NativeDestruct()
{
	if (bThemeBound)
	{
		if (const UGameInstance* GI = GetGameInstance())
		{
			if (UZMMOThemeSubsystem* Theme = GI->GetSubsystem<UZMMOThemeSubsystem>())
			{
				Theme->OnThemeChanged.RemoveDynamic(this, &UUIProgressBar_Base::HandleThemeChanged);
			}
		}
		bThemeBound = false;
	}
	Super::NativeDestruct();
}

void UUIProgressBar_Base::HandleThemeChanged(FName /*NewThemeId*/)
{
	if (bUseTheme)
	{
		RefreshUIStyle();
	}
}

void UUIProgressBar_Base::NativeTick(const FGeometry& MyGeometry, float InDeltaTime)
{
	Super::NativeTick(MyGeometry, InDeltaTime);

	if (!bAnimatingPrimary && !bAnimatingSecondary)
	{
		return;
	}

	if (bAnimatingPrimary)
	{
		PrimaryElapsed += InDeltaTime;
		const float Duration = FMath::Max(PrimaryAnimationSeconds, MinAnimSeconds);
		const float Alpha = FMath::Clamp(PrimaryElapsed / Duration, 0.f, 1.f);
		CurrentPrimaryLevel = FMath::Lerp(PrimaryStart, TargetPrimaryLevel, EaseOutCubic(Alpha));
		ApplyPrimaryToMID(CurrentPrimaryLevel);
		if (Alpha >= 1.f)
		{
			CurrentPrimaryLevel = TargetPrimaryLevel;
			ApplyPrimaryToMID(CurrentPrimaryLevel);
			bAnimatingPrimary = false;
		}
	}

	if (bAnimatingSecondary)
	{
		SecondaryElapsed += InDeltaTime;
		const float Duration = FMath::Max(SecondaryAnimationSeconds, MinAnimSeconds);
		const float Alpha = FMath::Clamp(SecondaryElapsed / Duration, 0.f, 1.f);
		CurrentSecondaryLevel = FMath::Lerp(SecondaryStart, TargetSecondaryLevel, EaseOutCubic(Alpha));
		ApplySecondaryToMID(CurrentSecondaryLevel);
		if (Alpha >= 1.f)
		{
			CurrentSecondaryLevel = TargetSecondaryLevel;
			ApplySecondaryToMID(CurrentSecondaryLevel);
			bAnimatingSecondary = false;
		}
	}
}

void UUIProgressBar_Base::SetTargetPrimaryLevel(float Primary01)
{
	const float Clamped = FMath::Clamp(Primary01, 0.f, 1.f);
	if (PrimaryAnimationSeconds <= MinAnimSeconds)
	{
		SetPrimaryLevelImmediate(Clamped);
		return;
	}
	if (FMath::IsNearlyEqual(Clamped, CurrentPrimaryLevel, KINDA_SMALL_NUMBER) &&
	    FMath::IsNearlyEqual(Clamped, TargetPrimaryLevel, KINDA_SMALL_NUMBER))
	{
		return;
	}
	TargetPrimaryLevel = Clamped;
	PrimaryStart = CurrentPrimaryLevel;
	PrimaryElapsed = 0.f;
	bAnimatingPrimary = true;
}

void UUIProgressBar_Base::SetPrimaryLevelImmediate(float Primary01)
{
	const float Clamped = FMath::Clamp(Primary01, 0.f, 1.f);
	CurrentPrimaryLevel = Clamped;
	TargetPrimaryLevel = Clamped;
	PrimaryStart = Clamped;
	PrimaryElapsed = 0.f;
	bAnimatingPrimary = false;
	ApplyPrimaryToMID(CurrentPrimaryLevel);
}

void UUIProgressBar_Base::SetTargetSecondaryLevel(float Sec01)
{
	const float Clamped = FMath::Clamp(Sec01, 0.f, 1.f);
	if (SecondaryAnimationSeconds <= MinAnimSeconds)
	{
		SetSecondaryLevelImmediate(Clamped);
		return;
	}
	if (FMath::IsNearlyEqual(Clamped, CurrentSecondaryLevel, KINDA_SMALL_NUMBER) &&
	    FMath::IsNearlyEqual(Clamped, TargetSecondaryLevel, KINDA_SMALL_NUMBER))
	{
		return;
	}
	TargetSecondaryLevel = Clamped;
	SecondaryStart = CurrentSecondaryLevel;
	SecondaryElapsed = 0.f;
	bAnimatingSecondary = true;
}

void UUIProgressBar_Base::SetSecondaryLevelImmediate(float Sec01)
{
	const float Clamped = FMath::Clamp(Sec01, 0.f, 1.f);
	CurrentSecondaryLevel = Clamped;
	TargetSecondaryLevel = Clamped;
	SecondaryStart = Clamped;
	SecondaryElapsed = 0.f;
	bAnimatingSecondary = false;
	ApplySecondaryToMID(CurrentSecondaryLevel);
}

void UUIProgressBar_Base::SetDrawStyle(EUIProgressBarStyle InStyle)
{
	DrawStyle = InStyle;
	ApplyBrushStyle();
}

void UUIProgressBar_Base::SetCornerRadius(float RadiusPixels)
{
	CornerRadius = FMath::Clamp(RadiusPixels, 0.f, 100.f);
	ApplyBrushStyle();
}

void UUIProgressBar_Base::SetBorderVisible(bool bVisible)
{
	bShowBorder = bVisible;
	ApplyBrushStyle();
}

void UUIProgressBar_Base::SetBorderColour(FLinearColor Color)
{
	BorderColour = Color;
	bShowBorder = true;
	ApplyBrushStyle();
}

void UUIProgressBar_Base::SetBorderWidth(float WidthPixels)
{
	BorderWidth = FMath::Clamp(WidthPixels, 0.f, 10.f);
	ApplyBrushStyle();
}

void UUIProgressBar_Base::SetPrimaryColour(FLinearColor Color)
{
	PrimaryColour = Color;
	bOverridePrimaryColour = true;
	if (FillMID) FillMID->SetVectorParameterValue(P_PrimaryColour, Color);
}

void UUIProgressBar_Base::SetPrimaryColourBottom(FLinearColor Color)
{
	PrimaryColourBottom = Color;
	bOverridePrimaryColourBottom = true;
	if (FillMID) FillMID->SetVectorParameterValue(P_PrimaryColourBottom, Color);
}

void UUIProgressBar_Base::SetSecondaryColour(FLinearColor Color)
{
	SecondaryColour = Color;
	bOverrideSecondaryColour = true;
	if (FillMID) FillMID->SetVectorParameterValue(P_SecondaryColour, Color);
}

void UUIProgressBar_Base::SetSecondaryColourBottom(FLinearColor Color)
{
	SecondaryColourBottom = Color;
	bOverrideSecondaryColourBottom = true;
	if (FillMID) FillMID->SetVectorParameterValue(P_SecondaryColourBottom, Color);
}

void UUIProgressBar_Base::SetEmptyColour(FLinearColor Color)
{
	EmptyColour = Color;
	bOverrideEmptyColour = true;
	if (FillMID) FillMID->SetVectorParameterValue(P_EmptyColour, Color);
}

void UUIProgressBar_Base::SetBackgroundColour(FLinearColor Color)
{
	BackgroundColour = Color;
	bOverrideBackgroundColour = true;
	if (BackgroundMID) BackgroundMID->SetVectorParameterValue(P_BackgroundColour, Color);
}

void UUIProgressBar_Base::SetTrackGridVisible(bool bVisible)
{
	bShowTrackGrid = bVisible;
	if (TrackGridImage)
	{
		TrackGridImage->SetVisibility(bVisible ? ESlateVisibility::HitTestInvisible : ESlateVisibility::Collapsed);
	}
}

void UUIProgressBar_Base::SetGridColour(FLinearColor Color)
{
	GridColour = Color;
	bOverrideGridColour = true;
	if (TrackGridMID) TrackGridMID->SetVectorParameterValue(P_GridColour, Color);
}

void UUIProgressBar_Base::SetGridDivisions(float Divisions)
{
	GridDivisions = FMath::Clamp(Divisions, 2.f, 50.f);
	bOverrideGridDivisions = true;
	if (TrackGridMID) TrackGridMID->SetScalarParameterValue(P_GridDivisions, GridDivisions);
}

void UUIProgressBar_Base::SetGridLineThickness(float Thickness)
{
	GridLineThickness = FMath::Clamp(Thickness, 0.001f, 0.2f);
	bOverrideGridLineThickness = true;
	if (TrackGridMID) TrackGridMID->SetScalarParameterValue(P_GridLineThickness, GridLineThickness);
}

void UUIProgressBar_Base::SetEdgeVisible(bool bVisible)
{
	bShowEdge = bVisible;
	UpdateEdgeVisibility();
}

void UUIProgressBar_Base::SetEdgeColour(FLinearColor Color)
{
	EdgeColour = Color;
	bOverrideEdgeColour = true;
	if (EdgeMID) EdgeMID->SetVectorParameterValue(P_EdgeColour, Color);
}

void UUIProgressBar_Base::SetEdgeWidth(float Width01)
{
	EdgeWidth = FMath::Clamp(Width01, 0.001f, 0.1f);
	bOverrideEdgeWidth = true;
	if (EdgeMID) EdgeMID->SetScalarParameterValue(P_EdgeWidth, EdgeWidth);
}

void UUIProgressBar_Base::SetEdgeGlowWidth(float GlowWidth01)
{
	EdgeGlowWidth = FMath::Clamp(GlowWidth01, 0.f, 0.2f);
	bOverrideEdgeGlowWidth = true;
	if (EdgeMID) EdgeMID->SetScalarParameterValue(P_EdgeGlowWidth, EdgeGlowWidth);
}

void UUIProgressBar_Base::SetEdgeGlowIntensity(float Intensity01)
{
	EdgeGlowIntensity = FMath::Clamp(Intensity01, 0.f, 1.f);
	bOverrideEdgeGlowIntensity = true;
	if (EdgeMID) EdgeMID->SetScalarParameterValue(P_EdgeGlowIntensity, EdgeGlowIntensity);
}

void UUIProgressBar_Base::SetShimmerVisible(bool bVisible)
{
	bShowShimmer = bVisible;
	if (ShimmerImage)
	{
		ShimmerImage->SetVisibility(bVisible ? ESlateVisibility::HitTestInvisible : ESlateVisibility::Collapsed);
	}
}

void UUIProgressBar_Base::SetShimmerColour(FLinearColor Color)
{
	ShimmerColour = Color;
	bOverrideShimmerColour = true;
	if (ShimmerMID) ShimmerMID->SetVectorParameterValue(P_ShimmerColour, Color);
}

void UUIProgressBar_Base::SetShimmerWidth(float Width01)
{
	ShimmerWidth = FMath::Clamp(Width01, 0.05f, 1.f);
	bOverrideShimmerWidth = true;
	if (ShimmerMID) ShimmerMID->SetScalarParameterValue(P_ShimmerWidth, ShimmerWidth);
}

void UUIProgressBar_Base::SetShimmerSpeed(float Speed)
{
	ShimmerSpeed = FMath::Clamp(Speed, 0.01f, 5.f);
	bOverrideShimmerSpeed = true;
	if (ShimmerMID) ShimmerMID->SetScalarParameterValue(P_ShimmerSpeed, ShimmerSpeed);
}

void UUIProgressBar_Base::SetShimmerSoftness(float Softness)
{
	ShimmerSoftness = FMath::Clamp(Softness, 0.5f, 8.f);
	bOverrideShimmerSoftness = true;
	if (ShimmerMID) ShimmerMID->SetScalarParameterValue(P_ShimmerSoftness, ShimmerSoftness);
}

void UUIProgressBar_Base::SetGradientEnabled(bool bEnabled)
{
	bEnableGradient = bEnabled;
	bOverrideEnableGradient = true;
	if (FillMID) FillMID->SetScalarParameterValue(P_EnableGradient, bEnabled ? 1.f : 0.f);
}

void UUIProgressBar_Base::SetGradientSplit(float Split01)
{
	GradientSplit = FMath::Clamp(Split01, 0.f, 1.f);
	bOverrideGradientSplit = true;
	if (FillMID) FillMID->SetScalarParameterValue(P_GradientSplit, GradientSplit);
}

void UUIProgressBar_Base::ShowHealPreview(float TargetPct, FLinearColor PreviewColor)
{
	SetSecondaryColour(PreviewColor);
	SetTargetSecondaryLevel(TargetPct);
}

void UUIProgressBar_Base::ShowDamageLag(float OldPct, float NewPct, FLinearColor LagColor)
{
	SetSecondaryColour(LagColor);
	SetSecondaryLevelImmediate(OldPct);
	SetPrimaryLevelImmediate(NewPct);
	SetTargetSecondaryLevel(NewPct);
}

void UUIProgressBar_Base::ShowBuffer(float BufferPct, FLinearColor BufferColor)
{
	SetSecondaryColour(BufferColor);
	SetTargetSecondaryLevel(FMath::Clamp(CurrentPrimaryLevel + BufferPct, 0.f, 1.f));
}

void UUIProgressBar_Base::ClearSecondary()
{
	SetTargetSecondaryLevel(0.f);
}

void UUIProgressBar_Base::EnsureMIDs()
{
	if (FillImage && !FillMID)
	{
		if (UMaterialInterface* Mat = Cast<UMaterialInterface>(FillImage->GetBrush().GetResourceObject()))
		{
			FillMID = UMaterialInstanceDynamic::Create(Mat, this);
			FillImage->SetBrushFromMaterial(FillMID);
			// SetBrushFromMaterial reseta DrawAs e OutlineSettings — re-aplica.
			ApplyBrushStyle();
		}
	}
	if (BackgroundImage && !BackgroundMID)
	{
		if (UMaterialInterface* Mat = Cast<UMaterialInterface>(BackgroundImage->GetBrush().GetResourceObject()))
		{
			BackgroundMID = UMaterialInstanceDynamic::Create(Mat, this);
			BackgroundImage->SetBrushFromMaterial(BackgroundMID);
			ApplyBrushStyle();
		}
	}
	if (TrackGridImage && !TrackGridMID)
	{
		if (UMaterialInterface* Mat = Cast<UMaterialInterface>(TrackGridImage->GetBrush().GetResourceObject()))
		{
			TrackGridMID = UMaterialInstanceDynamic::Create(Mat, this);
			TrackGridImage->SetBrushFromMaterial(TrackGridMID);
			ApplyBrushStyle();
		}
	}
	if (ShimmerImage && !ShimmerMID)
	{
		if (UMaterialInterface* Mat = Cast<UMaterialInterface>(ShimmerImage->GetBrush().GetResourceObject()))
		{
			ShimmerMID = UMaterialInstanceDynamic::Create(Mat, this);
			ShimmerImage->SetBrushFromMaterial(ShimmerMID);
			ApplyBrushStyle();
		}
	}
	if (EdgeImage && !EdgeMID)
	{
		if (UMaterialInterface* Mat = Cast<UMaterialInterface>(EdgeImage->GetBrush().GetResourceObject()))
		{
			EdgeMID = UMaterialInstanceDynamic::Create(Mat, this);
			EdgeImage->SetBrushFromMaterial(EdgeMID);
			ApplyBrushStyle();
		}
	}
}

void UUIProgressBar_Base::ApplyMaterialOverrides()
{
	if (FillMID)
	{
		if (bOverridePrimaryColour)         FillMID->SetVectorParameterValue(P_PrimaryColour,         PrimaryColour);
		if (bOverridePrimaryColourBottom)   FillMID->SetVectorParameterValue(P_PrimaryColourBottom,   PrimaryColourBottom);
		if (bOverrideSecondaryColour)       FillMID->SetVectorParameterValue(P_SecondaryColour,       SecondaryColour);
		if (bOverrideSecondaryColourBottom) FillMID->SetVectorParameterValue(P_SecondaryColourBottom, SecondaryColourBottom);
		if (bOverrideEmptyColour)           FillMID->SetVectorParameterValue(P_EmptyColour,           EmptyColour);
		if (bOverrideEnableGradient)        FillMID->SetScalarParameterValue(P_EnableGradient,        bEnableGradient ? 1.f : 0.f);
		if (bOverrideGradientSplit)         FillMID->SetScalarParameterValue(P_GradientSplit,         GradientSplit);
	}
	if (BackgroundMID)
	{
		if (bOverrideBackgroundColour) BackgroundMID->SetVectorParameterValue(P_BackgroundColour, BackgroundColour);
	}
	if (TrackGridMID)
	{
		if (bOverrideGridColour)        TrackGridMID->SetVectorParameterValue(P_GridColour,        GridColour);
		if (bOverrideGridDivisions)     TrackGridMID->SetScalarParameterValue(P_GridDivisions,     GridDivisions);
		if (bOverrideGridLineThickness) TrackGridMID->SetScalarParameterValue(P_GridLineThickness, GridLineThickness);
	}

	if (ShimmerMID)
	{
		if (bOverrideShimmerColour)   ShimmerMID->SetVectorParameterValue(P_ShimmerColour, ShimmerColour);
		if (bOverrideShimmerWidth)    ShimmerMID->SetScalarParameterValue(P_ShimmerWidth,    ShimmerWidth);
		if (bOverrideShimmerSpeed)    ShimmerMID->SetScalarParameterValue(P_ShimmerSpeed,    ShimmerSpeed);
		if (bOverrideShimmerSoftness) ShimmerMID->SetScalarParameterValue(P_ShimmerSoftness, ShimmerSoftness);
	}
	if (EdgeMID)
	{
		if (bOverrideEdgeColour)        EdgeMID->SetVectorParameterValue(P_EdgeColour,        EdgeColour);
		if (bOverrideEdgeWidth)         EdgeMID->SetScalarParameterValue(P_EdgeWidth,         EdgeWidth);
		if (bOverrideEdgeGlowWidth)     EdgeMID->SetScalarParameterValue(P_EdgeGlowWidth,     EdgeGlowWidth);
		if (bOverrideEdgeGlowIntensity) EdgeMID->SetScalarParameterValue(P_EdgeGlowIntensity, EdgeGlowIntensity);
	}

	// Visibilidade dos widgets opcionais
	if (TrackGridImage)
	{
		TrackGridImage->SetVisibility(bShowTrackGrid ? ESlateVisibility::HitTestInvisible : ESlateVisibility::Collapsed);
	}
	UpdateEdgeVisibility();
	if (ShimmerImage)
	{
		ShimmerImage->SetVisibility(bShowShimmer ? ESlateVisibility::HitTestInvisible : ESlateVisibility::Collapsed);
	}
}

void UUIProgressBar_Base::ApplyBrushStyle()
{
	const float InsetForShimmer = bShowBorder ? FMath::Max(BorderWidth, 0.f) : 0.f;

	auto Apply = [this](UImage* Img, bool bAllowBorder, float RadiusInset)
	{
		if (!Img)
		{
			return;
		}
		FSlateBrush B = Img->GetBrush();
		B.DrawAs = (DrawStyle == EUIProgressBarStyle::Rounded)
			? ESlateBrushDrawType::RoundedBox
			: ESlateBrushDrawType::Image;

		FSlateBrushOutlineSettings Outline = B.OutlineSettings;
		const float R = FMath::Max(CornerRadius - RadiusInset, 0.f);
		Outline.CornerRadii = FVector4(R, R, R, R);
		Outline.RoundingType = ESlateBrushRoundingType::FixedRadius;

		if (bAllowBorder && bShowBorder)
		{
			Outline.Color = FSlateColor(BorderColour);
			Outline.Width = FMath::Max(BorderWidth, 0.f);
		}
		else
		{
			Outline.Color = FSlateColor(FLinearColor::Transparent);
			Outline.Width = 0.f;
		}
		B.OutlineSettings = Outline;

		Img->SetBrush(B);
	};

	// Borda só no BG. Shimmer ganha inset = BorderWidth (padding no slot + corner reduzido)
	// pra não passar por cima do outline do BG. Demais widgets sem inset.
	Apply(BackgroundImage, /*bAllowBorder=*/true,  0.f);
	Apply(TrackGridImage,  /*bAllowBorder=*/false, 0.f);
	Apply(FillImage,       /*bAllowBorder=*/false, 0.f);
	Apply(EdgeImage,       /*bAllowBorder=*/false, 0.f);
	Apply(ShimmerImage,    /*bAllowBorder=*/false, InsetForShimmer);

	if (ShimmerImage)
	{
		if (UOverlaySlot* OS = Cast<UOverlaySlot>(ShimmerImage->Slot))
		{
			OS->SetPadding(FMargin(InsetForShimmer));
		}
	}
}

void UUIProgressBar_Base::ApplyPrimaryToMID(float Value)
{
	if (FillMID)
	{
		FillMID->SetScalarParameterValue(P_PrimaryLevel, Value);
	}
	// Edge acompanha o nível Primary (posição da linha = PrimaryLevel)
	if (EdgeMID)
	{
		EdgeMID->SetScalarParameterValue(P_PrimaryLevel, Value);
	}
	UpdateEdgeVisibility();
}

void UUIProgressBar_Base::UpdateEdgeVisibility()
{
	if (!EdgeImage)
	{
		return;
	}
	if (!bShowEdge)
	{
		EdgeImage->SetVisibility(ESlateVisibility::Collapsed);
		return;
	}
	// Auto-hide quando Primary está nos extremos (0 ou 1) — Edge encostaria na borda.
	const bool bAtExtreme = (CurrentPrimaryLevel <= 0.f) || (CurrentPrimaryLevel >= 1.f);
	EdgeImage->SetVisibility(bAtExtreme ? ESlateVisibility::Collapsed : ESlateVisibility::HitTestInvisible);
}

void UUIProgressBar_Base::ApplySecondaryToMID(float Value)
{
	if (FillMID)
	{
		FillMID->SetScalarParameterValue(P_SecondaryLevel, Value);
	}
}

// =====================================================================
// Theme integration (bUseTheme + Variant)
// =====================================================================

void UUIProgressBar_Base::RefreshUIStyle()
{
	if (!bUseTheme || Variant.IsNone())
	{
		// Fallback: comportamento manual.
		ApplyBrushStyle();
		EnsureMIDs();
		ApplyMaterialOverrides();
		return;
	}
	const FUIStyle ActiveStyle = ResolveProgressBarStyle(this);
	const FUIStyleProgressBarVariant* V = ActiveStyle.ProgressBar.Variants.Find(Variant);
	if (!V)
	{
		// Variante não existe no DT — fallback manual.
		ApplyBrushStyle();
		EnsureMIDs();
		ApplyMaterialOverrides();
		return;
	}
	ApplyThemeVariant(*V);
}

void UUIProgressBar_Base::ApplyThemeVariant(const FUIStyleProgressBarVariant& V)
{
	// Style — copia pros campos do widget e re-aplica brush.
	DrawStyle    = V.DrawStyle;
	CornerRadius = V.CornerRadius;
	bShowBorder  = V.bShowBorder;
	BorderColour = V.BorderColour;
	BorderWidth  = V.BorderWidth;

	// Toggles de efeito
	bShowTrackGrid = V.bShowTrackGrid;
	bShowEdge      = V.bShowEdge;
	bShowShimmer   = V.bShowShimmer;

	// Troca materiais nos brushes quando definidos. Reseta MIDs cacheados pra
	// que EnsureMIDs() pegue o material novo na próxima chamada.
	auto AssignMaterial = [](UImage* Img, UMaterialInterface* Mat)
	{
		if (!Img || !Mat) return;
		FSlateBrush B = Img->GetBrush();
		if (B.GetResourceObject() != Mat)
		{
			B.SetResourceObject(Mat);
			B.DrawAs = ESlateBrushDrawType::Image; // reset; ApplyBrushStyle re-aplica
			Img->SetBrush(B);
		}
	};
	if (V.FillMaterial)       { AssignMaterial(FillImage,       V.FillMaterial);       FillMID       = nullptr; }
	if (V.BackgroundMaterial) { AssignMaterial(BackgroundImage, V.BackgroundMaterial); BackgroundMID = nullptr; }
	if (V.TrackGridMaterial)  { AssignMaterial(TrackGridImage,  V.TrackGridMaterial);  TrackGridMID  = nullptr; }
	if (V.EdgeMaterial)       { AssignMaterial(EdgeImage,       V.EdgeMaterial);       EdgeMID       = nullptr; }
	if (V.ShimmerMaterial)    { AssignMaterial(ShimmerImage,    V.ShimmerMaterial);    ShimmerMID    = nullptr; }

	ApplyBrushStyle();
	EnsureMIDs();
	// Quando vem do tema, ignora os bOverride* individuais — variante já é a
	// fonte da verdade. Cores são definidas pela MI atribuída ao brush.

	// Aplica visibility dos toggles
	if (TrackGridImage) TrackGridImage->SetVisibility(bShowTrackGrid ? ESlateVisibility::HitTestInvisible : ESlateVisibility::Collapsed);
	if (ShimmerImage)   ShimmerImage->SetVisibility(bShowShimmer   ? ESlateVisibility::HitTestInvisible : ESlateVisibility::Collapsed);
	UpdateEdgeVisibility();
}

TArray<FString> UUIProgressBar_Base::GetProgressBarVariantOptions() const
{
	return CollectVariantOptions();
}
