using TMPro;
using UnityEngine;
using UVC.Locale;
using UVC.Log; // LocalizationManager를 사용한다면 필요합니다.

namespace UVC.UI.Tooltip
{
    /// <summary>
    /// 툴팁 UI를 전역적으로 관리하는 싱글톤 클래스입니다.
    /// 툴팁의 생성, 표시, 숨김, 위치 조정 및 다국어 지원 기능을 담당합니다.
    /// 이 클래스는 일반적으로 애플리케이션 전체에서 하나의 인스턴스만 존재합니다.
    /// 
    /// 사용 예시:
    /// 1. 초기화: 애플리케이션 시작 시점 (예: GameManager, UIManager 등)에서 한 번 호출해야 합니다.
    /// <code>
    /// // Canvas Transform과 최상위 Canvas 객체를 전달하여 초기화합니다.
    /// // TooltipManager.Instance.Initialize(uiCanvas.transform, uiCanvas); 
    /// </code>
    /// 
    /// 2. 툴팁 표시/숨김 요청: TooltipHandler를 통해 간접적으로 호출되거나, 직접 호출할 수도 있습니다.
    ///    TooltipHandler를 사용하는 것이 일반적입니다.
    /// </summary>
    public class TooltipManager
    {
        #region Singleton Implementation
        private static TooltipManager _instance;
        public static TooltipManager Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new TooltipManager();
                }
                return _instance;
            }
        }
        // 외부에서 직접 생성하지 못하도록 protected 생성자로 변경
        protected TooltipManager() { }
        #endregion

        protected Transform _defaultParentTransform; // 툴팁 인스턴스가 생성될 기본 부모 Transform
        protected Canvas _rootCanvas; // 화면 좌표 계산 및 UI 스케일링에 사용될 Canvas

        protected GameObject _activeTooltipInstance; // 현재 활성화된 툴팁 게임 오브젝트
        protected TextMeshProUGUI _tooltipTextElement; // 툴팁 텍스트를 표시하는 TextMeshProUGUI 컴포넌트
        protected RectTransform _tooltipRectTransform; // 툴팁의 크기 및 위치 조정을 위한 RectTransform

        protected bool _isInitialized = false; // 초기화 완료 여

        /// <summary>
        /// TooltipManager가 성공적으로 초기화되었는지 여부를 반환합니다.
        /// </summary>
        public bool IsInitialized => _isInitialized;

        protected string tooltipPrefabPath = "Prefabs/UI/Tooltip/Tooltip";

        /// <summary>
        /// Resources 폴더 내의 툴팁 UI 프리팹 경로입니다.
        /// 상속을 통해 다른 경로를 사용하도록 재정의할 수 있습니다.
        /// </summary>
        protected virtual string TooltipPrefabPath => tooltipPrefabPath;

        /// <summary>
        /// TooltipManager를 초기화합니다. 이 메서드는 한 번만 호출되어야 합니다.
        /// 일반적으로 애플리케이션 시작 시점이나 UI 시스템이 로드될 때 호출됩니다.
        /// 툴팁 프리팹을 로드하고, 필요한 컴포넌트를 찾아 내부 변수에 할당합니다.
        /// </summary>
        /// <param name="defaultParent">생성된 툴팁 인스턴스의 기본 부모 Transform입니다. 보통 Canvas의 Transform입니다.</param>
        /// <param name="rootCanvas">툴팁의 위치와 크기를 계산하는 데 사용될 최상위 Canvas입니다.</param>
        /// <param name="customTooltipPrefabPath">Resources 폴더 내의 사용자 정의 툴팁 UI 프리팹 경로입니다. null일 경우 기본 경로를 사용합니다.</param>
        /// <example>
        /// <code>
        /// // 게임 시작 시 UIManager 등에서 호출
        /// public class UIManager : MonoBehaviour
        /// {
        ///     public Canvas mainCanvas; // Inspector에서 할당
        /// 
        ///     void Start()
        ///     {
        ///         // mainCanvas.transform을 부모로, mainCanvas를 루트 캔버스로 하여 초기화
        ///         TooltipManager.Instance.Initialize(mainCanvas.transform, mainCanvas);
        /// 
        ///         // 특정 프리팹 경로를 사용하고 싶다면:
        ///         // TooltipManager.Instance.Initialize(mainCanvas.transform, mainCanvas, "MyCustomTooltipPrefab");
        ///     }
        /// }
        /// </code>
        /// </example>
        public void Initialize(Transform defaultParent, Canvas rootCanvas, string tooltipPrefabPath = null)
        {
            if (_isInitialized)
            {
                Debug.LogWarning("TooltipVisualManager는 이미 초기화되었습니다.");
                return;
            }

            if (defaultParent == null)
            {
                Debug.LogError("TooltipVisualManager 초기화 실패: defaultParent가 null입니다.");
                return;
            }
            if (rootCanvas == null)
            {
                Debug.LogError("TooltipVisualManager 초기화 실패: rootCanvas가 null입니다.");
                return;
            }

            if (!string.IsNullOrEmpty(tooltipPrefabPath))
            {
                this.tooltipPrefabPath = tooltipPrefabPath; // 사용자 지정 경로가 제공되면 업데이트
            }

            GameObject loadedTooltipPrefab = Resources.Load<GameObject>(this.tooltipPrefabPath);

            if (loadedTooltipPrefab == null)
            {
                Debug.LogError($"TooltipManager 초기화 실패: Resources 폴더에서 '{this.tooltipPrefabPath}' 경로의 프리팹을 로드할 수 없습니다.");
                return;
            }

            _defaultParentTransform = defaultParent;
            _rootCanvas = rootCanvas;

            // 툴팁 인스턴스 생성 및 초기화
            _activeTooltipInstance = GameObject.Instantiate(loadedTooltipPrefab, _defaultParentTransform);
            _tooltipTextElement = _activeTooltipInstance.GetComponentInChildren<TextMeshProUGUI>();
            _tooltipRectTransform = _activeTooltipInstance.GetComponent<RectTransform>();

            if (_tooltipTextElement == null || _tooltipRectTransform == null)
            {
                Debug.LogError("TooltipVisualManager 초기화 실패: tooltipPrefab의 구성요소가 올바르지 않습니다. TextMeshProUGUI와 RectTransform이 필요합니다.");
                if (_activeTooltipInstance != null) GameObject.Destroy(_activeTooltipInstance);
                _activeTooltipInstance = null; // 초기화 실패 상태로 설정
                return;
            }

            _activeTooltipInstance.SetActive(false); // 처음에는 숨김
            _isInitialized = true;
        }

        /// <summary>
        /// 마우스 포인터가 UI 요소에 진입했을 때 호출되어 툴팁을 표시합니다.
        /// TooltipHandler 컴포넌트에 의해 주로 호출됩니다.
        /// 툴팁 내용은 다국어 처리를 거쳐 표시될 수 있습니다.
        /// </summary>
        /// <param name="tooltipKeyOrText">표시할 툴팁 내용 또는 다국어 키입니다.</param>
        /// <param name="mousePosition">현재 마우스 포인터의 화면 좌표입니다.</param>
        public void HandlePointerEnter(string tooltipKeyOrText, Vector3 mousePosition)
        {
            if (!_isInitialized || _activeTooltipInstance == null)
            {
                // Debug.LogWarning("TooltipManager가 초기화되지 않았거나 툴팁 인스턴스가 없습니다.");
                return;
            }

            string tooltipTextToShow = tooltipKeyOrText; // 기본값은 전달된 문자열 자체

            // LocalizationManager가 있고, tooltipKeyOrText가 비어있지 않다면 다국어 시도
            if (LocalizationManager.Instance != null && !string.IsNullOrEmpty(tooltipKeyOrText))
            {
                string localizedText = LocalizationManager.Instance.GetString(tooltipKeyOrText);
                // 번역된 텍스트가 있고, 원본 키와 다르다면 (즉, 번역 성공) 해당 텍스트 사용
                if (!string.IsNullOrEmpty(localizedText) && localizedText != tooltipKeyOrText)
                {
                    tooltipTextToShow = localizedText;
                }
                // 번역 결과가 비어있다면 (키는 있지만 번역 값이 없는 경우) 툴팁을 숨김
                else if (string.IsNullOrEmpty(localizedText))
                {
                    HideTooltip();
                    return;
                }
                // 그 외의 경우 (키 자체가 번역 값인 경우 등)는 tooltipKeyOrText를 그대로 사용
            }

            // 최종적으로 표시할 텍스트가 비어있다면 툴팁을 숨김
            if (string.IsNullOrEmpty(tooltipTextToShow))
            {
                HideTooltip();
                return;
            }
            ShowTooltip(tooltipTextToShow, mousePosition);
        }

        /// <summary>
        /// 마우스 포인터가 UI 요소에서 벗어났을 때 호출되어 툴팁을 숨깁니다.
        /// TooltipHandler 컴포넌트에 의해 주로 호출됩니다.
        /// </summary>
        public void HandlePointerExit()
        {
            // ULog.Debug("TooltipManager.HandlePointerExit() called."); // 디버그 로그 필요시 활성화
            if (!_isInitialized) return;
            HideTooltip();
        }

        /// <summary>
        /// 툴팁 UI를 화면에 실제로 표시하고 내용을 설정하며 위치를 조정합니다.
        /// </summary>
        /// <param name="text">툴팁에 표시될 최종 텍스트입니다.</param>
        /// <param name="mousePosition">툴팁 위치를 결정하기 위한 현재 마우스 포인터의 화면 좌표입니다.</param>
        private void ShowTooltip(string text, Vector3 mousePosition)
        {
            if (_activeTooltipInstance == null || _tooltipTextElement == null || _tooltipRectTransform == null) return;

            _tooltipTextElement.text = text; // 텍스트 설정
            _activeTooltipInstance.SetActive(true); // 툴팁 활성화

            // 툴팁을 현재 부모 내에서 가장 마지막 자식으로 만들어 다른 UI 요소들 위에 표시되도록 합니다.
            if (_activeTooltipInstance.transform.parent != null)
            {
                _activeTooltipInstance.transform.SetAsLastSibling();
            }

            _tooltipTextElement.ForceMeshUpdate(); // 텍스트 변경 후 메쉬 강제 업데이트 (정확한 크기 계산 위함)
            Vector2 textSize = _tooltipTextElement.GetPreferredValues(text); // 텍스트 내용에 따른 선호 크기 계산
            Vector2 padding = new Vector2(10, 2); // 툴팁 내부 여백 (좌우 10, 상하 2)
            _tooltipRectTransform.sizeDelta = textSize + padding * 2; // 텍스트 크기와 여백을 합쳐 툴팁 전체 크기 설정

            AdjustPosition(mousePosition); // 마우스 위치 기준으로 툴팁 위치 조정
        }

        /// <summary>
        /// 툴팁의 위치를 마우스 포인터 주변으로 조정합니다.
        /// 화면 좌표계의 마우스 위치를 Canvas 내의 로컬 좌표로 변환하여 사용합니다.
        /// </summary>
        /// <param name="mousePosition">현재 마우스 포인터의 화면 좌표입니다.</param>
        private void AdjustPosition(Vector3 mousePosition)
        {
            if (_rootCanvas == null || _tooltipRectTransform == null) return;

            Vector2 localPoint; // Canvas 내 로컬 좌표
            // 현재 Canvas의 Render Mode에 따라 적절한 카메라 사용
            Camera eventCamera = (_rootCanvas.renderMode == RenderMode.ScreenSpaceOverlay) ? null : _rootCanvas.worldCamera;

            // 화면 좌표(mousePosition)를 _rootCanvas의 RectTransform 내 로컬 좌표로 변환
            RectTransformUtility.ScreenPointToLocalPointInRectangle(
                _rootCanvas.transform as RectTransform, // 좌표 변환의 기준이 될 RectTransform
                mousePosition,                          // 변환할 화면 좌표
                eventCamera,                            // 이벤트 카메라 (ScreenSpaceOverlay의 경우 null)
                out localPoint                          // 변환된 로컬 좌표 결과
            );

            // 툴팁을 마우스 오른쪽 아래에 표시하기 위한 오프셋 계산.
            // 툴팁 RectTransform의 Pivot 설정을 고려합니다.
            // 예: Pivot (0,1) (좌상단)일 경우, 마우스 위치에서 오른쪽으로 약간, 아래로 툴팁 높이만큼 이동.
            Vector2 pivotOffset = new Vector2(
                _tooltipRectTransform.sizeDelta.x * _tooltipRectTransform.pivot.x + 10f, // X 오프셋 (오른쪽으로 10px)
                _tooltipRectTransform.sizeDelta.y * (1 - _tooltipRectTransform.pivot.y) - 10f // Y 오프셋 (아래로 10px)
            );

            // 최종적으로 툴팁의 로컬 위치 설정
            _tooltipRectTransform.localPosition = localPoint + pivotOffset;

            // 화면 경계를 벗어나지 않도록 위치 추가 조정
            AdjustPositionWithinScreenBounds();
        }


        /// <summary>
        /// 활성화된 툴팁 인스턴스를 비활성화하여 화면에서 숨깁니다.
        /// </summary>
        public void HideTooltip()
        {
            if (_activeTooltipInstance != null)
            {
                _activeTooltipInstance.SetActive(false);
            }
        }

        /// <summary>
        /// 툴팁이 화면 경계를 벗어나는 경우 위치를 조정하여 화면 내에 보이도록 합니다.
        /// </summary>
        private void AdjustPositionWithinScreenBounds()
        {
            if (_tooltipRectTransform == null || _activeTooltipInstance == null || !_activeTooltipInstance.activeSelf || _rootCanvas == null) return;

            Vector3[] tooltipCorners = new Vector3[4]; // 툴팁의 네 꼭짓점 월드 좌표
            _tooltipRectTransform.GetWorldCorners(tooltipCorners);

            RectTransform canvasRectTransform = _rootCanvas.transform as RectTransform;

            // 화면 경계 좌표 설정
            float minX, maxX, minY, maxY;

            if (_rootCanvas.renderMode == RenderMode.ScreenSpaceOverlay)
            {
                // Screen Space Overlay 모드에서는 Screen.width/height를 사용
                minX = 0;
                maxX = Screen.width;
                minY = 0;
                maxY = Screen.height;
            }
            else
            {
                // Screen Space Camera 또는 World Space 모드에서는 Canvas의 월드 좌표 경계를 사용
                Vector3[] canvasCorners = new Vector3[4];
                canvasRectTransform.GetWorldCorners(canvasCorners);
                minX = canvasCorners[0].x; // Bottom-left X
                maxX = canvasCorners[2].x; // Top-right X
                minY = canvasCorners[0].y; // Bottom-left Y
                maxY = canvasCorners[1].y; // Top-left Y (또는 corners[2].y)
            }

            Vector3 currentPosition = _tooltipRectTransform.position; // 현재 툴팁 위치 (월드 좌표)
            Vector2 size = _tooltipRectTransform.sizeDelta * _rootCanvas.scaleFactor; // Canvas 스케일을 고려한 실제 픽셀 크기
            Vector2 pivot = _tooltipRectTransform.pivot; // 툴팁의 Pivot

            // 오른쪽 경계 넘어감: 왼쪽으로 이동
            if (tooltipCorners[2].x > maxX) // Top-right X
            {
                currentPosition.x -= (tooltipCorners[2].x - maxX);
            }
            // 왼쪽 경계 넘어감: 오른쪽으로 이동
            if (tooltipCorners[0].x < minX) // Bottom-left X
            {
                currentPosition.x += (minX - tooltipCorners[0].x);
            }
            // 아래쪽 경계 넘어감: 마우스 포인터 위쪽으로 이동
            if (tooltipCorners[0].y < minY) // Bottom-left Y
            {
                Vector3 mouseWorldPos = Vector3.zero;
                // 마우스 포인터의 월드 Y 좌표를 가져옴
                if (_rootCanvas.renderMode == RenderMode.ScreenSpaceOverlay) mouseWorldPos = Input.mousePosition;
                else RectTransformUtility.ScreenPointToWorldPointInRectangle(canvasRectTransform, Input.mousePosition, _rootCanvas.worldCamera, out mouseWorldPos);

                // 마우스 Y 위치 + 툴팁 높이 (pivot 고려) + 약간의 오프셋
                currentPosition.y = mouseWorldPos.y + (size.y * (1 - pivot.y)) + 15f;
            }
            // 위쪽 경계 넘어감: 아래로 이동
            if (tooltipCorners[1].y > maxY) // Top-left Y
            {
                currentPosition.y -= (tooltipCorners[1].y - maxY);
            }
            _tooltipRectTransform.position = currentPosition; // 조정된 위치 적용
        }

        /// <summary>
        /// TooltipManager가 사용하던 리소스를 해제합니다.
        /// 애플리케이션 종료 시 또는 UI 시스템 해제 시 호출하는 것이 좋습니다.
        /// 생성된 툴팁 인스턴스를 파괴하고 내부 참조들을 null로 설정합니다.
        /// </summary>
        public void Dispose()
        {
            if (_activeTooltipInstance != null)
            {
                GameObject.Destroy(_activeTooltipInstance);
                _activeTooltipInstance = null;
            }
            _tooltipTextElement = null;
            _tooltipRectTransform = null;
            _defaultParentTransform = null;
            _rootCanvas = null;
            _isInitialized = false;
            _instance = null; // 싱글톤 인스턴스 참조 해제
        }
    }
}