using Shouldly;
using ZB.MOM.NatsNet.Server.Internal;

namespace ZB.MOM.NatsNet.Server.Tests.Internal;

/// <summary>
/// Tests for <see cref="ProcessStatsProvider"/>, mirroring pse_test.go.
/// The Go tests compare against `ps` command output — the .NET tests verify
/// that values are within reasonable bounds since Process gives us the same data
/// through a managed API without needing external command comparison.
/// </summary>
public sealed class ProcessStatsProviderTests
{
    [Fact]
    public async Task PSEmulationCPU_ShouldReturnReasonableValue()
    {
        // Mirror: TestPSEmulationCPU
        // Allow one sampling cycle to complete.
        await Task.Delay(TimeSpan.FromSeconds(2));

        ProcessStatsProvider.ProcUsage(out var pcpu, out _, out _);

        // CPU % should be non-negative and at most 100% × processor count.
        pcpu.ShouldBeGreaterThanOrEqualTo(0);
        pcpu.ShouldBeLessThanOrEqualTo(100.0 * Environment.ProcessorCount);
    }

    [Fact]
    public void PSEmulationMem_ShouldReturnReasonableValue()
    {
        // Mirror: TestPSEmulationMem
        ProcessStatsProvider.ProcUsage(out _, out var rss, out var vss);

        // RSS should be at least 1 MB (any .NET process uses far more).
        rss.ShouldBeGreaterThan(1024L * 1024L);

        // VSS should be at least as large as RSS.
        vss.ShouldBeGreaterThanOrEqualTo(rss);
    }

    [Fact]
    public async Task PSEmulationWin_ShouldCacheAndRefresh()
    {
        // Mirror: TestPSEmulationWin (caching behaviour validation)
        ProcessStatsProvider.ProcUsage(out _, out var rss1, out _);
        ProcessStatsProvider.ProcUsage(out _, out var rss2, out _);

        // Two immediate calls should return the same cached value.
        rss1.ShouldBe(rss2);

        // After a sampling interval, values should still be valid.
        await Task.Delay(TimeSpan.FromSeconds(2));
        ProcessStatsProvider.ProcUsage(out _, out var rssAfter, out _);
        rssAfter.ShouldBeGreaterThan(0);
    }
}
