using UnityEngine;
using UnityEngine.Events;

/// <summary>
/// GAME 1303 Tier 6 — A ghost that hates the flashlight. Flees, freezes, fades, or burns
/// while lit. Detective Liz ("uses her flashlight to fight ghosts"); a Commission Witch
/// variant works too.
///
/// SETUP
///  1. Ghost: FloatingEnemy and/or EnemyChase (Tier 2) + Health + this script.
///     Add a Hurtbox child (Team = Enemy) so the flashlight's Hitbox can damage it.
///  2. Drag the player's Flashlight2D in, or leave it empty and it finds the Player tag.
///  3. Reaction while lit:
///       Flee     – runs away from the player (EnemyChase is disabled while lit)
///       Freeze   – stops dead, vulnerable
///       Weaken   – keeps moving but takes damage (via the beam's Hitbox) and fades
///       Banish   – takes Damage Per Second directly from this script; no Hitbox needed
///  4. Fade While Lit makes it visibly weaker — good feedback even without damage numbers.
///  5. Requires Line Of Sight stops the beam working through walls.
///
/// The reason this is a separate script rather than just "the beam is a Hitbox": the
/// interesting part isn't damage, it's that the ghost BEHAVES differently in light. That's
/// what makes the flashlight feel like a tool rather than a gun.
/// </summary>
public class LightSensitiveEnemy : MonoBehaviour
{
    public enum Reaction { Flee, Freeze, Weaken, Banish }

    public Reaction reaction = Reaction.Flee;
    public Flashlight2D flashlight;
    [Tooltip("Beam cone half-angle and range used for the check. Match your Light 2D.")]
    public float coneAngle = 35f;
    public float range = 8f;
    public bool requiresLineOfSight = true;
    public LayerMask wallLayers;

    [Header("Behaviour while lit")]
    public float fleeSpeed = 4f;
    public bool fadeWhileLit = true;
    [Range(0f, 1f)] public float litAlpha = 0.35f;
    [Tooltip("Banish mode: health lost per second in the beam.")]
    public float damagePerSecond = 2f;
    [Tooltip("Seconds still lit before the reaction starts (a moment of resistance).")]
    public float resistTime = 0.2f;

    [Header("Events")]
    public UnityEvent OnEnteredLight;
    public UnityEvent OnLeftLight;
    public UnityEvent OnBanished;

    public bool IsLit { get; private set; }

    private EnemyChase chase;
    private FloatingEnemy floater;
    private Rigidbody2D rb;
    private Health health;
    private SpriteRenderer sr;
    private Transform player;
    private float litTimer;
    private float damageAccumulator;
    private Color baseColour = Color.white;

    void Awake()
    {
        chase = GetComponent<EnemyChase>();
        floater = GetComponent<FloatingEnemy>();
        rb = GetComponent<Rigidbody2D>();
        health = GetComponent<Health>();
        sr = GetComponentInChildren<SpriteRenderer>();
        if (sr != null) baseColour = sr.color;
    }

    void Start()
    {
        var p = GameObject.FindGameObjectWithTag("Player");
        if (p != null)
        {
            player = p.transform;
            if (flashlight == null) flashlight = p.GetComponent<Flashlight2D>();
        }
    }

    void FixedUpdate()
    {
        bool lit = CheckLit();

        if (lit != IsLit)
        {
            IsLit = lit;
            litTimer = 0f;
            if (lit) OnEnteredLight?.Invoke(); else OnLeftLight?.Invoke();
            ApplyVisual();
            if (!lit) RestoreBehaviour();
        }

        if (!IsLit) return;

        litTimer += Time.fixedDeltaTime;
        if (litTimer < resistTime) return;

        switch (reaction)
        {
            case Reaction.Flee:
                if (chase != null) chase.enabled = false;
                if (floater != null) floater.enabled = false;
                if (rb != null && player != null)
                {
                    Vector2 away = ((Vector2)transform.position - (Vector2)player.position).normalized;
                    rb.linearVelocity = away * fleeSpeed;
                }
                break;

            case Reaction.Freeze:
                if (chase != null) chase.enabled = false;
                if (floater != null) floater.enabled = false;
                if (rb != null) rb.linearVelocity = Vector2.zero;
                break;

            case Reaction.Weaken:
                // Keeps moving; the beam's Hitbox does the damage.
                break;

            case Reaction.Banish:
                damageAccumulator += damagePerSecond * Time.fixedDeltaTime;
                if (damageAccumulator >= 1f && health != null)
                {
                    int whole = Mathf.FloorToInt(damageAccumulator);
                    damageAccumulator -= whole;
                    health.ClearInvulnerability();
                    health.TakeDamage(whole);
                    if (health.IsDead) OnBanished?.Invoke();
                }
                break;
        }
    }

    bool CheckLit()
    {
        if (flashlight == null || !flashlight.IsOn) return false;
        if (!flashlight.IsLit(transform.position, coneAngle, range)) return false;

        if (requiresLineOfSight && player != null)
        {
            Vector2 dir = (Vector2)transform.position - (Vector2)player.position;
            if (Physics2D.Raycast(player.position, dir.normalized, dir.magnitude, wallLayers)) return false;
        }
        return true;
    }

    void ApplyVisual()
    {
        if (sr == null || !fadeWhileLit) return;
        Color c = baseColour;
        c.a = IsLit ? litAlpha : baseColour.a;
        sr.color = c;
    }

    void RestoreBehaviour()
    {
        if (chase != null) chase.enabled = true;
        if (floater != null) floater.enabled = true;
        damageAccumulator = 0f;
    }
}