namespace NeonSprawl.Server.Game.Gathering;

/// <summary>Registry-backed lazy init and atomic depletion commits for world node instances (NEO-61).</summary>
public static class ResourceNodeInstanceOperations
{
    /// <summary>
    /// Decrements remaining gathers by one after lazy-init from catalog <c>maxGathers</c>. Interact wiring (NEO-63)
    /// maps <see cref="ResourceNodeInstanceReasonCodes.NodeDepleted"/> to denied interact responses.
    /// </summary>
    public static ResourceNodeInstanceMutationOutcome TryCommitSuccessfulGatherDecrement(
        string interactableId,
        IResourceNodeDefinitionRegistry registry,
        IResourceNodeInstanceStore store)
    {
        var key = ResourceNodeInstanceIds.Normalize(interactableId);
        if (key.Length == 0 || !registry.TryGetDefinition(key, out var definition))
        {
            return new ResourceNodeInstanceMutationOutcome(
                ResourceNodeInstanceMutationKind.Denied,
                ResourceNodeInstanceReasonCodes.UnknownNode,
                null);
        }

        if (!store.TryGetRemainingGathers(key, out _))
        {
            if (!store.TryEnsureInitialized(key, definition.MaxGathers))
            {
                throw new InvalidOperationException(
                    $"Failed to initialize resource node instance '{key}' with maxGathers {definition.MaxGathers}.");
            }
        }

        if (store.TryDecrementRemainingGathers(key, out _, out var remaining))
        {
            return new ResourceNodeInstanceMutationOutcome(
                ResourceNodeInstanceMutationKind.Applied,
                null,
                new ResourceNodeInstanceSnapshot(key, remaining));
        }

        if (!store.TryGetRemainingGathers(key, out var current))
        {
            current = new ResourceNodeInstanceSnapshot(key, 0);
        }

        return new ResourceNodeInstanceMutationOutcome(
            ResourceNodeInstanceMutationKind.Denied,
            ResourceNodeInstanceReasonCodes.NodeDepleted,
            current);
    }
}
