using UnityEngine;
using UnityEngine.EventSystems;

public class FurnitureController : MonoBehaviour
{
    public enum EditTool { Move, Rotate }

    [Header("Настройки")]
    public GameObject currentPrefab; 
    public LayerMask floorLayer;
    public LayerMask wallLayer; 
    public LayerMask furnitureLayer;

    [SerializeField] private GameObject shopPanel;

    [Header("Режим редактирования (UI)")]
    [SerializeField] private GameObject editPanel; 
    [SerializeField] private GameObject rotate90Button; 
    public float rotationSpeed = 5f;

    [Header("Связь с камерой")]
    public MonoBehaviour cameraController; 

    private GameObject _activeFurniture;
    private FurnitureObject _activeFurnitureScript; 
    private EditTool _currentTool = EditTool.Move;
    private Camera _cam;
    
    private bool _isInteracting = false;
    private Vector3 _lastInputPos; 
    private Vector3 _dragOffset; 

    private void Start()
    {
        _cam = Camera.main;
        if (cameraController == null && _cam != null)
            cameraController = _cam.GetComponent("CameraController") as MonoBehaviour;

        currentPrefab = null;
        editPanel.SetActive(false); 
        if (rotate90Button != null) rotate90Button.SetActive(false); 
    }

    void Update()
    {
        if (_activeFurniture != null)
        {
            HandleEditing();
        }
        else if (currentPrefab != null)
        {
            if (Input.GetMouseButtonDown(0) && !shopPanel.activeSelf && !IsPointerOverUI())
                TryPlaceFurniture();
        }
        else 
        {
            if (Input.GetMouseButtonDown(0) && !shopPanel.activeSelf && !IsPointerOverUI())
                TrySelectPlacedFurniture();
        }
    }

