#pragma once

#include "CoreMinimal.h"
#include "UIActivatableScreen_Base.h"
#include "UI/LoadingTypes.h"
#include "UILoadingScreen_Base.generated.h"

class UCommonTextBlock;
class UProgressBar;
class UDataTable;
class UZMMOLoadingProfilesDataAsset;

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FZMMOOnLoadingComplete);

/**
 *  Tela de loading genérica. Reusada pelo FrontEnd (handoff CharServer →
 *  WorldServer) e pelo InGame (entrada em instance/dungeon, respawn). Cada
 *  uso passa um EZMMOLoadingContext em Configure(), que resolve o perfil
 *  no UZMMOLoadingProfilesDataAsset (lista de etapas + título).
 *
 *  Quem orquestra (UIFrontEndFlowSubsystem, futuro UIInGameFlowSubsystem)
 *  assina os próprios eventos (HandlePostLoadMap, OnPlayerSpawned, etc) e
 *  chama MarkStepDone(StepId) — server NÃO envia opcode de progresso (ver
 *  [[project_ui_loading_dynamic]]).
 *
 *  Dismiss: a tela emite OnLoadingComplete quando todas as etapas estão
 *  Done. Caller decide quando popar (geralmente após pequeno fade-out).
 *
 *  WBP concreto herda DIRETO desta classe. Subclasses C++ específicas só
 *  surgem quando houver necessidade real de estilo divergente.
 */
UCLASS(Abstract, Blueprintable)
class ZMMO_API UUILoadingScreen_Base : public UUIActivatableScreen_Base
{
	GENERATED_BODY()

public:
	/**
	 *  Configura a tela: carrega o perfil do contexto, popula a pool de
	 *  dicas filtrada e reseta estado das etapas. Pode ser chamado depois
	 *  de NativeOnActivated (estado é reaplicado em RefreshUI).
	 */
	UFUNCTION(BlueprintCallable, Category = "Loading")
	void Configure(EZMMOLoadingContext InContext,
	               UZMMOLoadingProfilesDataAsset* Profiles,
	               UDataTable* TipsTable);

	UFUNCTION(BlueprintCallable, Category = "Loading")
	void MarkStepRunning(FName StepId);

	UFUNCTION(BlueprintCallable, Category = "Loading")
	void MarkStepDone(FName StepId);

	UFUNCTION(BlueprintCallable, Category = "Loading")
	void MarkStepFailed(FName StepId, const FText& Reason);

	UFUNCTION(BlueprintPure, Category = "Loading")
	bool AreAllStepsDone() const;

	/** Disparado UMA vez quando todas as etapas viram Done. */
	UPROPERTY(BlueprintAssignable, Category = "Loading")
	FZMMOOnLoadingComplete OnLoadingComplete;

protected:
	virtual void NativeOnActivated() override;
	virtual void NativeOnDeactivated() override;

	/** Reaplica todo o estado aos widgets bindados (texto, progress, tip). */
	void RefreshUI();
	void RotateTip();
	void StartTipTimer();
	void StopTipTimer();

	/** Acha índice da etapa por StepId; -1 se não existir. */
	int32 FindStepIndex(FName StepId) const;

	/** Status atual da etapa em [Steps_]; Pending se não rastreada. */
	EZMMOLoadingStepStatus GetStepStatus(int32 Index) const;

	/** Texto exibido em Text_Status — etapa Running atual ou última Done. */
	FText ComputeCurrentStatusText() const;

	/** Progresso 0..1: #Done / max(1,#Steps). Running conta como meio passo. */
	float ComputeProgress01() const;

	// ---- Bind widgets (BindWidgetOptional — WBP pode omitir qualquer) ----
	UPROPERTY(meta = (BindWidgetOptional))
	TObjectPtr<UCommonTextBlock> Text_Title;

	UPROPERTY(meta = (BindWidgetOptional))
	TObjectPtr<UCommonTextBlock> Text_Status;

	UPROPERTY(meta = (BindWidgetOptional))
	TObjectPtr<UProgressBar> ProgressBar_Progress;

	UPROPERTY(meta = (BindWidgetOptional))
	TObjectPtr<UCommonTextBlock> Text_Tip;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Loading")
	FText TitleDefault = FText::FromString(TEXT("Carregando"));

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Loading")
	FText StatusDefault = FText::FromString(TEXT("Entrando no mundo..."));

	/** Intervalo entre dicas. 0 = sem rotação (mostra a primeira dica fixa). */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Loading")
	float TipRotationIntervalSeconds = 6.f;

private:
	EZMMOLoadingContext Context_ = EZMMOLoadingContext::None;

	UPROPERTY(Transient)
	FZMMOLoadingProfile Profile_;

	UPROPERTY(Transient)
	TMap<FName, EZMMOLoadingStepStatus> StepStatus_;

	UPROPERTY(Transient)
	TArray<FText> TipPool_;

	int32 NextTipIndex_ = 0;
	bool bCompleteFired_ = false;
	FTimerHandle TipTimerHandle_;
};
