using System.Threading;
using Cysharp.Threading.Tasks;
using FlappyBird.Core;
using UnityEngine;
using Zenject;

namespace FlappyBird.UI
{
    [RequireComponent(typeof(CanvasGroup))]
    public class ScorePopupView : MonoBehaviour, Core.IPoolable
    {
        [SerializeField] private float floatSpeed = 100f;
        [SerializeField] private float duration = 0.7f;
        [SerializeField] private AnimationCurve alphaCurve = AnimationCurve.Linear(0, 1, 1, 0);

        private IObjectPoolManager _poolManager;
        private CanvasGroup _canvasGroup;
        private RectTransform _rectTransform;
        private CancellationTokenSource _cts;

        [Inject]
        public void Construct(IObjectPoolManager poolManager)
        {
            _poolManager = poolManager;
        }

        private void Awake()
        {
            _canvasGroup = GetComponent<CanvasGroup>();
            _rectTransform = transform as RectTransform;
        }

        /// <summary>
        /// Called by the ObjectPoolManager when the popup is retrieved from the pool.
        /// Starts the async animation task.
        /// </summary>
        public void OnSpawned()
        {
            _cts?.Cancel();
            _cts = new CancellationTokenSource();

            AnimateAndReturnAsync(_cts.Token).Forget();
        }

        public void OnDespawned()
        {
            _cts?.Cancel();
            _cts?.Dispose();
            _cts = null;
        }

        private async UniTaskVoid AnimateAndReturnAsync(CancellationToken token)
        {
            float elapsed = 0f;
            Vector2 startPosition = _rectTransform.anchoredPosition;

            while (elapsed < duration)
            {
                if (token.IsCancellationRequested) return;

                elapsed += Time.deltaTime;
                float normalizedTime = elapsed / duration;

                // Move upwards using RectTransform for UI consistency
                _rectTransform.anchoredPosition = startPosition + (Vector2.up * (floatSpeed * normalizedTime));

                // Apply fading based on curve
                if (_canvasGroup != null)
                {
                    _canvasGroup.alpha = alphaCurve.Evaluate(normalizedTime);
                }

                await UniTask.Yield(PlayerLoopTiming.Update, token);
            }

            // Return to pool after animation finishes
            _poolManager.Return(this);
        }

        private void OnDestroy()
        {
            _cts?.Cancel();
            _cts?.Dispose();
        }
    }
}