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

namespace IStalk.Eye
{
    public class EyeScanAbility : NetworkBehaviour
    {
        [SerializeField] private float _scanCost = 25f;
        [SerializeField] private float _scanDuration = 3f;
        [SerializeField] private float _scanCooldown = 15f;
        [SerializeField] private float _scanRadius = 20f;

        private readonly SyncVar<bool> _isScanning = new();
        private readonly SyncVar<float> _cooldownRemaining = new();

        private DreadEconomy _dread;
        private float _scanTimer;
        private float _cooldownMultiplier = 1f;
        private float _radiusMultiplier = 1f;

        public void ApplyTypeModifiers(float cooldownMult, float radiusMult)
        {
            _cooldownMultiplier = cooldownMult;
            _radiusMultiplier = radiusMult;
        }

        public bool IsScanning => _isScanning.Value;
        public float CooldownRemaining => _cooldownRemaining.Value;
        public float ScanRadius => _scanRadius * _radiusMultiplier;

        public event System.Action OnScanStarted;
        public event System.Action OnScanEnded;

        public override void OnStartServer()
        {
            base.OnStartServer();
            _dread = GetComponent<DreadEconomy>();
        }

        public override void OnStartClient()
        {
            base.OnStartClient();
            _isScanning.OnChange += OnScanChanged;
        }

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

            if (_cooldownRemaining.Value <= 0 && Input.GetKeyDown(KeyCode.Space))
                ServerStartScan();

            if (!IsServerStarted) return;

            if (_cooldownRemaining.Value > 0)
                _cooldownRemaining.Value -= Time.deltaTime;

            if (_isScanning.Value)
            {
                _scanTimer -= Time.deltaTime;
                if (_scanTimer <= 0)
                {
                    _isScanning.Value = false;
                    _cooldownRemaining.Value = _scanCooldown * _cooldownMultiplier;
                }
            }
        }

        [ServerRpc]
        private void ServerStartScan()
        {
            if (_isScanning.Value) return;
            if (_cooldownRemaining.Value > 0) return;
            if (!_dread.TrySpend(_scanCost)) return;

            _isScanning.Value = true;
            _scanTimer = _scanDuration;

            if (LoSManager.Instance != null)
                LoSManager.Instance.RevealAllRunners(_scanDuration);

            ScanPulseObservers(transform.position);
        }

        [ObserversRpc]
        private void ScanPulseObservers(Vector3 position)
        {
            OnScanStarted?.Invoke();
        }

        private void OnScanChanged(bool prev, bool next, bool asServer)
        {
            if (next) OnScanStarted?.Invoke();
            else OnScanEnded?.Invoke();
        }
    }
}
