using UnityEngine;

/// <summary>
/// GAME 1303 Tier 2 — Ghosts, bees, flying roaches. Ignores gravity, bobs gently,
/// drifts along a path.
///
/// SETUP
///  1. Sprite + Rigidbody2D (Gravity Scale 0, Freeze Rotation Z) + Collider2D + Health
///     + this script. Hurtbox child (Team = Enemy). To hurt the player on touch add
///     DamageOnContact or an always-on Hitbox.
///  2. Path:
///       Hover      – stays put, just bobs (Commission Witch's ghost that "moves around
///                    but don't touch it" works well as Hover with a big bob).
///       Waypoints  – drifts through a list of Transforms (loop).
///       Wander     – picks random points within Wander Radius of its start.
///  3. Combine with EnemyChase (Movement = Free) for a ghost that hovers until it
///     notices you — this script yields while EnemyChase.IsChasing is true.
/// </summary>
[RequireComponent(typeof(Rigidbody2D))]
public class FloatingEnemy : MonoBehaviour
{
    public enum Path { Hover, Waypoints, Wander }

    public Path path = Path.Hover;
    public float speed = 1.5f;

    [Header("Bob")]
    public float bobHeight = 0.25f;
    public float bobSpeed = 2f;

    [Header("Waypoints")]
    public Transform[] waypoints;

    [Header("Wander")]
    public float wanderRadius = 3f;
    public float repickEvery = 2f;

    [Header("Facing")]
    public bool flipToFaceDirection = true;
    public bool artFacesRight = true;

    private Rigidbody2D rb;
    private EnemyChase chase;
    private Knockback knockback;
    private Vector2 startPos;
    private Vector2 target;
    private int wpIndex;
    private float repickTimer;
    private float bobPhase;
    private bool facingRight;

    void Awake()
    {
        rb = GetComponent<Rigidbody2D>();
        rb.gravityScale = 0f;
        chase = GetComponent<EnemyChase>();
        knockback = GetComponent<Knockback>();
        facingRight = artFacesRight ? transform.localScale.x > 0 : transform.localScale.x < 0;
        bobPhase = Random.value * Mathf.PI * 2f;   // so groups don't bob in sync
    }

    void Start()
    {
        startPos = rb.position;
        PickTarget();
    }

    void FixedUpdate()
    {
        if (chase != null && chase.IsChasing) return;
        if (knockback != null && knockback.IsStunned) return;

        bobPhase += bobSpeed * Time.fixedDeltaTime;
        float bobVel = Mathf.Cos(bobPhase) * bobHeight * bobSpeed;   // derivative of sin bob

        Vector2 vel = Vector2.zero;
        if (path != Path.Hover)
        {
            Vector2 toTarget = target - rb.position;
            if (toTarget.magnitude < 0.15f) PickTarget();
            else vel = toTarget.normalized * speed;

            if (path == Path.Wander)
            {
                repickTimer -= Time.fixedDeltaTime;
                if (repickTimer <= 0f) PickTarget();
            }
        }

        rb.linearVelocity = new Vector2(vel.x, vel.y + bobVel);

        if (flipToFaceDirection && Mathf.Abs(vel.x) > 0.05f)
        {
            bool right = vel.x > 0f;
            if (right != facingRight)
            {
                facingRight = right;
                Vector3 s = transform.localScale; s.x *= -1f; transform.localScale = s;
            }
        }
    }

    void PickTarget()
    {
        switch (path)
        {
            case Path.Waypoints:
                if (waypoints == null || waypoints.Length == 0) { target = startPos; return; }
                wpIndex = (wpIndex + 1) % waypoints.Length;
                target = waypoints[wpIndex].position;
                break;
            case Path.Wander:
                target = startPos + Random.insideUnitCircle * wanderRadius;
                repickTimer = repickEvery;
                break;
            default:
                target = startPos;
                break;
        }
    }

    void OnDrawGizmosSelected()
    {
        if (path == Path.Wander)
        {
            Gizmos.color = Color.cyan;
            Gizmos.DrawWireSphere(Application.isPlaying ? (Vector3)startPos : transform.position, wanderRadius);
        }
    }
}