using FishNet.Object;
using UnityEngine;
using IStalk.Data;
using IStalk.Shared;

namespace IStalk.Runner
{
    public class RunnerFootsteps : NetworkBehaviour
    {
        [SerializeField] private float _stepInterval = 0.45f;
        [SerializeField] private float _sprintStepInterval = 0.3f;
        [SerializeField] private float _walkNoiseRadius = 3f;
        [SerializeField] private float _sprintNoiseRadius = 8f;
        [SerializeField] private float _landNoiseRadius = 12f;
        [SerializeField] private AudioClip[] _footstepClips;
        [SerializeField] private AudioClip _landClip;

        private CharacterController _cc;
        private RunnerController _runner;
        private NoiseEmitter _noise;
        private float _stepTimer;
        private bool _wasGrounded;

        public override void OnStartServer()
        {
            base.OnStartServer();
            _cc = GetComponent<CharacterController>();
            _runner = GetComponent<RunnerController>();
            _noise = GetComponent<NoiseEmitter>();
        }

        private void Update()
        {
            if (!IsServerStarted) return;
            if (_cc == null) return;

            bool grounded = _cc.isGrounded;
            float hSpeed = new Vector2(_cc.velocity.x, _cc.velocity.z).magnitude;

            if (!_wasGrounded && grounded && _cc.velocity.y < -5f)
            {
                float intensity = Mathf.Abs(_cc.velocity.y) * 0.1f;
                _noise.EmitNoise(transform.position, _landNoiseRadius, intensity);
                PlayFootstepObservers(true);
            }
            _wasGrounded = grounded;

            if (!grounded || hSpeed < 0.5f) return;

            bool sprinting = _runner != null && _runner.GetMoveState() == RunnerController.MoveState.Normal && hSpeed > 6f;
            float interval = sprinting ? _sprintStepInterval : _stepInterval;

            _stepTimer += Time.deltaTime;
            if (_stepTimer >= interval)
            {
                _stepTimer = 0;
                float radius = sprinting ? _sprintNoiseRadius : _walkNoiseRadius;
                float intensity = sprinting ? 1.5f : 0.5f;
                _noise.EmitNoise(transform.position, radius, intensity);
                PlayFootstepObservers(false);
            }
        }

        [ObserversRpc]
        private void PlayFootstepObservers(bool isLand)
        {
            AudioClip clip;
            if (isLand)
            {
                clip = _landClip;
            }
            else
            {
                if (_footstepClips == null || _footstepClips.Length == 0) return;
                clip = _footstepClips[Random.Range(0, _footstepClips.Length)];
            }
            if (clip != null)
                AudioSource.PlayClipAtPoint(clip, transform.position, 0.5f);
        }
    }
}