    private void HandleEditing()
    {
        if (Input.GetMouseButtonDown(0) && !IsPointerOverUI())
        {
            _lastInputPos = Input.mousePosition; 

            if (_currentTool == EditTool.Move)
            {
                Ray ray = _cam.ScreenPointToRay(Input.mousePosition);
                RaycastHit[] hits = Physics.SphereCastAll(ray, 0.5f, 100f);
                
                bool foundFurniture = false;
                foreach (var hit in hits)
                {
                    if (hit.transform.IsChildOf(_activeFurniture.transform) || hit.transform == _activeFurniture.transform)
                    {
                        foundFurniture = true;
                        break;
                    }
                }

                if (foundFurniture) 
                {
                    // Для пола считаем смещение, настенные предметы просто цепляем к курсору
                    if (!_activeFurnitureScript.isWallObject && Physics.Raycast(ray, out RaycastHit floorHit, 100f, floorLayer))
                    {
                        _dragOffset = _activeFurniture.transform.position - floorHit.point;
                        _dragOffset.y = 0; 
                    }
                    else _dragOffset = Vector3.zero;

                    StartInteraction();
                }
            }
            else if (_currentTool == EditTool.Rotate)
            {
                StartInteraction();
            }
        }

        if (Input.GetMouseButton(0) && _isInteracting)
        {
            Ray ray = _cam.ScreenPointToRay(Input.mousePosition);

            if (_currentTool == EditTool.Move)
            {
                // === ЛОГИКА ДЛЯ НАСТЕННЫХ ПРЕДМЕТОВ ===
                if (_activeFurnitureScript.isWallObject)
                {
                    if (Physics.Raycast(ray, out RaycastHit hit, 100f, wallLayer))
                    {
                        _activeFurniture.transform.position = hit.point;
                        // Магия: Поворачиваем объект "лицом" от стены
                        _activeFurniture.transform.rotation = Quaternion.LookRotation(hit.normal);
                    }
                }
                // === ЛОГИКА ДЛЯ НАПОЛЬНЫХ ПРЕДМЕТОВ (Старая) ===
                else
                {
                    if (Physics.Raycast(ray, out RaycastHit hit, 100f, floorLayer))
                    {
                        Vector3 currentPos = _activeFurniture.transform.position;
                        Vector3 targetPos = hit.point + _dragOffset;
                        targetPos.y = currentPos.y; 
                        
                        Vector3 moveDir = targetPos - currentPos;
                        float moveDist = moveDir.magnitude;

                        if (moveDist > 0.001f)
                        {
                            BoxCollider box = _activeFurniture.GetComponent<BoxCollider>();
                            if (box != null)
                            {
                                Vector3 center = _activeFurniture.transform.TransformPoint(box.center);
                                Vector3 halfExtents = Vector3.Scale(box.size, _activeFurniture.transform.lossyScale) * 0.49f;

                                if (Physics.BoxCast(center, halfExtents, moveDir.normalized, out RaycastHit wallHit, _activeFurniture.transform.rotation, moveDist, wallLayer))
                                {
                                    float safeDist = Mathf.Max(0f, wallHit.distance - 0.01f);
                                    Vector3 remainingMove = moveDir - (moveDir.normalized * safeDist);
                                    Vector3 slideMove = Vector3.ProjectOnPlane(remainingMove, wallHit.normal);

                                    if (slideMove.magnitude > 0.001f)
                                    {
                                        Vector3 newCenter = center + moveDir.normalized * safeDist;
                                        if (Physics.BoxCast(newCenter, halfExtents, slideMove.normalized, out RaycastHit slideHit, _activeFurniture.transform.rotation, slideMove.magnitude, wallLayer))
                                        {
                                            slideMove = slideMove.normalized * Mathf.Max(0f, slideHit.distance - 0.01f);
                                        }
                                    }

                                    targetPos = currentPos + (moveDir.normalized * safeDist) + slideMove;
                                }
                            }
                        }
                        targetPos.y = currentPos.y; 
                        _activeFurniture.transform.position = targetPos;
                    }
                }
            }
            else if (_currentTool == EditTool.Rotate)
            {
                float deltaX = Input.mousePosition.x - _lastInputPos.x;
                
                // Настенные предметы крутим вокруг своей оси Z (по циферблату), а напольные - вокруг мировой Y
                if (_activeFurnitureScript.isWallObject)
                    _activeFurniture.transform.Rotate(Vector3.forward, -deltaX * rotationSpeed * 0.2f, Space.Self);
                else
                    _activeFurniture.transform.Rotate(Vector3.up, -deltaX * rotationSpeed * 0.2f, Space.World);
            }
            
            _lastInputPos = Input.mousePosition;
        }

        if (Input.GetMouseButtonUp(0) && _isInteracting) EndInteraction();
        if (!_isInteracting) UpdateUIPosition();
    }

    private void TrySelectPlacedFurniture()
    {
        Ray ray = _cam.ScreenPointToRay(Input.mousePosition);
        if (Physics.Raycast(ray, out RaycastHit hit, 1000f, furnitureLayer, QueryTriggerInteraction.Collide))
        {
            FurnitureObject furnScript = hit.collider.GetComponentInParent<FurnitureObject>();
            if (furnScript != null)
            {
                _activeFurniture = furnScript.gameObject;
                _activeFurnitureScript = furnScript;
                _activeFurnitureScript.SetEditMode(true);
                
                _currentTool = EditTool.Move; 
                if (rotate90Button != null) rotate90Button.SetActive(false);

                _isInteracting = false;
                LockCamera(false); 
                UpdateUIPosition(); 
            }
        }
    }

    private void StartInteraction()
    {
        _isInteracting = true;
        if (editPanel.activeSelf) editPanel.SetActive(false);
        if (_currentTool == EditTool.Move) LockCamera(true);
    }

    private void EndInteraction()
    {
        _isInteracting = false;
        UpdateUIPosition(); 
        editPanel.SetActive(true);
        if (_currentTool == EditTool.Move) LockCamera(false);
    }

