#pragma once

#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "UI/ThemeKeys.h"
#include "UI/ThemeRow.h"
#include "UI/UIStyleRow.h"
#include "ZMMOThemeSubsystem.generated.h"

class UZMMOThemeDataAsset;
class UDataTable;
class UTexture2D;
class USoundBase;
class UNiagaraSystem;

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnZMMOThemeChanged, FName, NewThemeId);

/**
 * Resolves which UI theme is active and answers asset lookups by EZMMOThemeKey.
 *
 * Resolution precedence (see ARQUITETURA.md §1.10):
 *   1. Dev override (.ini DevThemeOverride) — ignored in Shipping builds.
 *   2. Authoritative server theme (set via ApplyServerTheme).
 *   3. Local calendar (DT_ThemeCalendar).
 *   4. DA_Theme_Default.
 *
 * Widgets must never hold hard refs to theme textures/sounds. They consume the
 * active theme through Get* methods on this subsystem.
 */
UCLASS(Config = Game)
class ZMMO_API UZMMOThemeSubsystem : public UGameInstanceSubsystem
{
	GENERATED_BODY()

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

	/** Server-authoritative theme. Call from the ZeusNetwork ServerHello handler. */
	UFUNCTION(BlueprintCallable, Category = "Theme")
	void ApplyServerTheme(FName ThemeId);

	/** Forces a specific theme regardless of precedence. Use only for debug UI. */
	UFUNCTION(BlueprintCallable, Category = "Theme|Debug")
	void ForceTheme(FName ThemeId);

	/** Resets to the precedence-resolved theme. */
	UFUNCTION(BlueprintCallable, Category = "Theme|Debug")
	void ClearForcedTheme();

	UFUNCTION(BlueprintPure, Category = "Theme")
	FName GetActiveThemeId() const { return ActiveThemeId; }

	UFUNCTION(BlueprintCallable, Category = "Theme")
	UTexture2D* GetTexture(EZMMOThemeKey Key) const;

	UFUNCTION(BlueprintCallable, Category = "Theme")
	USoundBase* GetSound(EZMMOThemeKey Key) const;

	UFUNCTION(BlueprintCallable, Category = "Theme")
	UNiagaraSystem* GetVFX(EZMMOThemeKey Key) const;

	UFUNCTION(BlueprintCallable, Category = "Theme")
	UObject* GetGeneric(EZMMOThemeKey Key) const;

	/**
	 * Tokens de estilo (cores/fontes/dimensões) do tema ativo, resolvidos de
	 * DT_UI_Styles pelo ThemeId. Faz fallback para a linha "Default" quando o
	 * tema ativo não tem linha própria — mesma política dos assets (§5).
	 */
	UFUNCTION(BlueprintPure, Category = "Theme|Style")
	const FUIStyle& GetActiveUIStyle() const { return ActiveUIStyle; }

	/** Fired whenever the active theme actually changes. */
	UPROPERTY(BlueprintAssignable, Category = "Theme")
	FOnZMMOThemeChanged OnThemeChanged;

protected:
	/** Default theme. Must be filled with every key — it is the final fallback. */
	UPROPERTY(Config, EditDefaultsOnly, Category = "Theme")
	TSoftObjectPtr<UZMMOThemeDataAsset> DefaultThemeAsset;

	/** Registry of seasonal/event themes keyed by ThemeId. */
	UPROPERTY(Config, EditDefaultsOnly, Category = "Theme")
	TMap<FName, TSoftObjectPtr<UZMMOThemeDataAsset>> ThemeRegistry;

	/** Local calendar table (FThemeCalendarRow). Optional. */
	UPROPERTY(Config, EditDefaultsOnly, Category = "Theme")
	TSoftObjectPtr<UDataTable> CalendarTable;

	/** Tabela de tokens de estilo (FUIStyleRow), keyed por ThemeId. */
	UPROPERTY(Config, EditDefaultsOnly, Category = "Theme")
	TSoftObjectPtr<UDataTable> UIStyleTable;

	/** Dev-only override read from DefaultGame.ini. Empty in Shipping. */
	UPROPERTY(Config, EditDefaultsOnly, Category = "Theme|Debug")
	FName DevThemeOverride;

private:
	void ResolveActiveTheme();
	FName ResolveByCalendar() const;
	UZMMOThemeDataAsset* LoadThemeById(FName ThemeId) const;
	const FThemeEntry* FindEntryWithFallback(EZMMOThemeKey Key) const;
	void ResolveActiveUIStyle(FName ThemeId);

	UPROPERTY(Transient)
	TObjectPtr<UZMMOThemeDataAsset> ActiveTheme;

	UPROPERTY(Transient)
	TObjectPtr<UZMMOThemeDataAsset> DefaultTheme;

	UPROPERTY(Transient)
	FName ActiveThemeId;

	UPROPERTY(Transient)
	FName ServerThemeId;

	UPROPERTY(Transient)
	FName ForcedThemeId;

	UPROPERTY(Transient)
	FUIStyle ActiveUIStyle;
};
