using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;

/// <summary>
/// GAME 1303 Tier 2 — Spawns Projectiles from a fire point.
///
/// SETUP
///  1. Add to the shooter's root. Create an empty child "FirePoint" at the muzzle /
///     hand and drag it in. Assign a Projectile prefab.
///  2. Team: Player for the player, Enemy for enemies (so bullets don't hit the owner).
///  3. Mode:
///       PlayerInput  – fires on the Input System "Attack" action (Send Messages).
///                      If the player ALSO has MeleeAttack on "Attack", set one of them
///                      to Manual and call it from a different action.
///       AutoFire     – fires every Fire Rate seconds (turrets, bosses, sorcerer NPC).
///       Manual       – only when something calls Fire() (BossController, EnemyChase).
///  4. Direction: Facing uses the owner's X scale (flips with PlayerController2D);
///     TowardPlayer aims at the Player tag (enemy shooters); FirePointRight uses
///     the fire point's own right vector (rotate the FirePoint to aim).
/// </summary>
public class ProjectileShooter : MonoBehaviour
{
    public enum Mode { PlayerInput, AutoFire, Manual }
    public enum AimMode { Facing, TowardPlayer, FirePointRight }

    public Projectile projectilePrefab;
    public Transform firePoint;
    public Team team = Team.Player;
    public Mode mode = Mode.PlayerInput;
    public AimMode aim = AimMode.Facing;

    [Tooltip("Minimum seconds between shots.")]
    public float fireRate = 0.3f;
    [Tooltip("Shots per press (3 = burst). Spread is degrees between them.")]
    public int shotsPerFire = 1;
    public float spreadDegrees = 0f;

    [Header("Feel")]
    public string animatorTrigger = "Shoot";
    public string sfxName = "shoot";
    public UnityEvent OnFired;

    private float cooldown;
    private Animator anim;
    private ComboCounter combo;
    private Transform player;

    void Awake()
    {
        anim = GetComponent<Animator>();
        combo = GetComponent<ComboCounter>();
        if (firePoint == null) firePoint = transform;
    }

    void Update()
    {
        cooldown -= Time.deltaTime;
        if (mode == Mode.AutoFire && cooldown <= 0f) Fire();
    }

    void OnAttack(InputValue value)
    {
        if (mode != Mode.PlayerInput || !value.isPressed) return;
        Fire();
    }

    /// <summary>Fire if off cooldown. Returns true if a shot was fired.</summary>
    public bool Fire()
    {
        if (cooldown > 0f || projectilePrefab == null) return false;
        cooldown = fireRate;

        Vector2 dir = GetAimDirection();
        float startAngle = -spreadDegrees * (shotsPerFire - 1) / 2f;
        for (int i = 0; i < shotsPerFire; i++)
        {
            float angle = startAngle + spreadDegrees * i;
            Vector2 d = Quaternion.Euler(0, 0, angle) * dir;
            Projectile p = Instantiate(projectilePrefab, firePoint.position, Quaternion.identity);
            p.Launch(d, team, team == Team.Player ? combo : null);
        }

        if (anim != null && !string.IsNullOrEmpty(animatorTrigger)) anim.SetTrigger(animatorTrigger);
        if (!string.IsNullOrEmpty(sfxName)) AudioManager.Instance?.PlaySFX(sfxName);
        OnFired?.Invoke();
        return true;
    }

    Vector2 GetAimDirection()
    {
        switch (aim)
        {
            case AimMode.TowardPlayer:
                if (player == null)
                {
                    var p = GameObject.FindGameObjectWithTag("Player");
                    if (p != null) player = p.transform;
                }
                if (player != null) return (player.position - firePoint.position).normalized;
                goto case AimMode.Facing;

            case AimMode.FirePointRight:
                return firePoint.right;

            default: // Facing — sign of X scale
                return transform.lossyScale.x >= 0f ? Vector2.right : Vector2.left;
        }
    }
}