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

namespace IStalk.Runner
{
    public class RunnerHealth : NetworkBehaviour
    {
        [SerializeField] private int _maxHits = 3;
        [SerializeField] private float _invulnerabilityDuration = 2f;
        [SerializeField] private float _slowDuration = 3f;
        [SerializeField] private float _slowMultiplier = 0.5f;

        private readonly SyncVar<int> _hitsTaken = new();
        private readonly SyncVar<bool> _isDown = new();
        private readonly SyncVar<bool> _isInvulnerable = new();

        private float _invulnTimer;
        private float _slowTimer;

        public int HitsTaken => _hitsTaken.Value;
        public int MaxHits => _maxHits;
        public bool IsDown => _isDown.Value;
        public bool IsInvulnerable => _isInvulnerable.Value;
        public bool IsSlowed => _slowTimer > 0;
        public float SlowMultiplier => IsSlowed ? _slowMultiplier : 1f;

        public event System.Action OnHit;
        public event System.Action OnDowned;
        public event System.Action OnRevived;

        public override void OnStartNetwork()
        {
            base.OnStartNetwork();
            _hitsTaken.OnChange += (prev, next, asServer) => OnHit?.Invoke();
            _isDown.OnChange += HandleDownStateChanged;
        }

        [Server]
        public void TakeHit()
        {
            if (_isInvulnerable.Value || _isDown.Value) return;

            _hitsTaken.Value++;
            _isInvulnerable.Value = true;
            _invulnTimer = _invulnerabilityDuration;
            _slowTimer = _slowDuration;

            if (_hitsTaken.Value >= _maxHits)
            {
                _isDown.Value = true;
                var inventory = GetComponent<PlayerInventory>();
                if (inventory != null)
                    inventory.DropAll(transform.position);
            }

            HitFeedbackObservers();
        }

        [Server]
        public void Revive()
        {
            if (!_isDown.Value) return;
            _isDown.Value = false;
            _hitsTaken.Value = Mathf.Max(0, _hitsTaken.Value - 1);
        }

        private void Update()
        {
            if (!IsServerStarted) return;

            if (_invulnTimer > 0)
            {
                _invulnTimer -= Time.deltaTime;
                if (_invulnTimer <= 0)
                    _isInvulnerable.Value = false;
            }

            if (_slowTimer > 0)
                _slowTimer -= Time.deltaTime;
        }

        [ObserversRpc]
        private void HitFeedbackObservers()
        {
            OnHit?.Invoke();
        }

        private void HandleDownStateChanged(bool prev, bool next, bool asServer)
        {
            if (next) OnDowned?.Invoke();
            else OnRevived?.Invoke();
        }
    }
}
