// Copyright Epic Games, Inc. All Rights Reserved.
// UE5 Modular Game Framework — BPC_DamageReceptionSystem (72)
// Damage reception, resistance calculation, and damage application.
// Called potentially dozens of times per combat frame — C++ performance critical.

#pragma once

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "GameplayTagContainer.h"
#include "BPC_DamageReceptionSystem.generated.h"

// Forward declarations
class UDA_EquipmentConfig;
class UBPC_HealthSystem;
class UBPC_ShieldDefenseSystem;
class UBPC_HitReactionSystem;

// Delegates
DECLARE_DYNAMIC_MULTICAST_DELEGATE_FiveParams(FOnDamageReceived, float, RawDamage, float, FinalDamage,
	AActor*, DamageCauser, FGameplayTag, DamageType, FVector, HitLocation);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnDamageResisted, float, DamageResisted,
	FGameplayTag, ResistanceType, FString, Reason);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnStaggered, AActor*, StaggerCauser, float, StaggerForce);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnKnockedDown, AActor*, KnockdownCauser, float, KnockdownForce);

/**
 * Damage modifier for a specific damage type.
 */
USTRUCT(BlueprintType)
struct PG_FRAMEWORK_API FDamageModifier
{
	GENERATED_BODY()

	/** The damage type this modifier applies to. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FGameplayTag DamageType;

	/** Multiplier applied to incoming damage of this type. 0.5 = half damage, 2.0 = double. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float Multiplier = 1.0f;

	/** If true, this is a flat reduction (subtract after multiplier). */
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	bool bFlatReduction = false;

	/** Flat damage reduction amount (only used if bFlatReduction is true). */
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float FlatReduction = 0.0f;
};

/**
 * BPC_DamageReceptionSystem — Damage Reception & Resistance.
 *
 * Processes incoming damage: calculates resistance, applies armor/shield modifiers,
 * triggers hit reactions (stagger, knockdown), and routes final damage to the
 * health system. In C++, the damage pipeline is native-speed vectorized math.
 */
UCLASS(Blueprintable, ClassGroup = (Framework), meta = (BlueprintSpawnableComponent))
class PG_FRAMEWORK_API UBPC_DamageReceptionSystem : public UActorComponent
{
	GENERATED_BODY()

public:
	UBPC_DamageReceptionSystem();

	// ========================================================================
	// Configuration
	// ========================================================================

	/** Equipment config for armor/damage modifiers. */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Framework|Config")
	TObjectPtr<UDA_EquipmentConfig> EquipmentConfig;

	/** Base damage resistance (0.0 = no resistance, 1.0 = immune). */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Framework|Combat")
	float BaseResistance = 0.0f;

	/** Damage multipliers per damage type. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Framework|Combat")
	TArray<FDamageModifier> DamageModifiers;

	// ========================================================================
	// Damage Calculation — Hot Path
	// ========================================================================

	/**
	 * Calculate and apply damage.
	 * Full pipeline: raw damage → calculate resistance → apply armor → apply shield → apply health.
	 * Returns actual damage dealt.
	 */
	UFUNCTION(BlueprintCallable, Category = "Framework|Combat")
	float ApplyDamage(float RawDamage, AActor* DamageCauser, FGameplayTag DamageType,
		FVector HitLocation, FVector HitDirection);

	/**
	 * Calculate effective resistance for a damage type.
	 * Used by UI/preview systems to show expected damage.
	 */
	UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Framework|Combat")
	float CalculateResistance(FGameplayTag DamageType) const;

	/**
	 * Get the damage modifier for a specific damage type.
	 */
	UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Framework|Combat")
	float GetDamageMultiplier(FGameplayTag DamageType) const;

	// ========================================================================
	// Hit Reaction
	// ========================================================================

	/** Damage threshold to trigger a stagger reaction. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Framework|Combat|Reactions")
	float StaggerThreshold = 20.0f;

	/** Damage threshold to trigger a knockdown. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Framework|Combat|Reactions")
	float KnockdownThreshold = 50.0f;

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

	UPROPERTY(BlueprintAssignable, Category = "Framework|Events")
	FOnDamageReceived OnDamageReceived;

	UPROPERTY(BlueprintAssignable, Category = "Framework|Events")
	FOnDamageResisted OnDamageResisted;

	UPROPERTY(BlueprintAssignable, Category = "Framework|Events")
	FOnStaggered OnStaggered;

	UPROPERTY(BlueprintAssignable, Category = "Framework|Events")
	FOnKnockedDown OnKnockedDown;

protected:
	/** Triggers hit reaction based on final damage amount. */
	void EvaluateHitReaction(float FinalDamage, AActor* DamageCauser, FVector HitDirection);

	/** Cached references to sibling components. */
	UPROPERTY()
	TObjectPtr<UBPC_HealthSystem> CachedHealthSystem;

	UPROPERTY()
	TObjectPtr<UBPC_ShieldDefenseSystem> CachedShieldSystem;

	UPROPERTY()
	TObjectPtr<UBPC_HitReactionSystem> CachedHitReactionSystem;
};
