using FishNet.Object;
using UnityEngine;
using IStalk.Props;

namespace IStalk.Eye
{
    public class EyeIncarnationController : NetworkBehaviour
    {
        [SerializeField] private LayerMask _propLayer;
        [SerializeField] private float _maxIncarnateRange = 50f;

        private DreadEconomy _dread;
        private IncarnationProp _currentProp;
        private bool _isIncarnating;

        public bool IsIncarnating => _isIncarnating;
        public IncarnationProp CurrentProp => _currentProp;

        public override void OnStartClient()
        {
            base.OnStartClient();
            if (!IsOwner)
            {
                enabled = false;
                return;
            }
        }

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

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

            if (_isIncarnating)
            {
                HandleIncarnatedInput();
            }
            else
            {
                HandleSelectionInput();
            }
        }

        private void HandleSelectionInput()
        {
            if (Input.GetKeyDown(KeyCode.Q))
            {
                Vector3 worldPos = GetMouseWorldPosition();
                ServerTryIncarnate(worldPos);
            }
        }

        private void HandleIncarnatedInput()
        {
            if (Input.GetKeyDown(KeyCode.Q) || Input.GetKeyDown(KeyCode.Escape))
            {
                ServerEndIncarnation();
                return;
            }

            float h = Input.GetAxisRaw("Horizontal");
            float v = Input.GetAxisRaw("Vertical");
            if (Mathf.Abs(h) > 0.01f || Mathf.Abs(v) > 0.01f)
            {
                Vector3 dir = new Vector3(h, 0, v).normalized;
                ServerMoveProp(dir);
            }
        }

        [ServerRpc]
        private void ServerTryIncarnate(Vector3 targetPos)
        {
            Collider[] hits = Physics.OverlapSphere(targetPos, 3f, _propLayer);
            IncarnationProp nearest = null;
            float minDist = float.MaxValue;

            foreach (var hit in hits)
            {
                var prop = hit.GetComponent<IncarnationProp>();
                if (prop == null || prop.IsIncarnated) continue;

                float dist = Vector3.Distance(targetPos, prop.transform.position);
                if (dist < minDist)
                {
                    minDist = dist;
                    nearest = prop;
                }
            }

            if (nearest == null) return;

            if (nearest.TryIncarnate(_dread))
            {
                _currentProp = nearest;
                _isIncarnating = true;
                NotifyIncarnateStateObservers(true);
            }
        }

        [ServerRpc]
        private void ServerMoveProp(Vector3 direction)
        {
            if (_currentProp == null || !_currentProp.IsIncarnated) return;
            _currentProp.MoveIncarnated(direction);
        }

        [ServerRpc]
        private void ServerEndIncarnation()
        {
            if (_currentProp != null)
            {
                _currentProp.EndIncarnation();
                _currentProp = null;
            }
            _isIncarnating = false;
            NotifyIncarnateStateObservers(false);
        }

        [ObserversRpc]
        private void NotifyIncarnateStateObservers(bool incarnating)
        {
            _isIncarnating = incarnating;
        }

        private Vector3 GetMouseWorldPosition()
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            Plane groundPlane = new(Vector3.up, Vector3.zero);
            if (groundPlane.Raycast(ray, out float dist))
                return ray.GetPoint(dist);
            return Vector3.zero;
        }
    }
}
