// Copyright 2012-2026 The NATS Authors
// Licensed under the Apache License, Version 2.0

using System.Threading;

namespace ZB.MOM.NatsNet.Server;

internal static class RaftStateExtensions
{
    internal static string String(this RaftState state) => state switch
    {
        RaftState.Follower => "FOLLOWER",
        RaftState.Candidate => "CANDIDATE",
        RaftState.Leader => "LEADER",
        RaftState.Closed => "CLOSED",
        _ => "UNKNOWN",
    };
}

internal sealed partial class Raft
{
    public bool CheckAccountNRGStatus()
    {
        return CheckAccountNrgStatusCore();
    }

    public Exception? RecreateInternalSubsLocked()
    {
        return RecreateInternalSubsLockedCore();
    }

    public bool OutOfResources()
    {
        return OutOfResourcesCore();
    }

    public void PauseApplyLocked()
    {
        PauseApplyLockedCore();
    }

    private bool CheckAccountNrgStatusCore()
    {
        if (Server_ is not NatsServer server)
        {
            return false;
        }

        if (!server.AccountNrgAllowed)
        {
            return false;
        }

        var enabled = true;
        foreach (var peerName in Peers_.Keys)
        {
            var nodeInfo = server.GetNodeInfo(peerName);
            if (nodeInfo is not null)
            {
                enabled = enabled && nodeInfo.AccountNrg;
            }
        }

        return enabled;
    }

    private Exception? RecreateInternalSubsLockedCore()
    {
        if (Server_ is null)
        {
            return new InvalidOperationException("server not found");
        }

        Interlocked.Exchange(ref _isSysAccV, 1);
        Active = DateTime.UtcNow;
        return null;
    }

    private bool OutOfResourcesCore()
    {
        if (!Track || JetStream_ is null)
        {
            return false;
        }

        if (JetStream_ is IJetStreamResourceLimits limits)
        {
            return limits.LimitsExceeded(WalType);
        }

        return false;
    }

    private void PauseApplyLockedCore()
    {
        if (State() == RaftState.Candidate)
        {
            StateValue = (int)RaftState.Follower;
            Interlocked.Exchange(ref HasLeaderV, 0);
        }

        Paused = true;
        if (HCommit < Commit)
        {
            HCommit = Commit;
        }
    }
}

internal interface IJetStreamResourceLimits
{
    bool LimitsExceeded(StorageType storageType);
}
