using UnityEngine;
using UnityEngine.Events;

/// <summary>
/// GAME 1303 Tier 7 — One need: hunger, energy, cleanliness, happiness. Cozy Critters.
///
/// SETUP
///  1. Add ONE of these per need to the pet. Rename the Stat Name field ("Hunger").
///  2. Decay Per Minute is how fast it falls. Rhys's pitch is explicit that the pet must
///     NOT die from two seconds of inattention, so keep these low: 2-5 per minute means
///     a full bar lasts 20-50 minutes of play. Tune by feel, not by realism.
///  3. Higher Is Better: ON for happiness/energy (100 = great), OFF for a stat where a
///     high number is bad. Everything below assumes higher = better.
///  4. Low Threshold fires OnBecameLow once when it drops past it — that's the cue for a
///     sad animation or a thought bubble, not a punishment.
///  5. Affects Happiness: if ON, this need being low drags happiness down (wire the
///     happiness NeedStat into Happiness Stat). That's how "care for it, increase
///     happiness" from the pitch actually works.
///
/// NO DEATH: there is deliberately no "hits zero = game over" here. The worst that happens
/// is the pet is unhappy and its nature drifts (PersonalityTracker). That's the whole point
/// of a cozy sim.
/// </summary>
public class NeedStat : MonoBehaviour
{
    [Header("Identity")]
    public string statName = "Hunger";
    public Sprite icon;

    [Header("Value")]
    [Range(0f, 100f)] public float value = 100f;
    public float maxValue = 100f;
    [Tooltip("Points lost per minute of real time. Keep this gentle.")]
    public float decayPerMinute = 3f;
    public bool higherIsBetter = true;

    [Header("Thresholds")]
    [Range(0f, 100f)] public float lowThreshold = 30f;
    [Range(0f, 100f)] public float fullThreshold = 90f;

    [Header("Knock-on effect")]
    [Tooltip("While this need is low, drain the happiness stat too.")]
    public bool affectsHappiness = true;
    public NeedStat happinessStat;
    public float happinessDrainPerMinute = 2f;

    [Header("Events")]
    public UnityEvent<float> OnValueChanged;    // normalized 0-1
    public UnityEvent OnBecameLow;
    public UnityEvent OnBecameFull;

    public float Normalized => maxValue > 0f ? Mathf.Clamp01(value / maxValue) : 0f;
    public bool IsLow => value <= lowThreshold;
    public bool IsFull => value >= fullThreshold;

    private bool wasLow, wasFull;

    void Start() => OnValueChanged?.Invoke(Normalized);

    void Update()
    {
        float before = value;
        value = Mathf.Clamp(value - decayPerMinute / 60f * Time.deltaTime, 0f, maxValue);

        if (affectsHappiness && IsLow && happinessStat != null && happinessStat != this)
            happinessStat.Add(-happinessDrainPerMinute / 60f * Time.deltaTime);

        if (!Mathf.Approximately(before, value)) OnValueChanged?.Invoke(Normalized);

        if (IsLow && !wasLow) OnBecameLow?.Invoke();
        if (IsFull && !wasFull) OnBecameFull?.Invoke();
        wasLow = IsLow;
        wasFull = IsFull;
    }

    /// <summary>Add (or subtract) points. CareAction calls this.</summary>
    public void Add(float amount)
    {
        value = Mathf.Clamp(value + amount, 0f, maxValue);
        OnValueChanged?.Invoke(Normalized);
    }

    public void SetValue(float v)
    {
        value = Mathf.Clamp(v, 0f, maxValue);
        OnValueChanged?.Invoke(Normalized);
    }

    /// <summary>Apply offline decay when the game reloads. SaveSystem calls this.</summary>
    public void ApplyOfflineTime(float minutesAway)
    {
        Add(-decayPerMinute * minutesAway);
    }
}