#pragma once

#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "UI/FrontEndTypes.h"
#include "UIFrontEndFlowSubsystem.generated.h"

class UUIFrontEndScreenSet;
class UUIManagerSubsystem;
class UZeusNetworkSubsystem;
class UZeusCharServerSubsystem;

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnZMMOFrontEndStateChanged, EZMMOFrontEndState, NewState);

/**
 * Orquestrador do fluxo de front-end. UGameInstanceSubsystem porque o
 * GameInstance persiste o travel boot→mundo (a máquina de estados não pode
 * morrer no OpenLevel).
 *
 * Responsável por: (a) dirigir a conexão via UZeusNetworkSubsystem;
 * (b) manter EZMMOFrontEndState; (c) resolver estado→tela pelo
 * DA_FrontEndScreenSet e pedir ao UUIManagerSubsystem para empurrar na
 * camada certa; (d) detectar a chegada ao mundo.
 *
 * As telas (WBP) ainda não existem — virão do Zeus UMG Forge (§4.8).
 * Enquanto não registradas no DA, cada transição faz no-op + log.
 */
UCLASS(Config = Game)
class ZMMO_API UUIFrontEndFlowSubsystem : public UGameInstanceSubsystem
{
	GENERATED_BODY()

public:
	// USubsystem
	virtual void Initialize(FSubsystemCollectionBase& Collection) override;
	virtual void Deinitialize() override;

	/**
	 * Ponto de entrada chamado pelo AZMMOFrontEndPlayerController::BeginPlay
	 * (garante que os subsistemas já existem — ver aviso no header do
	 * ZeusNetworkSubsystem sobre GameInstance::Init). Cria o root layout,
	 * liga os delegates de rede e dispara Boot→Connecting.
	 */
	UFUNCTION(BlueprintCallable, Category = "FrontEnd")
	void StartFrontEnd();

	UFUNCTION(BlueprintCallable, Category = "FrontEnd")
	void SetState(EZMMOFrontEndState NewState);

	UFUNCTION(BlueprintPure, Category = "FrontEnd")
	EZMMOFrontEndState GetCurrentState() const { return CurrentState; }

	/** Mostra uma página interna do Lobby ("switch principal"). */
	UFUNCTION(BlueprintCallable, Category = "FrontEnd")
	void ShowLobbyPage(EZMMOLobbyPage Page);

	/** "Voltar". Retorna true se o fluxo consumiu (tela base encaminha aqui). */
	UFUNCTION(BlueprintCallable, Category = "FrontEnd")
	bool RequestBack();

	/** Chamado pela tela Boot quando o usuário clica "Iniciar" (já conectado). */
	UFUNCTION(BlueprintCallable, Category = "FrontEnd")
	void RequestEnterLogin();

	UPROPERTY(BlueprintAssignable, Category = "FrontEnd")
	FOnZMMOFrontEndStateChanged OnStateChanged;

protected:
	/** DA com o mapa estado→tela. Config em DefaultGame.ini. */
	UPROPERTY(Config, EditDefaultsOnly, Category = "FrontEnd")
	TSoftObjectPtr<UUIFrontEndScreenSet> ScreenSetAsset;

private:
	void BindNetwork();
	void UnbindNetwork();
	UZeusNetworkSubsystem* GetZeusNetwork() const;
	UZeusCharServerSubsystem* GetCharServer() const;
	UUIManagerSubsystem* GetUIManager() const;
	UUIFrontEndScreenSet* GetScreenSet();

	/** Resolve a soft class do estado e empurra na camada Menu (no-op+log se vazio). */
	void ResolveAndPushScreen(EZMMOFrontEndState State);

	UFUNCTION()
	void HandleConnected();

	UFUNCTION()
	void HandleConnectionFailed(FString Reason);

	UFUNCTION()
	void HandleCharDisconnected(int32 StatusCode, FString Reason);

	UFUNCTION()
	void HandleServerTravelRequested(const FString& MapName, const FString& MapPath);

	void HandlePostLoadMap(UWorld* LoadedWorld);

	/**
	 * Dívida técnica (D5): ServerHello traz ThemeId, mas o UZeusNetworkSubsystem
	 * ainda não expõe um delegate/getter dedicado. Quando expuser, ligar aqui
	 * → UZMMOThemeSubsystem::ApplyServerTheme. Sem isto, o tema resolve por
	 * calendário/Default (ARQUITETURA.md §1.10).
	 */
	void HandleServerHelloTheme(FName ThemeId);

	UPROPERTY(Transient)
	EZMMOFrontEndState CurrentState = EZMMOFrontEndState::None;

	UPROPERTY(Transient)
	TObjectPtr<UUIFrontEndScreenSet> ScreenSet;

	bool bNetBound = false;
	bool bTravelingToWorld = false;
	FDelegateHandle PostLoadMapHandle;
};
