Aim prediction system doesn't work properly

I’ve been working on this enemy AI to improve its aim, but I’ve hit a wall. The enemy has two modes: one predicts where to hit if the player doesn’t move, and the other tries to aim if the player moves. However, both modes currently miss the target. I’ve shared the code I’m using along with a video showing what’s happening. If anyone has a solution, guidance, or a different approach, it would be greatly appreciated. Thank you
Video:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Pool;


public class EnemyProjectilsCreator : ObjectsCreator
{
    [SerializeField]
    private float _forwardForce;
    [SerializeField]
    private float _fireCooldwon;
    [SerializeField]
    private Transform _fireePoint;

    private bool _canFire;

    private Rigidbody _projectilRB;

    [Range(0, 1)]
    [Tooltip("Using a values closer to 0 will make the agent throw with the lower force"
    + "down to the least possible force (highest angle) to reach the target.\n"
    + "Using a value of 1 the agent will always throw with the MaxThrowForce below.")]
    public float ForceRatio = 0;
    [SerializeField]
    [Tooltip("If the required force to throw the attack is greater than this value, "
        + "the agent will move closer until they come within range.")]
    private float MaxThrowForce = 25;

    [SerializeField]
    private bool UseMovementPrediction;
    public PredictionMode MovementPredictionMode;
    [Range(0.01f, 5f)]
    public float HistoricalTime = 1f;
    [Range(1, 100)]
    public int HistoricalResolution = 10;
    private Queue<Vector3> HistoricalPositions;

    private float HistoricalPositionInterval;
    private float LastHistoryRecordedTime;

    void Start()
    {
        _canFire = true;
        int capacity = Mathf.CeilToInt(HistoricalResolution * HistoricalTime);
        HistoricalPositions = new Queue<Vector3>(capacity);
        for (int i = 0; i < capacity; i++)
        {
            HistoricalPositions.Enqueue(GameManager.Instance.GetPlayerTransform().position);
        }
        HistoricalPositionInterval = HistoricalTime / HistoricalResolution;

    }

    public void FireBullet()
    {
        if (!_canFire)
            return;

        _canFire = false;

        Vector3 fireDirection;

        fireDirection = _fireePoint.forward * _forwardForce;

        ObjectToCreate projectile = _objectPool.Get();
        projectile.GetComponent<Bullet>().Creator = transform;
/*        projectile.GetComponent<Rigidbody>().useGravity = true;
        projectile.GetComponent<Rigidbody>().isKinematic = false;*/

        if (projectile == null)
        {
            return;
        }

        projectile.transform.position = _fireePoint.position;

        _projectilRB = projectile.GetComponent<Rigidbody>();

        //_projectilRB.WakeUp();
        //bulletRB.AddForce(fireDirection, ForceMode.Impulse);

        ThrowData throwData = CalculateThrowData(GameManager.Instance.GetPlayerTransform().position, projectile.transform.position);

        if (UseMovementPrediction)
        {
            throwData = GetPredictedPositionThrowData(throwData);
        }

        DoThrow(throwData);

        projectile.GetComponent<Bullet>().DeactivateOnParry();

        Invoke(nameof(FireAgain), _fireCooldwon);


    }

    private void FireAgain()
    {
        _canFire = true;
    }

    private ThrowData GetPredictedPositionThrowData(ThrowData DirectThrowData)
    {
        Vector3 throwVelocity = DirectThrowData.ThrowVelocity;
        throwVelocity.y = 0;
        float time = DirectThrowData.DeltaXZ / throwVelocity.magnitude;
        Vector3 playerMovement;

        if (MovementPredictionMode == PredictionMode.CurrentVelocity)
        {
            playerMovement = GameManager.Instance.GetPlayerRB().velocity * time;
        }
        else
        {

            Vector3[] positions = HistoricalPositions.ToArray();
            Vector3 averageVelocity = Vector3.zero;
            for (int i = 1; i < positions.Length; i++)
            {
                averageVelocity += (positions[i] - positions[i - 1]) / HistoricalPositionInterval;
            }
            averageVelocity /= HistoricalTime * HistoricalResolution;
            playerMovement = averageVelocity;

        }

        Vector3 newTargetPosition = new Vector3(
            GameManager.Instance.GetPlayerTransform().position.x + playerMovement.x,
            GameManager.Instance.GetPlayerTransform().position.y + playerMovement.y,
           GameManager.Instance.GetPlayerTransform().position.z + playerMovement.z
        );

        // Option Calculate again the trajectory based on target position
        ThrowData predictiveThrowData = CalculateThrowData(
            newTargetPosition,
            _projectilRB.position
        );

        predictiveThrowData.ThrowVelocity = Vector3.ClampMagnitude(
            predictiveThrowData.ThrowVelocity,
            MaxThrowForce
        );

        return predictiveThrowData;
    }

