using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DraggableObject : MonoBehaviour
{
    [HideInInspector] public float mass = 1f;
    [HideInInspector] public bool isHeavy = false;
    [HideInInspector] public Transform priorityTarget = null;

    public Vector3 startPosition { get; private set; }
    public Quaternion startRotation { get; private set; }

    private Vector3 _mousePosition;
    private Vector3 _mouseCameraPos;
    private Vector3 _initialPosition;
    private Rigidbody _rb;
    private Camera _camera;
    private Transform _scaleTarget;
    private float _lerpPosition;
    [HideInInspector] public bool isDragging;

    [SerializeField] private float _minY = 0.2f;
    [SerializeField] private float _maxDistanceFromStart = 30f;

    private void Awake()
    {
        _rb = GetComponent<Rigidbody>();
    }

    private void Start()
    {
        _camera = Camera.main;
        _rb.isKinematic = true;
        startPosition = transform.position;
        startRotation = transform.rotation;
    }

    private Vector3 GetMousePos()
    {
        return _camera != null ? _camera.WorldToScreenPoint(transform.position) : Vector3.zero;
    }

    private Transform GetNearestTargetToCursor()
    {
        if (priorityTarget != null && priorityTarget.gameObject.activeInHierarchy)
            return priorityTarget;

        var targets = new List<GameObject>();
        targets.AddRange(GameObject.FindGameObjectsWithTag("ScaleTarget"));
        targets.AddRange(GameObject.FindGameObjectsWithTag("MainScale"));

        Transform nearest = null;
        float minDist = float.MaxValue;
        foreach (var t in targets)
        {
            Vector3 screenPos = _camera.WorldToScreenPoint(t.transform.position);
            float d = Vector2.Distance(
                new Vector2(Input.mousePosition.x, Input.mousePosition.y),
                new Vector2(screenPos.x, screenPos.y));
            if (d < minDist) { minDist = d; nearest = t.transform; }
        }
        return nearest;
    }

    private void OnMouseDown()
    {
        _rb.isKinematic = false;
        _rb.useGravity = false;
        _rb.velocity = Vector3.zero;
        _scaleTarget = GetNearestTargetToCursor();
        _initialPosition = transform.position;
        _mousePosition = Input.mousePosition - GetMousePos();
        isDragging = true;
    }

    private void Update()
    {
        if (!isDragging || _camera == null) return;

        _rb.angularVelocity = Vector3.zero;
        _mouseCameraPos = _camera.ScreenToWorldPoint(Input.mousePosition - _mousePosition);

        float targetZ = _scaleTarget != null ? _scaleTarget.position.z : _initialPosition.z;
        _lerpPosition = _scaleTarget != null
            ? Mathf.InverseLerp(_initialPosition.x, _scaleTarget.position.x, _mouseCameraPos.x)
            : 0f;

        transform.position = new Vector3(
            _mouseCameraPos.x,
            Mathf.Max(_mouseCameraPos.y, _minY),
            Mathf.Lerp(_initialPosition.z, targetZ, _lerpPosition)
        );

        if (Input.GetMouseButtonUp(0))
        {
            isDragging = false;
            _rb.useGravity = true;
            _rb.isKinematic = false;
        }
    }

    private void FixedUpdate()
    {
        if (isDragging) return;
        if (Vector3.Distance(transform.position, startPosition) > _maxDistanceFromStart)
            ResetToStart();
    }

    public void ResetToStart()
    {
        _rb.velocity = Vector3.zero;
        _rb.angularVelocity = Vector3.zero;
        _rb.isKinematic = true;
        transform.position = startPosition;
        transform.rotation = startRotation;
        isDragging = false;
    }

    private void OnTriggerEnter(Collider other)
    {
        if (isDragging) return;
        if (!other.CompareTag("ScalePan")) return;
        StartCoroutine(SnapToPan(other.transform));
    }

    private IEnumerator SnapToPan(Transform pan)
    {
        _rb.isKinematic = true;
        _rb.useGravity = false;

        Vector3 targetPos = pan.position + Vector3.up * 0.1f;
        float t = 0f;
        Vector3 startPos = transform.position;

        while (t < 1f)
        {
            t += Time.deltaTime * 5f;
            transform.position = Vector3.Lerp(startPos, targetPos, t);
            yield return null;
        }

        _rb.isKinematic = false;
        _rb.useGravity = true;
    }
}
