namespace NATS.Server.Raft;

public sealed class RaftReplicator
{
    public static long BacktrackNextIndex(long nextIndex)
        => Math.Max(1, nextIndex - 1);

    public int Replicate(RaftLogEntry entry, IReadOnlyList<RaftNode> followers)
    {
        var acknowledgements = 0;
        foreach (var follower in followers)
        {
            follower.ReceiveReplicatedEntry(entry);
            acknowledgements++;
        }

        return acknowledgements;
    }

    public async Task<IReadOnlyList<AppendResult>> ReplicateAsync(
        string leaderId,
        RaftLogEntry entry,
        IReadOnlyList<RaftNode> followers,
        IRaftTransport? transport,
        CancellationToken ct)
    {
        if (transport != null)
            return await transport.AppendEntriesAsync(leaderId, followers.Select(f => f.Id).ToArray(), entry, ct);

        var results = new List<AppendResult>(followers.Count);
        foreach (var follower in followers)
        {
            follower.ReceiveReplicatedEntry(entry);
            results.Add(new AppendResult { FollowerId = follower.Id, Success = true });
        }

        return results;
    }
}
