#include "UIBootScreen_Base.h"

#include "ZMMO.h"
#include "UIButton_Base.h"
#include "UISpinner_Base.h"
#include "UIFrontEndFlowSubsystem.h"
#include "ZMMOThemeSubsystem.h"
#include "ZeusCharServerSubsystem.h"
#include "CommonTextBlock.h"
#include "Components/Border.h"
#include "Engine/GameInstance.h"
#include "Engine/DataTable.h"
#include "UI/UIStyleRow.h"

namespace
{
	// Runtime usa o tema ativo; design-time carrega a row "Default" de
	// DT_UI_Styles para o Designer ver o fundo (mesmo padrão de UUIPanel_Base).
	FUIStyle ResolveBootStyle(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("UIBootDesign"), false))
			{
				DesignStyle = Row->Style;
				bHas = true;
			}
		}
		return bHas ? DesignStyle : Fallback;
	}
}

void UUIBootScreen_Base::NativePreConstruct()
{
	Super::NativePreConstruct();
	RefreshUIStyle(); // preview do fundo no Designer (DT_UI_Styles "Default")
}

void UUIBootScreen_Base::NativeOnActivated()
{
	Super::NativeOnActivated(); // base: RefreshUIStyle + BP_OnScreenActivated

	if (Btn_Start)
	{
		Btn_Start->OnClicked().AddUObject(this, &UUIBootScreen_Base::HandleStartClicked);
	}

	UZeusCharServerSubsystem* Char = GetCharServer();
	const bool bConnected = Char && Char->IsConnected();
	SetReady(bConnected);

	if (Char && !bCharBound)
	{
		Char->OnConnected.AddDynamic(this, &UUIBootScreen_Base::HandleCharConnected);
		Char->OnConnectionFailed.AddDynamic(this, &UUIBootScreen_Base::HandleCharConnectionFailed);
		bCharBound = true;
	}
	// A conexão em si é disparada pelo UUIFrontEndFlowSubsystem (estado Boot).
}

void UUIBootScreen_Base::NativeOnDeactivated()
{
	if (Btn_Start)
	{
		Btn_Start->OnClicked().RemoveAll(this);
	}
	if (bCharBound)
	{
		if (UZeusCharServerSubsystem* Char = GetCharServer())
		{
			Char->OnConnected.RemoveDynamic(this, &UUIBootScreen_Base::HandleCharConnected);
			Char->OnConnectionFailed.RemoveDynamic(this, &UUIBootScreen_Base::HandleCharConnectionFailed);
		}
		bCharBound = false;
	}
	Super::NativeOnDeactivated();
}

void UUIBootScreen_Base::RefreshUIStyle_Implementation()
{
	Super::RefreshUIStyle_Implementation();

	const FUIStyle Fallback;
	const FUIStyle AS = ResolveBootStyle(this, Fallback);

	if (Border_Bg)
	{
		// Fundo data-driven do DT_UI_Styles (T_Boot_Background) — sem
		// hard-ref de textura no WBP (§5). Fallback p/ cor se vazio.
		if (AS.ScreenBackground.GetResourceObject() != nullptr)
		{
			Border_Bg->SetBrush(AS.ScreenBackground);
		}
		else
		{
			Border_Bg->SetBrushColor(AS.Palette.Bg0);
		}
	}
	if (Text_Status)
	{
		Text_Status->SetColorAndOpacity(FSlateColor(AS.Semantic.OnSurfaceMuted));
	}
}

void UUIBootScreen_Base::SetReady(bool bReady)
{
	if (Btn_Start)
	{
		// Enquanto conecta: OCULTO (Collapsed, sem ocupar layout). Conectado:
		// visível e interagível.
		Btn_Start->SetVisibility(
			bReady ? ESlateVisibility::Visible : ESlateVisibility::Collapsed);
		Btn_Start->SetIsInteractionEnabled(bReady);
	}
	if (Spinner_Connect)
	{
		Spinner_Connect->SetVisibility(
			bReady ? ESlateVisibility::Collapsed : ESlateVisibility::HitTestInvisible);
	}
	if (Text_Status)
	{
		Text_Status->SetText(bReady ? ReadyText : ConnectingText);
	}
}

UZeusCharServerSubsystem* UUIBootScreen_Base::GetCharServer() const
{
	const UGameInstance* GI = GetGameInstance();
	return GI ? GI->GetSubsystem<UZeusCharServerSubsystem>() : nullptr;
}

void UUIBootScreen_Base::HandleStartClicked()
{
	UZeusCharServerSubsystem* Char = GetCharServer();
	if (!Char || !Char->IsConnected())
	{
		return; // botão só age quando conectado (defensivo)
	}
	if (const UGameInstance* GI = GetGameInstance())
	{
		if (UUIFrontEndFlowSubsystem* Flow = GI->GetSubsystem<UUIFrontEndFlowSubsystem>())
		{
			Flow->RequestEnterLogin();
		}
	}
}

void UUIBootScreen_Base::HandleCharConnected()
{
	UE_LOG(LogZMMO, Log, TEXT("BootScreen: CharServer conectado — botão liberado."));
	SetReady(true);
}

void UUIBootScreen_Base::HandleCharConnectionFailed(FString Reason)
{
	UE_LOG(LogZMMO, Warning, TEXT("BootScreen: falha ao conectar ao CharServer: %s"), *Reason);
	SetReady(false);
	if (Text_Status)
	{
		Text_Status->SetText(FailedText);
	}
}
