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

namespace IStalk.Eye
{
    public class TrapInstance : NetworkBehaviour
    {
        private readonly SyncVar<string> _trapId = new();
        private readonly SyncVar<bool> _isArmed = new();
        private readonly SyncVar<bool> _isTriggered = new();

        private TrapData_SO _data;
        private float _armTimer;
        private float _effectTimer;

        public override void OnStartServer()
        {
            base.OnStartServer();
            _armTimer = 0;
        }

        public override void OnStartClient()
        {
            base.OnStartClient();
            _trapId.OnChange += OnTrapIdChanged;
            _isTriggered.OnChange += OnTriggeredChanged;
            CacheData();
        }

        [Server]
        public void Initialize(string trapId)
        {
            _trapId.Value = trapId;
            CacheData();
        }

        private void CacheData()
        {
            if (string.IsNullOrEmpty(_trapId.Value)) return;
            _data = ItemDatabase.Instance.GetTrap(_trapId.Value);
        }

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

            if (!_isArmed.Value)
            {
                _armTimer += Time.deltaTime;
                if (_armTimer >= _data.armDelay)
                    _isArmed.Value = true;
                return;
            }

            if (_isTriggered.Value)
            {
                _effectTimer -= Time.deltaTime;
                if (_effectTimer <= 0)
                    ServerManager.Despawn(NetworkObject);
                return;
            }

            CheckTrigger();
        }

        [Server]
        private void CheckTrigger()
        {
            var colliders = Physics.OverlapSphere(transform.position, _data.triggerRadius);
            foreach (var col in colliders)
            {
                var runner = col.GetComponentInParent<RunnerController>();
                if (runner == null) continue;

                _isTriggered.Value = true;
                _effectTimer = _data.effectDuration;
                ApplyEffect(runner);
                TriggerVfxObservers();
                break;
            }
        }

        [Server]
        private void ApplyEffect(RunnerController runner)
        {
            switch (_data.effectType)
            {
                case TrapEffectType.NoiseEmit:
                    var noise = runner.GetComponent<NoiseEmitter>();
                    if (noise != null)
                        noise.EmitNoise(transform.position, _data.effectRadius, _data.effectIntensity * 5f);
                    break;
                case TrapEffectType.RevealPosition:
                    break;
            }
        }

        [ObserversRpc]
        private void TriggerVfxObservers()
        {
            if (_data == null) return;
            if (_data.triggerSound != null)
                AudioSource.PlayClipAtPoint(_data.triggerSound, transform.position);
            if (_data.triggerVfxPrefab != null)
                Instantiate(_data.triggerVfxPrefab, transform.position, Quaternion.identity);
        }

        private void OnTrapIdChanged(string prev, string next, bool asServer)
        {
            CacheData();
        }

        private void OnTriggeredChanged(bool prev, bool next, bool asServer)
        {
            if (next && _data != null && _data.revealsToRunners)
            {
                var renderers = GetComponentsInChildren<Renderer>();
                foreach (var r in renderers)
                    r.enabled = true;
            }
        }
    }
}
