// © 2025 Naked People Team. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "Subsystems/WorldSubsystem.h"
#include "SessionManagerSubsystem.generated.h"

class UStatsManager;
class ULocationData;

/**
 * Why a session ended (GDD §4.4). SafeReturn is a non-loss end (player walked
 * home); the other three are the session-loss conditions from §3.3. The actual
 * "what gets lost" handling lives in USessionLossResolver (DEV-100), which also
 * applies police-chase precedence via bPoliceChaseActive.
 */
UENUM(BlueprintType)
enum class ESessionLossCause : uint8
{
	SafeReturn,
	EmbarrassmentMax,
	EnergyZero,
	PoliceCapture
};

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnSessionStartSignature);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnSessionEndSignature, ESessionLossCause, Cause);

/**
 * Owns the "going outside" session state (GDD §4). A session starts when the
 * player leaves the apartment and ends when they return safely or hit a loss
 * condition (embarrassment max / energy zero / police capture). The apartment
 * ALocationTrigger drives start / end; embarrassment-max and energy-zero are
 * detected by subscribing to UStatsManager. This replaces the EndGameEmbarrassed
 * Blueprint event on ANakedDesireGameMode.
 *
 * The apartment threshold is detected via ULocationSubsystem: a session starts when the player leaves
 * a location tagged Location.Apartment and ends (SafeReturn) when they re-enter one. There is no
 * per-trigger apartment flag — the apartment is just a tagged location.
 */
UCLASS()
class NAKEDDESIRE_API USessionManagerSubsystem : public UWorldSubsystem
{
	GENERATED_BODY()

public:
	virtual void OnWorldBeginPlay(UWorld& InWorld) override;

	UFUNCTION(BlueprintPure, Category = "Session")
	bool IsSessionActive() const { return bSessionActive; }

	// Set by the police AI pipeline (Phase 6). Read by USessionLossResolver for
	// the §4.4 loss precedence rule: a loss fired mid-chase resolves as capture.
	UFUNCTION(BlueprintCallable, Category = "Session")
	void SetPoliceChaseActive(bool bActive) { bPoliceChaseActive = bActive; }

	UFUNCTION(BlueprintPure, Category = "Session")
	bool IsPoliceChaseActive() const { return bPoliceChaseActive; }

	UPROPERTY(BlueprintAssignable, Category = "Session")
	FOnSessionStartSignature OnSessionStart;

	UPROPERTY(BlueprintAssignable, Category = "Session")
	FOnSessionEndSignature OnSessionEnd;

private:
	void StartSession();
	void EndSession(ESessionLossCause Cause);

	void BindToPlayerStats();

	UFUNCTION()
	void HandleLocationEntered(ULocationData* Location);

	UFUNCTION()
	void HandleLocationExited(ULocationData* Location);

	UFUNCTION()
	void HandleEmbarrassmentUpdate(float CurrentValue, float MaxValue);

	UFUNCTION()
	void HandleEnergyUpdate(float CurrentValue, float MaxValue);

	bool bSessionActive = false;
	bool bPoliceChaseActive = false;
};