#include "UIPanel_Base.h"

#include "ZMMOThemeSubsystem.h"
#include "Engine/GameInstance.h"
#include "Components/Border.h"
#include "Styling/SlateBrush.h"
#include "Engine/DataTable.h"
#include "UI/UIStyleRow.h"

namespace
{
	FUIStyle ResolvePanelStyle(const UUserWidget* Widget, const FUIStyle& Fallback)
	{
		if (Widget)
		{
			if (const UGameInstance* GI = Widget->GetGameInstance())
			{
				if (const UZMMOThemeSubsystem* Theme = GI->GetSubsystem<UZMMOThemeSubsystem>())
				{
					return Theme->GetActiveUIStyle();
				}
			}
		}
		// Design-time (sem GameInstance/subsystem): carrega o DT_UI_Styles
		// direto e usa a row "Default", para o Designer pintar/mostrar os
		// brushes igual ao runtime (caso contrário FUIStyle vem vazio).
		// Design-time relê o DT a cada chamada: editar o DT_UI_Styles e
		// RECOMPILAR o WBP já reflete (sem reiniciar o editor).
		FUIStyle DesignStyle;
		bool bHas = false;
		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("UIPanelDesign"), false))
			{
				DesignStyle = Row->Style;
				bHas = true;
			}
		}
		return bHas ? DesignStyle : Fallback;
	}
}

void UUIPanel_Base::RefreshUIStyle()
{
	if (!Background)
	{
		return;
	}
	const FUIStyle Fallback;
	const FUIStyle AS = ResolvePanelStyle(this, Fallback);
	const FUIStylePanel& P = AS.Panel;

	// bUseTheme = true  -> brushes vêm da DT (lookup pelas 3 chaves).
	// bUseTheme = false -> brushes vêm dos 3 FSlateBrush em Panels (direto).

	static const FSlateBrush NoDrawBrush = []
	{
		FSlateBrush B;
		B.DrawAs = ESlateBrushDrawType::NoDrawType;
		return B;
	}();

	auto ResolveFromTheme = [](FName Key,
		const TMap<FName, FSlateBrush>& Map) -> const FSlateBrush*
	{
		return Key.IsNone() ? nullptr : Map.Find(Key);
	};

	const FSlateBrush* BgTex = bUseTheme
		? ResolveFromTheme(BackgroundKey, P.PanelBackgroundByName)
		: &Panels.PanelBackground;
	Background->SetBrush(BgTex ? *BgTex : NoDrawBrush);

	if (Outline)
	{
		const FSlateBrush* OlTex = bUseTheme
			? ResolveFromTheme(OutlineKey, P.PanelOutlineByName)
			: &Panels.PanelOutline;
		Outline->SetBrush(OlTex ? *OlTex : NoDrawBrush);
	}

	if (OutlineEffect)
	{
		const FSlateBrush* OeTex = bUseTheme
			? ResolveFromTheme(OutlineEffectKey, P.PanelOutlineEffectByName)
			: &Panels.PanelOutlineEffect;
		OutlineEffect->SetBrush(OeTex ? *OeTex : NoDrawBrush);
	}

	BP_ApplyPanelStyle(P);
}

void UUIPanel_Base::NativePreConstruct()
{
	Super::NativePreConstruct();
	RefreshUIStyle();
}

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

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

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

void UUIPanel_Base::HandleThemeChanged(FName /*NewThemeId*/)
{
	RefreshUIStyle();
}

namespace
{
	enum class EPanelBrushSlot : uint8 { Background, Outline, OutlineEffect };

	TArray<FString> CollectPanelOptions(EPanelBrushSlot Slot)
	{
		TArray<FString> Options;
		Options.Add(FString());  // entry vazia = "sem brush" (NoDrawType)

		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("UIPanelGetOptions"), false);
		if (!Row)
		{
			return Options;
		}

		const TMap<FName, FSlateBrush>* Map = nullptr;
		switch (Slot)
		{
			case EPanelBrushSlot::Background:    Map = &Row->Style.Panel.PanelBackgroundByName;    break;
			case EPanelBrushSlot::Outline:       Map = &Row->Style.Panel.PanelOutlineByName;       break;
			case EPanelBrushSlot::OutlineEffect: Map = &Row->Style.Panel.PanelOutlineEffectByName; break;
		}
		if (Map)
		{
			for (const TPair<FName, FSlateBrush>& Pair : *Map)
			{
				Options.Add(Pair.Key.ToString());
			}
			Options.Sort();
		}
		return Options;
	}
}

TArray<FString> UUIPanel_Base::GetPanelBackgroundOptions() const
{
	return CollectPanelOptions(EPanelBrushSlot::Background);
}

TArray<FString> UUIPanel_Base::GetPanelOutlineOptions() const
{
	return CollectPanelOptions(EPanelBrushSlot::Outline);
}

TArray<FString> UUIPanel_Base::GetPanelOutlineEffectOptions() const
{
	return CollectPanelOptions(EPanelBrushSlot::OutlineEffect);
}
