using UnityEngine;
namespace FlappyBird.Gameplay.Bird
{
    /// <summary>
    /// Pure C# service — all bird physics and rotation logic lives here.
    /// No MonoBehaviour, no Unity lifecycle. Injected via Zenject.
    /// </summary>
    public sealed class BirdController : IBirdController
    {
        // ── Dependencies ────────────────────────────────────────────────────
        private readonly Rigidbody2D _rigidbody;
        private readonly BirdSettings _settings;
        /// <summary>
        /// Constructor injection (Zenject will call this).
        /// </summary>
        /// <param name="rigidbody">The bird's Rigidbody2D component.</param>
        /// <param name="settings">Configurable physics parameters.</param>
        public BirdController(Rigidbody2D rigidbody, BirdSettings settings)
        {
            _rigidbody = rigidbody;
            _settings  = settings;

            // Lock X position so the bird never drifts horizontally.
            // The illusion of forward movement comes from pipes scrolling left.
            _rigidbody.constraints = RigidbodyConstraints2D.FreezePositionX;
        }
        // ── IBirdController ─────────────────────────────────────────────────
        /// <inheritdoc/>
        public void Tick()
        {
            ApplyRotation();
        }
        /// <inheritdoc/>
        public void Jump()
        {
            // Reset vertical velocity so each tap feels consistent regardless of fall speed.
            // X is frozen via constraints, but we explicitly keep it zero for safety.
            _rigidbody.linearVelocity = Vector2.zero;
            _rigidbody.AddForce(Vector2.up * _settings.JumpForce, ForceMode2D.Impulse);
        }
        // ── Private helpers ─────────────────────────────────────────────────
        /// <summary>
        /// Maps vertical velocity to a tilt angle and smoothly rotates the bird.
        /// Velocity range [rotationUpVelocity .. rotationDownVelocity] maps to
        /// [maxUpRotation .. maxDownRotation] via an inverse-lerp → lerp.
        /// </summary>
        private void ApplyRotation()
        {
            float velocityY = _rigidbody.linearVelocity.y;
            // Normalise velocity to [0, 1] (0 = falling fast, 1 = rising fast).
            float t = Mathf.InverseLerp(
                _settings.RotationDownVelocity,
                _settings.RotationUpVelocity,
                velocityY);
            float targetAngle = Mathf.Lerp(
                _settings.MaxDownRotation,
                _settings.MaxUpRotation,
                t);
            // Read current Z rotation from the transform via the rigidbody.
            float currentAngle = _rigidbody.rotation;
            float smoothedAngle = Mathf.LerpAngle(
                currentAngle,
                targetAngle,
                _settings.RotationSpeed * Time.deltaTime);
            _rigidbody.MoveRotation(smoothedAngle);
        }
    }
}
