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

#pragma once

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

class UCommission;
class UCommissionBoardConfig;
class ANakedDesireCharacter;
class UGlobalSaveGameData;
struct FCommissionReward;

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnCommissionBoardChangedSignature);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnCommissionCompletedSignature, UCommission*, Commission);

/**
 * Runtime owner of the commission board (GDD §13). Offers the hand-authored pool, drives the
 * accept / complete / expire lifecycle, pays rewards instantly on completion (§23 #23), and persists
 * commission state to the save. A WorldSubsystem (like UTimeOfDaySubsystem / SessionManager): it needs
 * world access + OnDayChanged, and rehydrates durable state from the GameInstance save each level.
 */
UCLASS()
class NAKEDDESIRE_API UMissionSubsystem : public UWorldSubsystem
{
	GENERATED_BODY()

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

	UFUNCTION(BlueprintPure)
	const TArray<UCommission*>& GetOfferedCommissions() const { return OfferedCommissions; }

	UFUNCTION(BlueprintPure)
	const TArray<UCommission*>& GetAcceptedCommissions() const { return AcceptedCommissions; }

	// Commissions completed within the current period. Cleared at the day-roll alongside the accepted
	// list (see ExpireAccepted), so today this is "completed today" for both tiers — true week-long
	// retention for weeklies needs the deferred §13.1 weekly-lifecycle work.
	UFUNCTION(BlueprintPure)
	const TArray<UCommission*>& GetCompletedCommissions() const { return CompletedCommissions; }

	UFUNCTION(BlueprintCallable)
	void AcceptCommission(UCommission* Commission);

	UFUNCTION(BlueprintCallable)
	void AbandonCommission(UCommission* Commission);

	UPROPERTY(BlueprintAssignable)
	FOnCommissionBoardChangedSignature OnBoardChanged;

	UPROPERTY(BlueprintAssignable)
	FOnCommissionCompletedSignature OnCommissionCompleted;

private:
	UFUNCTION()
	void HandleDayChanged(int32 NewDay);

	void BuildBoard();        // instantiate offered commissions from the config
	void RestoreFromSave();   // re-apply persisted accepted / completed states
	void ExpireAccepted();    // deadline: accepted & unfinished -> expired
	void HandleCommissionCompleted(UCommission* Commission);
	void ApplyReward(const FCommissionReward& Reward);
	void PersistState() const;

	ANakedDesireCharacter* GetPlayer() const;
	UGlobalSaveGameData* GetSave() const;
	UCommissionBoardConfig* GetBoardConfig() const;

	UPROPERTY()
	TArray<UCommission*> OfferedCommissions;

	UPROPERTY()
	TArray<UCommission*> AcceptedCommissions;

	UPROPERTY()
	TArray<UCommission*> CompletedCommissions;
};