    private void DoThrow(ThrowData ThrowData)
    {
        _projectilRB.velocity = ThrowData.ThrowVelocity;
    }

    private ThrowData CalculateThrowData(Vector3 TargetPosition, Vector3 StartPosition)
    {
        // v = initial velocity, assume max speed for now
        // x = distance to travel on X/Z plane only
        // y = difference in altitudes from thrown point to target hit point
        // g = gravity

        Vector3 displacement = new Vector3(
            TargetPosition.x,
            StartPosition.y,
            TargetPosition.z
        ) - StartPosition;
        float deltaY = TargetPosition.y - StartPosition.y;
        float deltaXZ = displacement.magnitude;

        // find lowest initial launch velocity with other magic formula from https://en.wikipedia.org/wiki/Projectile_motion
        // v^2 / g = y + sqrt(y^2 + x^2)
        // meaning.... v = sqrt(g * (y+ sqrt(y^2 + x^2)))
        float gravity = Mathf.Abs(Physics.gravity.y);
        float throwStrength = Mathf.Clamp(
            Mathf.Sqrt(
                gravity
                * (deltaY + Mathf.Sqrt(Mathf.Pow(deltaY, 2)
                + Mathf.Pow(deltaXZ, 2)))),
            0.01f,
            MaxThrowForce
        );
        throwStrength = Mathf.Lerp(throwStrength, MaxThrowForce, ForceRatio);

        float angle;
        if (ForceRatio == 0)
        {
            // optimal angle is chosen with a relatively simple formula
            angle = Mathf.PI / 2f - (0.5f * (Mathf.PI / 2 - (deltaY / deltaXZ)));
        }
        else
        {
            // when we know the initial velocity, we have to calculate it with this formula
            // Angle to throw = arctan((v^2 +- sqrt(v^4 - g * (g * x^2 + 2 * y * v^2)) / g*x)
            angle = Mathf.Atan(
                (Mathf.Pow(throwStrength, 2) - Mathf.Sqrt(
                    Mathf.Pow(throwStrength, 4) - gravity
                    * (gravity * Mathf.Pow(deltaXZ, 2)
                    + 2 * deltaY * Mathf.Pow(throwStrength, 2)))
                ) / (gravity * deltaXZ)
            );
        }

        if (float.IsNaN(angle))
        {
            // you will need to handle this case when there
            // is no feasible angle to throw the object and reach the target.
            return new ThrowData();
        }

        Vector3 initialVelocity =
            Mathf.Cos(angle) * throwStrength * displacement.normalized
            + Mathf.Sin(angle) * throwStrength * Vector3.up;

        return new ThrowData
        {
            ThrowVelocity = initialVelocity,
            Angle = angle,
            DeltaXZ = deltaXZ,
            DeltaY = deltaY
        };
    }

    private struct ThrowData
    {
        public Vector3 ThrowVelocity;
        public float Angle;
        public float DeltaXZ;
        public float DeltaY;
    }

    public enum PredictionMode
    {
        CurrentVelocity,
        AverageVelocity
    }
}

I have a GitHub project that you can use for comparison. It will always hit a stationary target, or a target moving at a consistent velocity for the time it takes for the projectile to hit the target. To avoid the hits, you need to change velocity after the shot has been fired, but before it lands.