using UnityEngine;
using UnityEngine.Events;

/// <summary>
/// GAME 1303 Tier 6 — "Being in the dark too long has bad effects on the player."
/// (Jax's class idea for Detective Liz.) A dread meter that fills in darkness, empties
/// in light, and hurts you when it's full.
///
/// SETUP
///  1. Add to the player, next to Health and Flashlight2D.
///  2. What counts as "safe light":
///       - the player's own flashlight being ON (tick Flashlight Counts), and/or
///       - standing inside a SafeLightZone trigger (a lamp, a window, a lit room).
///  3. Fill Rate / Drain Rate are per second. At 1.0 the meter is full: the player takes
///     Damage Per Interval every Damage Interval seconds until they find light.
///  4. OnMeterChanged(0-1) -> a HUD vignette (an Image whose alpha you drive) or a bar.
///     OnEnteredDarkness / OnFoundLight are good hooks for a heartbeat sound and music.
///  5. Grace Seconds gives a moment of darkness for free so walking past a shadow doesn't
///     start the dread.
///
/// Design note: pairing this with the "recharge only while standing still" flashlight rule
/// makes a real dilemma — stand still to get light back, and the dread rises while you do.
/// That tension is the game.
/// </summary>
public class DarknessMeter : MonoBehaviour
{
    [Header("Rates (per second)")]
    public float fillRate = 0.15f;
    public float drainRate = 0.5f;
    public float graceSeconds = 1.5f;

    [Header("Light sources that count")]
    public bool flashlightCounts = true;
    public Flashlight2D flashlight;
    [Tooltip("Layers of SafeLightZone triggers.")]
    public LayerMask safeLightLayers;
    public float checkRadius = 0.3f;

    [Header("Damage when full")]
    public int damagePerInterval = 1;
    public float damageInterval = 2f;

    [Header("Events")]
    public UnityEvent<float> OnMeterChanged;   // 0-1
    public UnityEvent OnEnteredDarkness;
    public UnityEvent OnFoundLight;
    public UnityEvent OnMeterFull;

    public float Meter { get; private set; }
    public bool InDarkness { get; private set; }

    private Health health;
    private float graceTimer;
    private float damageTimer;
    private bool wasInDarkness;

    void Awake()
    {
        health = GetComponent<Health>();
        if (flashlight == null) flashlight = GetComponent<Flashlight2D>();
    }

    void Update()
    {
        bool lit = IsInLight();
        InDarkness = !lit;

        if (InDarkness != wasInDarkness)
        {
            wasInDarkness = InDarkness;
            if (InDarkness) { graceTimer = graceSeconds; OnEnteredDarkness?.Invoke(); }
            else OnFoundLight?.Invoke();
        }

        float before = Meter;

        if (InDarkness)
        {
            if (graceTimer > 0f) graceTimer -= Time.deltaTime;
            else Meter = Mathf.Min(1f, Meter + fillRate * Time.deltaTime);
        }
        else
        {
            Meter = Mathf.Max(0f, Meter - drainRate * Time.deltaTime);
            damageTimer = 0f;
        }

        if (!Mathf.Approximately(before, Meter)) OnMeterChanged?.Invoke(Meter);

        if (Meter >= 1f)
        {
            if (before < 1f) OnMeterFull?.Invoke();
            damageTimer -= Time.deltaTime;
            if (damageTimer <= 0f)
            {
                damageTimer = damageInterval;
                health?.TakeDamage(damagePerInterval);
            }
        }
    }

    bool IsInLight()
    {
        if (flashlightCounts && flashlight != null && flashlight.IsOn) return true;
        return Physics2D.OverlapCircle(transform.position, checkRadius, safeLightLayers) != null;
    }

    /// <summary>Reset on respawn — wire RespawnManager.OnRespawned here.</summary>
    public void ResetMeter()
    {
        Meter = 0f;
        graceTimer = graceSeconds;
        damageTimer = 0f;
        OnMeterChanged?.Invoke(0f);
    }
}