    private void UpdateUIPosition()
    {
        Vector3 screenPos = _cam.WorldToScreenPoint(_activeFurniture.transform.position);
        if (screenPos.z > 0) 
        {
            if (!editPanel.activeSelf) editPanel.SetActive(true);
            float yOffset = Screen.height * 0.15f; 
            float targetX = screenPos.x;
            float targetY = screenPos.y + yOffset;

            RectTransform rect = editPanel.GetComponent<RectTransform>();
            if (rect != null)
            {
                float paddingX = (rect.rect.width / 2f) * editPanel.transform.lossyScale.x;
                float paddingY = (rect.rect.height / 2f) * editPanel.transform.lossyScale.y;
                targetX = Mathf.Clamp(targetX, paddingX, Screen.width - paddingX);
                targetY = Mathf.Clamp(targetY, paddingY, Screen.height - paddingY);
            }
            editPanel.transform.position = new Vector3(targetX, targetY, editPanel.transform.position.z);
        }
        else if (editPanel.activeSelf) editPanel.SetActive(false);
    }

    void TryPlaceFurniture()
    {
        Ray ray = _cam.ScreenPointToRay(Input.mousePosition);
        
        // Определяем, куда пускать луч при установке в зависимости от типа предмета
        FurnitureObject prefabScript = currentPrefab.GetComponent<FurnitureObject>();
        LayerMask targetLayer = prefabScript.isWallObject ? wallLayer : floorLayer;

        if (Physics.Raycast(ray, out RaycastHit hit, 100f, targetLayer))
        {
            _activeFurniture = Instantiate(currentPrefab, hit.point, Quaternion.identity);
            
            // Если это стена - сразу поворачиваем спиной к ней
            if (prefabScript.isWallObject)
            {
                _activeFurniture.transform.rotation = Quaternion.LookRotation(hit.normal);
            }

            _activeFurnitureScript = _activeFurniture.GetComponent<FurnitureObject>(); 
            _activeFurnitureScript.SetEditMode(true);
            
            _currentTool = EditTool.Move; 
            if (rotate90Button != null) rotate90Button.SetActive(false);

            currentPrefab = null; 
            _isInteracting = false;
            LockCamera(false); 
            UpdateUIPosition(); 
        }
    }

    public void Rotate90Degrees()
    {
        if (_activeFurniture != null)
        {
            if (_activeFurnitureScript.isWallObject)
            {
                // Настенные объекты поворачиваем по их локальной оси Z (как часы)
                _activeFurniture.transform.Rotate(0, 0, 90f, Space.Self);
            }
            else
            {
                float currentY = _activeFurniture.transform.eulerAngles.y;
                float snappedY = Mathf.Round(currentY / 90f) * 90f;
                _activeFurniture.transform.rotation = Quaternion.Euler(0, snappedY + 90f, 0);
            }
        }
    }

    public void SelectMoveTool() { _currentTool = EditTool.Move; if (rotate90Button != null) rotate90Button.SetActive(false); LockCamera(false); }
    public void SelectRotateTool() { _currentTool = EditTool.Rotate; if (rotate90Button != null) rotate90Button.SetActive(true); LockCamera(true); }

    public void ConfirmPlacement()
    {
        if (_activeFurnitureScript != null && _activeFurnitureScript.IsPlacementValid)
        {
            _activeFurnitureScript.SetEditMode(false); 
            _activeFurniture = null;                   
            _activeFurnitureScript = null;
            editPanel.SetActive(false);
            LockCamera(false); 
        }
    }

    public void CancelPlacement()
    {
        if (_activeFurniture != null)
        {
            Destroy(_activeFurniture); 
            _activeFurniture = null;
            _activeFurnitureScript = null;
            editPanel.SetActive(false); 
            LockCamera(false); 
        }
    }

    public void SelectFurnitureAndCloseShop(GameObject prefabToSelect)
    {
        currentPrefab = prefabToSelect;
        shopPanel.SetActive(false);    
    }

    private void LockCamera(bool isLocked) { if (cameraController != null) cameraController.enabled = !isLocked; }

    private bool IsPointerOverUI()
    {
        if (EventSystem.current != null)
        {
            if (EventSystem.current.IsPointerOverGameObject()) return true;
            if (Input.touchCount > 0 && EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId)) return true;
        }
        return false;
    }
}