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

#pragma once

#include "CoreMinimal.h"
#include "CommonUserWidget.h"
#include "ForumCommissionWidget.generated.h"

class UButton;
class UCommonTextBlock;
class UCommission;
struct FCommissionReward;

// One commission entry on the forum board (GDD §13). Populated from a runtime UCommission by the
// owning UForumCommissionsWidget; it shows the title, lore poster, reward, and per-objective progress,
// and surfaces the accept / abandon control appropriate to the commission's lifecycle state. The row
// owns no logic beyond display — it reports button taps up via delegates, like UPhoneAppIconWidget.
UCLASS(Abstract)
class NAKEDDESIRE_API UForumCommissionWidget : public UCommonUserWidget
{
	GENERATED_BODY()

public:
	// Bind a runtime commission and refresh the row. Passing null leaves the row blank.
	void SetCommission(UCommission* InCommission);

	DECLARE_DELEGATE_OneParam(FOnCommissionActionRequested, UCommission*);
	FOnCommissionActionRequested OnAcceptClicked;   // Offered -> accept
	FOnCommissionActionRequested OnAbandonClicked;  // Accepted -> abandon (§13.2, no penalty)

protected:
	virtual void NativeOnInitialized() override;

	// Accepted commissions ramp progress continuously (travel distance, hold timers) with no per-tick
	// delegate, so the row polls its objectives here while live to keep the percentages current.
	virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override;

private:
	UPROPERTY(meta = (BindWidget))
	TObjectPtr<UCommonTextBlock> TitleText;

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

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

	UPROPERTY(meta = (BindWidget))
	TObjectPtr<UCommonTextBlock> DescriptionText;

	// Optional so display-only hosts (e.g. the HUD commission tracker) can reuse this row without a button.
	UPROPERTY(meta = (BindWidgetOptional))
	TObjectPtr<UButton> AcceptButton;

	UPROPERTY(meta = (BindWidgetOptional))
	TObjectPtr<UButton> AbandonButton;

	UFUNCTION()
	void HandleAcceptClicked();

	UFUNCTION()
	void HandleAbandonClicked();

	// Rebuild the per-objective progress text, but only push it to the widget when it actually changed,
	// so the poll doesn't churn SetText every tick.
	void UpdateObjectivesText();
	FString BuildObjectivesString() const;
	static FText FormatReward(const FCommissionReward& Reward);

	UPROPERTY()
	TObjectPtr<UCommission> Commission;

	// Throttle for the in-progress poll (seconds between objective-text refreshes) and its accumulator.
	static constexpr float ProgressRefreshInterval = 0.25f;
	float TimeSinceProgressRefresh = 0.0f;

	// Last string pushed to DescriptionText; used to skip redundant SetText calls.
	FString CachedObjectivesString;
};