using NeonSprawl.Server.Game.Gathering;
using Xunit;

namespace NeonSprawl.Server.Tests.Game.Gathering;

public sealed class InMemoryResourceNodeInstanceStoreTests
{
    private const string NodeId = "prototype_resource_node_alpha";

    [Fact]
    public void TryEnsureInitialized_ShouldBeIdempotent()
    {
        // Arrange
        var store = new InMemoryResourceNodeInstanceStore();

        // Act
        var first = store.TryEnsureInitialized(NodeId, initialRemainingGathers: 10);
        var second = store.TryEnsureInitialized(NodeId, initialRemainingGathers: 99);
        store.TryGetRemainingGathers(NodeId, out var snapshot);

        // Assert
        Assert.True(first);
        Assert.True(second);
        Assert.Equal(10, snapshot.RemainingGathers);
    }

    [Fact]
    public void TryDecrementRemainingGathers_FromOne_ShouldReachZeroAndDenySecondDecrement()
    {
        // Arrange
        var store = new InMemoryResourceNodeInstanceStore();
        store.TryEnsureInitialized(NodeId, initialRemainingGathers: 1);

        // Act
        var first = store.TryDecrementRemainingGathers(NodeId, out var previous, out var remaining);
        var second = store.TryDecrementRemainingGathers(NodeId, out _, out var afterDeny);

        // Assert
        Assert.True(first);
        Assert.Equal(1, previous);
        Assert.Equal(0, remaining);
        Assert.False(second);
        Assert.Equal(0, afterDeny);
        store.TryGetRemainingGathers(NodeId, out var persisted);
        Assert.Equal(0, persisted.RemainingGathers);
    }

    [Fact]
    public void TryGetRemainingGathers_ShouldNormalizeInteractableId()
    {
        // Arrange
        var store = new InMemoryResourceNodeInstanceStore();
        store.TryEnsureInitialized(NodeId, initialRemainingGathers: 7);

        // Act
        var found = store.TryGetRemainingGathers($"  {NodeId.ToUpperInvariant()}  ", out var snapshot);

        // Assert
        Assert.True(found);
        Assert.Equal(NodeId, snapshot.InteractableId);
        Assert.Equal(7, snapshot.RemainingGathers);
    }

    [Fact]
    public void TryGetRemainingGathers_ForUnknownId_ShouldReturnFalse()
    {
        // Arrange
        var store = new InMemoryResourceNodeInstanceStore();

        // Act
        var found = store.TryGetRemainingGathers("missing-node", out _);

        // Assert
        Assert.False(found);
    }
}
