#include "UICheckBox_Base.h"

#include "ZMMOThemeSubsystem.h"
#include "Engine/GameInstance.h"
#include "Engine/DataTable.h"
#include "Components/CheckBox.h"
#include "CommonTextBlock.h"
#include "UICommonText_Base.h"
#include "UI/UIStyleRow.h"

namespace
{
	// Mesmo padrão de UUISpinner_Base: runtime usa o tema ativo; design-time
	// carrega a row "Default" de DT_UI_Styles para o Designer ver igual.
	FUIStyle ResolveCheckBoxStyle(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 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("UICheckBoxDesign"), false))
			{
				DesignStyle = Row->Style;
				bHas = true;
			}
		}
		return bHas ? DesignStyle : Fallback;
	}
}

TArray<FString> UUICheckBox_Base::GetLabelTextRoleOptions() const
{
	return UUICommonText_Base::GetThemeTextRoleOptions();
}

TArray<FString> UUICheckBox_Base::GetVariantOptions() const
{
	TArray<FString> Options;
	Options.Add(TEXT("Default"));
	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("UICheckBoxVariantOptions"), false))
		{
			for (const TPair<FName, FUIStyleCheckBoxFill>&   P : Row->Style.CheckBox.Fills)   { Options.AddUnique(P.Key.ToString()); }
			for (const TPair<FName, FUIStyleCheckBoxStroke>& P : Row->Style.CheckBox.Strokes) { Options.AddUnique(P.Key.ToString()); }
			for (const TPair<FName, FUIStyleCheckBoxLayout>& P : Row->Style.CheckBox.Layouts) { Options.AddUnique(P.Key.ToString()); }
		}
	}
	return Options;
}

static FUIStyleCheckBoxVariant ResolveCheckBoxVariant(const FUIStyleCheckBox& C, FName VariantName)
{
	static const FUIStyleCheckBox Defaults;
	FUIStyleCheckBoxVariant V;

	if (const FUIStyleCheckBoxFill* E = C.Fills.Find(VariantName))      { V.Fill = *E; }
	else if (const FUIStyleCheckBoxFill* E2 = Defaults.Fills.Find(VariantName)) { V.Fill = *E2; }
	else { V.Fill = Defaults.Fills.FindRef(TEXT("Default")); }

	if (const FUIStyleCheckBoxStroke* E = C.Strokes.Find(VariantName))      { V.Stroke = *E; }
	else if (const FUIStyleCheckBoxStroke* E2 = Defaults.Strokes.Find(VariantName)) { V.Stroke = *E2; }
	else { V.Stroke = Defaults.Strokes.FindRef(TEXT("Default")); }

	if (const FUIStyleCheckBoxLayout* E = C.Layouts.Find(VariantName))      { V.Layout = *E; }
	else if (const FUIStyleCheckBoxLayout* E2 = Defaults.Layouts.Find(VariantName)) { V.Layout = *E2; }
	else { V.Layout = Defaults.Layouts.FindRef(TEXT("Default")); }

	return V;
}

void UUICheckBox_Base::RefreshUIStyle()
{
	const FUIStyle Fallback;
	const FUIStyle AS = ResolveCheckBoxStyle(this, Fallback);
	const FUIStyleCheckBoxVariant V = ResolveCheckBoxVariant(AS.CheckBox, Variant);

	if (Label && !LabelText.IsEmpty())
	{
		Label->SetText(LabelText);
	}
	if (UUICommonText_Base* CT = Cast<UUICommonText_Base>(Label))
	{
		if (CT->TextRole != LabelTextRole)
		{
			CT->TextRole = LabelTextRole;
		}
		CT->RefreshUIStyle();
	}

	if (CheckBox)
	{
		FCheckBoxStyle S = CheckBox->GetWidgetStyle();
		const FVector2D Box(V.Layout.BoxSize, V.Layout.BoxSize);

		auto Paint = [&Box](FSlateBrush& Brush, const FLinearColor& Tint)
		{
			Brush.TintColor = FSlateColor(Tint);
			Brush.ImageSize = Box;
		};
		Paint(S.UncheckedImage,            V.Stroke.BorderColor);
		Paint(S.UncheckedHoveredImage,     V.Fill.HoveredColor);
		Paint(S.UncheckedPressedImage,     V.Fill.PressedColor);
		Paint(S.CheckedImage,              V.Fill.BoxColor);
		Paint(S.CheckedHoveredImage,       V.Fill.HoveredColor);
		Paint(S.CheckedPressedImage,       V.Fill.PressedColor);
		Paint(S.UndeterminedImage,         V.Stroke.BorderColor);
		Paint(S.UndeterminedHoveredImage,  V.Fill.HoveredColor);
		Paint(S.UndeterminedPressedImage,  V.Fill.PressedColor);

		S.ForegroundColor = FSlateColor(V.Fill.CheckColor);
		S.BorderBackgroundColor = FSlateColor(V.Fill.DisabledColor);

		CheckBox->SetWidgetStyle(S);
	}

	BP_ApplyCheckBoxStyle(V);
}

bool UUICheckBox_Base::IsChecked() const
{
	return CheckBox ? CheckBox->IsChecked() : false;
}

void UUICheckBox_Base::SetIsChecked(bool bInChecked)
{
	if (CheckBox)
	{
		CheckBox->SetIsChecked(bInChecked);
	}
}

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

void UUICheckBox_Base::SynchronizeProperties()
{
	Super::SynchronizeProperties();
	// Live no Designer: edita LabelText/LabelTextRole nos Detalhes e o canvas
	// reflete na hora (sem precisar recompilar o WBP).
	RefreshUIStyle();
}

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

	if (CheckBox && !bCheckBound)
	{
		CheckBox->OnCheckStateChanged.AddDynamic(this, &UUICheckBox_Base::HandleCheckStateChanged);
		bCheckBound = true;
	}

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

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

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

void UUICheckBox_Base::HandleCheckStateChanged(bool bIsChecked)
{
	OnCheckStateChanged.Broadcast(bIsChecked);
}
