using System.Collections;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;

/// <summary>
/// GAME 1303 Tier 2 — Press Attack, swing, hurt what's in front of you.
///
/// SETUP
///  1. Add to the player root (needs PlayerInput with Send Messages — the default
///     actions asset already has an "Attack" action in the Player map).
///  2. Make a child "AttackHitbox" with a trigger collider + Hitbox (Target Team = Enemy),
///     placed in front of the character. DISABLE the child. Drag it into Hitbox.
///     Because it's a child, it flips with the player automatically.
///  3. Timing: Windup = frames before the hitbox turns on, Active = how long it's on,
///     Recovery = time before you can attack again. Match these to your animation.
///  4. Animator: add an "Attack" trigger (PlayerAnimatorBridge doesn't need changes).
///  5. Optional: instead of timers, call EnableHitbox()/DisableHitbox() from
///     Animation Events on the swing clip for frame-perfect hits — set Use Animation Events.
///
/// Enemies can use this too: set Player Controlled = false and call Attack() from AI
/// (EnemyChase does this when in range).
/// </summary>
public class MeleeAttack : MonoBehaviour
{
    public bool playerControlled = true;

    [Header("Hitbox")]
    public Hitbox hitbox;

    [Header("Timing (seconds)")]
    public float windup = 0.08f;
    public float active = 0.12f;
    public float recovery = 0.2f;
    [Tooltip("If ON, hitbox is driven by Animation Events calling EnableHitbox/DisableHitbox.")]
    public bool useAnimationEvents = false;

    [Header("Feel")]
    [Tooltip("Freeze horizontal movement while attacking (grounded only).")]
    public bool stopWhileAttacking = true;
    public string animatorTrigger = "Attack";
    public string sfxName = "swing";

    [Header("Events")]
    public UnityEvent OnAttackStarted;

    public bool IsAttacking { get; private set; }

    private Animator anim;
    private PlayerController2D controller;
    private Rigidbody2D rb;
    private Knockback knockback;

    void Awake()
    {
        anim = GetComponent<Animator>();
        controller = GetComponent<PlayerController2D>();
        rb = GetComponent<Rigidbody2D>();
        knockback = GetComponent<Knockback>();
        if (hitbox != null) hitbox.gameObject.SetActive(false);
    }

    // Input System message (PlayerInput -> Send Messages)
    void OnAttack(InputValue value)
    {
        if (!playerControlled || !value.isPressed) return;
        if (controller != null && !controller.InputEnabled) return;
        Attack();
    }

    /// <summary>Start a swing if not already attacking. Safe to call from AI or UI.</summary>
    public bool Attack()
    {
        if (IsAttacking) return false;
        if (knockback != null && knockback.IsStunned) return false;
        StartCoroutine(AttackRoutine());
        return true;
    }

    IEnumerator AttackRoutine()
    {
        IsAttacking = true;
        OnAttackStarted?.Invoke();
        if (anim != null && !string.IsNullOrEmpty(animatorTrigger)) anim.SetTrigger(animatorTrigger);
        if (!string.IsNullOrEmpty(sfxName)) AudioManager.Instance?.PlaySFX(sfxName);

        if (stopWhileAttacking && rb != null && (controller == null || controller.IsGrounded))
            rb.linearVelocity = new Vector2(0f, rb.linearVelocity.y);

        if (useAnimationEvents)
        {
            // Animation events handle the hitbox; we just wait out the total time
            yield return new WaitForSeconds(windup + active + recovery);
        }
        else
        {
            yield return new WaitForSeconds(windup);
            EnableHitbox();
            yield return new WaitForSeconds(active);
            DisableHitbox();
            yield return new WaitForSeconds(recovery);
        }
        IsAttacking = false;
    }

    // Public so Animation Events can call them
    public void EnableHitbox()  { if (hitbox != null) hitbox.gameObject.SetActive(true); }
    public void DisableHitbox() { if (hitbox != null) hitbox.gameObject.SetActive(false); }
}