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

namespace IStalk.Runner
{
    public class RunnerCoopActions : NetworkBehaviour
    {
        private PlayerInventory _inventory;
        private RunnerController _controller;
        private RunnerHealth _health;
        private float _boostCooldown;

        private GlobalRules_SO Rules => GlobalRules_SO.Instance;

        public override void OnStartClient()
        {
            base.OnStartClient();
            if (!IsOwner)
            {
                enabled = false;
                return;
            }
            _inventory = GetComponent<PlayerInventory>();
            _controller = GetComponent<RunnerController>();
            _health = GetComponent<RunnerHealth>();
        }

        private void Update()
        {
            if (!IsOwner) return;
            if (_health != null && _health.IsDown) return;

            _boostCooldown -= Time.deltaTime;

            if (Input.GetKeyDown(KeyCode.F))
                TryBoost();

            if (Input.GetKey(KeyCode.G))
                TryThrowItem();
        }

        private void TryBoost()
        {
            if (_boostCooldown > 0) return;

            var colliders = Physics.OverlapSphere(transform.position, Rules.boostRange);
            foreach (var col in colliders)
            {
                if (col.gameObject == gameObject) continue;
                var otherController = col.GetComponentInParent<RunnerController>();
                if (otherController == null) continue;
                var otherHealth = col.GetComponentInParent<RunnerHealth>();
                if (otherHealth != null && otherHealth.IsDown) continue;

                if (IsCrouchingNearWall(otherController))
                {
                    ServerRequestBoost(otherController.NetworkObject);
                    _boostCooldown = 1f;
                    return;
                }
            }
        }

        private bool IsCrouchingNearWall(RunnerController other)
        {
            Vector3 pos = other.transform.position;
            return Physics.Raycast(pos, other.transform.forward, 1.2f) ||
                   Physics.Raycast(pos, -other.transform.forward, 1.2f) ||
                   Physics.Raycast(pos, other.transform.right, 1.2f) ||
                   Physics.Raycast(pos, -other.transform.right, 1.2f);
        }

        [ServerRpc]
        private void ServerRequestBoost(NetworkObject booster)
        {
            if (booster == null) return;
            var boosterHealth = booster.GetComponent<RunnerHealth>();
            if (boosterHealth != null && boosterHealth.IsDown) return;

            float dist = Vector3.Distance(transform.position, booster.transform.position);
            if (dist > Rules.boostRange * 1.5f) return;

            var cc = GetComponent<CharacterController>();
            if (cc != null)
                cc.Move(Vector3.up * Rules.boostHeight);

            BoostVfxObservers(transform.position);
        }

        [ObserversRpc]
        private void BoostVfxObservers(Vector3 position)
        {
            // VFX/SFX hook for boost effect
        }

        private void TryThrowItem()
        {
            if (_inventory == null) return;
            var items = _inventory.GetItems();
            if (items.Count == 0) return;

            var target = FindThrowTarget();
            if (target == null) return;

            string lastItem = items[items.Count - 1];
            ServerThrowItem(lastItem, target.NetworkObject);
        }

        private RunnerController FindThrowTarget()
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out RaycastHit hit, 30f))
            {
                var runner = hit.collider.GetComponentInParent<RunnerController>();
                if (runner != null && runner.gameObject != gameObject)
                {
                    float dist = Vector3.Distance(transform.position, runner.transform.position);
                    if (dist <= Rules.throwRangeBase)
                        return runner;
                }
            }

            var colliders = Physics.OverlapSphere(transform.position, Rules.throwRangeBase);
            RunnerController closest = null;
            float closestDist = float.MaxValue;

            foreach (var col in colliders)
            {
                if (col.gameObject == gameObject) continue;
                var runner = col.GetComponentInParent<RunnerController>();
                if (runner == null) continue;
                var health = col.GetComponentInParent<RunnerHealth>();
                if (health != null && health.IsDown) continue;

                float d = Vector3.Distance(transform.position, runner.transform.position);
                if (d < closestDist)
                {
                    closestDist = d;
                    closest = runner;
                }
            }
            return closest;
        }

        [ServerRpc]
        private void ServerThrowItem(string itemId, NetworkObject target)
        {
            if (target == null) return;
            if (!_inventory.Contains(itemId)) return;

            float dist = Vector3.Distance(transform.position, target.transform.position);

            var itemData = ItemDatabase.Instance.GetLootItem(itemId);
            float maxRange = Rules.throwRangeBase;
            if (itemData != null)
                maxRange -= itemData.weight * Rules.throwRangeWeightScale;

            if (dist > maxRange * 1.5f) return;

            _inventory.TryRemoveItem(itemId);

            var targetInventory = target.GetComponent<PlayerInventory>();
            if (targetInventory != null && targetInventory.HasSpace)
            {
                targetInventory.TryAddItem(itemId);
            }
            else
            {
                WorldItem.SpawnWorldItem(itemId, target.transform.position + Vector3.up * 0.5f);
            }

            ThrowVfxObservers(transform.position, target.transform.position);
        }

        [ObserversRpc]
        private void ThrowVfxObservers(Vector3 from, Vector3 to)
        {
            // VFX/SFX hook for throw arc
        }
    }
}
