using UnityEngine;

namespace Streamingle.Utils
{
    /// <summary>
    /// 타겟 오브젝트를 부드럽게 따라가는 컴포넌트
    /// </summary>
    public class SmoothFollow : MonoBehaviour
    {
        [Header("Target")]
        [Tooltip("따라갈 대상 Transform")]
        public Transform target;

        [Header("Follow Settings")]
        [Tooltip("위치 따라가기 활성화")]
        public bool followPosition = true;

        [Tooltip("회전 따라가기 활성화")]
        public bool followRotation = false;

        [Header("Smoothing")]
        [Tooltip("위치 보간 속도 (낮을수록 더 부드럽게)")]
        [Range(0.01f, 20f)]
        public float positionSmoothSpeed = 5f;

        [Tooltip("회전 보간 속도 (낮을수록 더 부드럽게)")]
        [Range(0.01f, 20f)]
        public float rotationSmoothSpeed = 5f;

        [Header("Offset")]
        [Tooltip("타겟으로부터의 위치 오프셋 (로컬 기준)")]
        public Vector3 positionOffset = Vector3.zero;

        [Tooltip("타겟으로부터의 회전 오프셋")]
        public Vector3 rotationOffset = Vector3.zero;

        [Header("Constraints")]
        [Tooltip("X축 위치 고정")]
        public bool freezePositionX = false;
        [Tooltip("Y축 위치 고정")]
        public bool freezePositionY = false;
        [Tooltip("Z축 위치 고정")]
        public bool freezePositionZ = false;

        private Vector3 _initialPosition;
        private Quaternion _initialRotation;
        private Vector3 _velocity = Vector3.zero;

        private void Awake()
        {
            _initialPosition = transform.position;
            _initialRotation = transform.rotation;
        }

        private void LateUpdate()
        {
            if (target == null) return;

            if (followPosition)
            {
                UpdatePosition();
            }

            if (followRotation)
            {
                UpdateRotation();
            }
        }

        private void UpdatePosition()
        {
            // 타겟 위치 + 로컬 오프셋 계산
            Vector3 targetPosition = target.TransformPoint(positionOffset);

            // 부드러운 보간
            Vector3 smoothedPosition = Vector3.Lerp(
                transform.position,
                targetPosition,
                positionSmoothSpeed * Time.deltaTime
            );

            // 축 고정 적용
            if (freezePositionX) smoothedPosition.x = _initialPosition.x;
            if (freezePositionY) smoothedPosition.y = _initialPosition.y;
            if (freezePositionZ) smoothedPosition.z = _initialPosition.z;

            transform.position = smoothedPosition;
        }

        private void UpdateRotation()
        {
            Quaternion targetRotation = target.rotation * Quaternion.Euler(rotationOffset);

            transform.rotation = Quaternion.Slerp(
                transform.rotation,
                targetRotation,
                rotationSmoothSpeed * Time.deltaTime
            );
        }

        /// <summary>
        /// 타겟을 런타임에 변경
        /// </summary>
        public void SetTarget(Transform newTarget)
        {
            target = newTarget;
        }

        /// <summary>
        /// 즉시 타겟 위치로 이동 (보간 없이)
        /// </summary>
        public void SnapToTarget()
        {
            if (target == null) return;

            if (followPosition)
            {
                Vector3 targetPosition = target.TransformPoint(positionOffset);
                if (freezePositionX) targetPosition.x = _initialPosition.x;
                if (freezePositionY) targetPosition.y = _initialPosition.y;
                if (freezePositionZ) targetPosition.z = _initialPosition.z;
                transform.position = targetPosition;
            }

            if (followRotation)
            {
                transform.rotation = target.rotation * Quaternion.Euler(rotationOffset);
            }
        }

        /// <summary>
        /// 초기 위치로 복귀
        /// </summary>
        public void ResetToInitial()
        {
            transform.position = _initialPosition;
            transform.rotation = _initialRotation;
        }

#if UNITY_EDITOR
        private void OnDrawGizmosSelected()
        {
            if (target == null) return;

            Gizmos.color = Color.cyan;
            Vector3 targetPos = target.TransformPoint(positionOffset);
            Gizmos.DrawLine(transform.position, targetPos);
            Gizmos.DrawWireSphere(targetPos, 0.1f);
        }
#endif
    }
}
