using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;

namespace Northbound
{
    /// <summary>
    /// 플레이어가 월드의 오브젝트와 상호작용하는 시스템
    /// </summary>
    public class PlayerInteraction : NetworkBehaviour
    {
        [Header("Interaction Settings")]
        public float interactionRange = 3f;
        public LayerMask interactableLayer = ~0;
        
        [Header("Detection")]
        public Transform rayOrigin;
        public bool useForwardDirection = true;
        
        [Header("Animation")]
        public bool playAnimations = true;
        public bool useAnimationEvents = true;
        public bool blockDuringAnimation = true;
        
        [Header("Equipment")]
        public bool useEquipment = true;
        
        [Header("Debug")]
        public bool showDebugRay = true;

        private PlayerInputActions _inputActions;
        private IInteractable _currentInteractable;
        private Camera _mainCamera;
        private Animator _animator;
        private EquipmentSocket _equipmentSocket;
        
        private InteractionEquipmentData _pendingEquipmentData;
        private string _currentEquipmentSocket;
        private bool _isInteracting = false;

        public override void OnNetworkSpawn()
        {
            if (!IsOwner) return;

            _mainCamera = Camera.main;
            _animator = GetComponent<Animator>();
            _equipmentSocket = GetComponent<EquipmentSocket>();
            
            if (rayOrigin == null)
                rayOrigin = transform;

            _inputActions = new PlayerInputActions();
            _inputActions.Player.Interact.performed += OnInteract;
            _inputActions.Enable();
        }

        public override void OnNetworkDespawn()
        {
            if (IsOwner && _inputActions != null)
            {
                _inputActions.Player.Interact.performed -= OnInteract;
                _inputActions.Disable();
                _inputActions.Dispose();
            }
        }

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

        private void DetectInteractable()
        {
            Vector3 origin = rayOrigin.position;
            Vector3 direction = useForwardDirection ? transform.forward : _mainCamera.transform.forward;
            
            Ray ray = new Ray(origin, direction);

            if (showDebugRay)
            {
                Debug.DrawRay(ray.origin, ray.direction * interactionRange, 
                    _currentInteractable != null ? Color.green : Color.yellow);
            }

            if (Physics.Raycast(ray, out RaycastHit hit, interactionRange, interactableLayer))
            {
                IInteractable interactable = hit.collider.GetComponent<IInteractable>();
                
                if (interactable == null)
                    interactable = hit.collider.GetComponentInParent<IInteractable>();

                if (interactable != null && interactable.CanInteract(OwnerClientId))
                {
                    _currentInteractable = interactable;
                    return;
                }
            }

            _currentInteractable = null;
        }

        private void OnInteract(InputAction.CallbackContext context)
        {
            if (blockDuringAnimation && _isInteracting)
                return;

            if (_currentInteractable != null)
            {
                _isInteracting = true;
                _pendingEquipmentData = _currentInteractable.GetEquipmentData();

                if (!useAnimationEvents && useEquipment && _equipmentSocket != null && _pendingEquipmentData != null)
                {
                    if (_pendingEquipmentData.attachOnStart && _pendingEquipmentData.equipmentPrefab != null)
                    {
                        AttachEquipment();
                        
                        if (_pendingEquipmentData.detachOnEnd)
                        {
                            StartCoroutine(DetachEquipmentAfterDelay(2f));
                        }
                    }
                }

                if (playAnimations && _animator != null)
                {
                    string animTrigger = _currentInteractable.GetInteractionAnimation();
                    if (!string.IsNullOrEmpty(animTrigger))
                    {
                        _animator.SetTrigger(animTrigger);
                    }
                }

                _currentInteractable.Interact(OwnerClientId);
            }
        }

        // ========================================
        // Animation Event 함수들
        // ========================================

        public void OnEquipTool()
        {
            if (!useAnimationEvents || !useEquipment) return;
            AttachEquipment();
        }

        public void OnEquipTool(string socketName)
        {
            if (!useAnimationEvents || !useEquipment) return;
            AttachEquipment(socketName);
        }

        public void OnUnequipTool()
        {
            if (!useAnimationEvents || !useEquipment) return;
            DetachEquipment();
        }

        public void OnUnequipTool(string socketName)
        {
            if (!useAnimationEvents || !useEquipment) return;
            DetachEquipment(socketName);
        }

        public void OnInteractionComplete()
        {
            _isInteracting = false;
        }

        // ========================================
        // 내부 헬퍼 함수들
        // ========================================

        private void AttachEquipment(string socketName = null)
        {
            if (_equipmentSocket == null || _pendingEquipmentData == null)
                return;

            if (_pendingEquipmentData.equipmentPrefab == null)
                return;

            string socket = socketName ?? _pendingEquipmentData.socketName;
            _equipmentSocket.AttachToSocket(socket, _pendingEquipmentData.equipmentPrefab);
            _currentEquipmentSocket = socket;
        }

        private void DetachEquipment(string socketName = null)
        {
            if (_equipmentSocket == null)
                return;

            string socket = socketName ?? _currentEquipmentSocket;
            
            if (!string.IsNullOrEmpty(socket))
            {
                _equipmentSocket.DetachFromSocket(socket);
                
                if (socket == _currentEquipmentSocket)
                    _currentEquipmentSocket = null;
            }
        }

        private System.Collections.IEnumerator DetachEquipmentAfterDelay(float delay)
        {
            yield return new WaitForSeconds(delay);
            DetachEquipment();
            
            if (!useAnimationEvents)
            {
                _isInteracting = false;
            }
        }

        private void OnGUI()
        {
            if (!IsOwner || _currentInteractable == null) return;

            GUIStyle style = new GUIStyle(GUI.skin.label)
            {
                fontSize = 24,
                alignment = TextAnchor.MiddleCenter
            };
            style.normal.textColor = Color.white;

            string prompt = _currentInteractable.GetInteractionPrompt();
            
            if (_isInteracting)
            {
                prompt += " (진행 중...)";
                style.normal.textColor = Color.yellow;
            }

            GUI.Label(new Rect(Screen.width / 2 - 200, Screen.height - 100, 400, 50), prompt, style);
        }

        private void OnDestroy()
        {
            if (_inputActions != null)
            {
                _inputActions.Dispose();
            }
        }
    }
}