using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using Zenject;
using FlappyBird.Core;

namespace FlappyBird.UI
{
    public class GameUIView : MonoBehaviour
    {
        [Header("Score Display")]
        [SerializeField] private Component currentScoreText;
        [SerializeField] private Component bestScoreText;
        [SerializeField] private RectTransform popupContainer;
        [SerializeField] private float scorePopScale = 1.4f;
        [SerializeField] private float scorePopDuration = 0.1f;

        [Header("Screens")]
        [SerializeField] private CanvasGroup tapToStartGroup;
        [SerializeField] private CanvasGroup gameOverGroup;
        [SerializeField] private float fadeSpeed = 5f;

        [Header("Game Over Details")]
        [SerializeField] private Component gameOverScoreText;
        [SerializeField] private Component gameOverBestScoreText;


        private IGameUIController _controller;
        private RectTransform _currentScoreRect;
        private Vector3 _currentScoreBaseScale;
        private float _scorePopTimer;
        private List<ScorePopupView> _activePopups = new List<ScorePopupView>();
        public Transform PopupTransform => transform;
        public RectTransform PopupContainer => popupContainer != null ? popupContainer : (transform as RectTransform);

        [Inject]
        public void Construct(IGameUIController controller)
        {
            _controller = controller;
        }

        private void Awake()
        {
            if (currentScoreText != null)
            {
                _currentScoreRect = currentScoreText.transform as RectTransform;
                _currentScoreBaseScale = _currentScoreRect.localScale;
            }
        }

        private void Start() => _controller.Bind(this);

        private void Update()
        {
            UpdateScorePop();
            UpdateScreenFades();
            UpdateMenuPulse();
            HandlePopupCleanup();
        }

        public void ShowScoreGain()
        {
            _scorePopTimer = scorePopDuration;
        }

        public void SetCurrentScore(int score)
        {
            SetText(currentScoreText, score.ToString());
            SetText(gameOverScoreText, score.ToString());
        }

        public void SetBestScore(int bestScore)
        {
            SetText(bestScoreText, $"BEST: {bestScore}");
            SetText(gameOverBestScoreText, bestScore.ToString());
        }

        private void UpdateScorePop()
        {
            if (_scorePopTimer <= 0) return;

            _scorePopTimer -= Time.unscaledDeltaTime;
            // Use an animation curve feel: pop out fast, shrink back
            float t = _scorePopTimer / scorePopDuration;
            float scale = Mathf.Lerp(1f, scorePopScale, t);
            _currentScoreRect.localScale = _currentScoreBaseScale * scale;
        }

        private void UpdateScreenFades()
        {
            float step = fadeSpeed * Time.unscaledDeltaTime;
            // Smoothly fade groups based on their active state handled in Controller
            tapToStartGroup.alpha = Mathf.MoveTowards(tapToStartGroup.alpha, tapToStartGroup.interactable ? 1 : 0, step);
            gameOverGroup.alpha = Mathf.MoveTowards(gameOverGroup.alpha, gameOverGroup.interactable ? 1 : 0, step);
        }

        private void UpdateMenuPulse()
        {
            if (tapToStartGroup.interactable)
            {
                float pulse = 1f + Mathf.Sin(Time.unscaledTime * 4f) * 0.05f;
                tapToStartGroup.transform.localScale = Vector3.one * pulse;
            }
        }

        public void SetTapToStartVisible(bool visible)
        {
            tapToStartGroup.interactable = visible;
            tapToStartGroup.blocksRaycasts = visible;
        }

        public void SetGameOverVisible(bool visible)
        {
            gameOverGroup.interactable = visible;
            gameOverGroup.blocksRaycasts = visible;
        }

        public void SetCurrentScoreVisible(bool visible)
        {
            currentScoreText.gameObject.SetActive(visible);
        }

        private void HandlePopupCleanup()
        {
            // Logic to return expired popups to pool would go here via the Controller
        }

        private static void SetText(Component target, string value)
        {
            if (target == null) return;
            var prop = target.GetType().GetProperty("text");
            prop?.SetValue(target, value, null);
        }
    }
}