// Copyright Epic Games, Inc. All Rights Reserved.
// UE5 Modular Game Framework — GS_CoreGameState (06)
// Shared session state. Fully replicated singleton visible to all players.
// Tracks chapter, narrative phase, encounter status, and active objectives.
// C++ gives us proper GetLifetimeReplicatedProps() and OnRep_ handlers.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/GameStateBase.h"
#include "GameplayTagContainer.h"
#include "Net/UnrealNetwork.h"
#include "GS_CoreGameState.generated.h"

// Delegates
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnChapterChanged, FGameplayTag, NewChapter);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnNarrativePhaseChanged, FGameplayTag, NewPhase);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnEncounterStateChanged, bool, bActive);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnObjectiveTagsChanged);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPlayTimeUpdated, float, ElapsedSeconds);

/**
 * GS_CoreGameState — Shared Session State.
 *
 * A replicated singleton data holder. All modification happens through
 * dedicated setter functions — never direct variable writes.
 *
 * In C++, replication is handled via GetLifetimeReplicatedProps() with
 * OnRep_ handlers that mirror broadcast dispatchers for both network
 * clients and local single-player.
 */
UCLASS(Blueprintable)
class PG_FRAMEWORK_API AGS_CoreGameState : public AGameStateBase
{
	GENERATED_BODY()

public:
	AGS_CoreGameState();

	// ========================================================================
	// Replicated State
	// ========================================================================

	/** Elapsed play time (accumulated only when GamePhase is InGame). */
	UPROPERTY(ReplicatedUsing = OnRep_ElapsedPlayTime, BlueprintReadOnly, Category = "Framework|State")
	float ElapsedPlayTime = 0.0f;

	/** Current story chapter tag. */
	UPROPERTY(ReplicatedUsing = OnRep_ActiveChapter, BlueprintReadOnly, Category = "Framework|Narrative")
	FGameplayTag ActiveChapterTag;

	/** Sub-chapter narrative phase. */
	UPROPERTY(ReplicatedUsing = OnRep_NarrativePhase, BlueprintReadOnly, Category = "Framework|Narrative")
	FGameplayTag ActiveNarrativePhase;

	/** Whether an AI encounter is currently active. */
	UPROPERTY(ReplicatedUsing = OnRep_EncounterActive, BlueprintReadOnly, Category = "Framework|Combat")
	bool bEncounterActive = false;

	/** Array of active objective tags. */
	UPROPERTY(ReplicatedUsing = OnRep_ObjectiveTags, BlueprintReadOnly, Category = "Framework|Narrative")
	TArray<FGameplayTag> ActiveObjectiveTags;

	// ========================================================================
	// Setters (Server-Authoritative)
	// ========================================================================

	UFUNCTION(BlueprintCallable, Category = "Framework|Narrative")
	void SetChapter(FGameplayTag ChapterTag);

	UFUNCTION(BlueprintCallable, Category = "Framework|Narrative")
	void SetNarrativePhase(FGameplayTag PhaseTag);

	UFUNCTION(BlueprintCallable, Category = "Framework|Combat")
	void SetEncounterActive(bool bActive);

	UFUNCTION(BlueprintCallable, Category = "Framework|Narrative")
	void AddObjective(FGameplayTag ObjectiveTag);

	UFUNCTION(BlueprintCallable, Category = "Framework|Narrative")
	void RemoveObjective(FGameplayTag ObjectiveTag);

	UFUNCTION(BlueprintCallable, Category = "Framework|Narrative")
	void ClearAllObjectives();

	// ========================================================================
	// Event Dispatchers
	// ========================================================================

	UPROPERTY(BlueprintAssignable, Category = "Framework|Events")
	FOnPlayTimeUpdated OnElapsedPlayTimeUpdated;

	UPROPERTY(BlueprintAssignable, Category = "Framework|Events")
	FOnChapterChanged OnChapterChanged;

	UPROPERTY(BlueprintAssignable, Category = "Framework|Events")
	FOnNarrativePhaseChanged OnNarrativePhaseChanged;

	UPROPERTY(BlueprintAssignable, Category = "Framework|Events")
	FOnEncounterStateChanged OnEncounterActiveStateChanged;

	UPROPERTY(BlueprintAssignable, Category = "Framework|Events")
	FOnObjectiveTagsChanged OnObjectiveTagsChanged;

	// ========================================================================
	// Overrides
	// ========================================================================

	virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
	virtual void BeginPlay() override;
	virtual void Tick(float DeltaTime) override;

protected:
	// ========================================================================
	// OnRep Handlers — Fire dispatchers for network clients AND local single-player
	// ========================================================================

	UFUNCTION()
	void OnRep_ElapsedPlayTime();

	UFUNCTION()
	void OnRep_ActiveChapter();

	UFUNCTION()
	void OnRep_NarrativePhase();

	UFUNCTION()
	void OnRep_EncounterActive();

	UFUNCTION()
	void OnRep_ObjectiveTags();

	// ========================================================================
	// Internal
	// ========================================================================

	/** Cached GameInstance for phase checking during time accumulation. */
	UPROPERTY()
	TObjectPtr<class UGI_GameFramework> CachedFramework;

	/** Throttle timer for play time updates (fires ~1/sec). */
	float TimeUpdateAccumulator = 0.0f;
	static constexpr float TimeUpdateInterval = 1.0f;
};
