using ErsatzTV.Application.Maintenance;
using ErsatzTV.Core.FFmpeg;
using ErsatzTV.Core.Interfaces.FFmpeg;
using Microsoft.Extensions.Logging;
using NSubstitute;
using NUnit.Framework;
using Shouldly;

namespace ErsatzTV.Tests.Application.Maintenance;

[TestFixture]
[NonParallelizable]
public class ReleaseMemoryHandlerTests
{
    [Test]
    public async Task Should_Use_Aggressive_Collection_When_No_Workers_Are_Active()
    {
        FFmpegProcess.ProcessCount.ShouldBe(0);

        IFFmpegSegmenterService segmenterService = Substitute.For<IFFmpegSegmenterService>();
        segmenterService.Workers.Returns([]);
        ILogger<ReleaseMemoryHandler> logger = Substitute.For<ILogger<ReleaseMemoryHandler>>();
        var handler = new ReleaseMemoryHandler(segmenterService, logger);

        await handler.Handle(new ReleaseMemory(false), CancellationToken.None);

        ShouldHaveLogged(logger, "Starting aggressive garbage collection");
    }

    [Test]
    public async Task Should_Use_Regular_Collection_When_A_Worker_Is_Active()
    {
        FFmpegProcess.ProcessCount.ShouldBe(0);

        IFFmpegSegmenterService segmenterService = Substitute.For<IFFmpegSegmenterService>();
        segmenterService.Workers.Returns([Substitute.For<IHlsSessionWorker>()]);
        ILogger<ReleaseMemoryHandler> logger = Substitute.For<ILogger<ReleaseMemoryHandler>>();
        var handler = new ReleaseMemoryHandler(segmenterService, logger);

        await handler.Handle(new ReleaseMemory(false), CancellationToken.None);

        ShouldHaveLogged(logger, "Starting garbage collection");
    }

    private static void ShouldHaveLogged(ILogger<ReleaseMemoryHandler> logger, string expectedMessage) =>
        logger.ReceivedCalls()
            .Any(call => call.GetArguments().ElementAtOrDefault(2)?.ToString() == expectedMessage)
            .ShouldBeTrue();
}
