using Microsoft.Extensions.Logging.Abstractions;
using TeamsISO.Engine.Domain;
using TeamsISO.Engine.Persistence;

namespace TeamsISO.Engine.Tests.Persistence;

public class ConfigStoreTests : IDisposable
{
    private readonly string _dir;

    public ConfigStoreTests()
    {
        _dir = Path.Combine(Path.GetTempPath(), $"teamsiso-tests-{Guid.NewGuid():N}");
        Directory.CreateDirectory(_dir);
    }

    public void Dispose() => Directory.Delete(_dir, recursive: true);

    private ConfigStore NewStore() =>
        new(Path.Combine(_dir, "config.json"), NullLogger<ConfigStore>.Instance);

    [Fact]
    public void Load_WhenFileMissing_ReturnsDefault()
    {
        var store = NewStore();
        var config = store.Load();
        config.Should().Be(EngineConfig.Default);
    }

    [Fact]
    public void SaveThenLoad_RoundTripsExactly()
    {
        var store = NewStore();
        var input = new EngineConfig(
            new FrameProcessingSettings(TargetFramerate.Fps59_94, TargetResolution.R720p,
                AspectMode.Letterbox, AudioMode.Isolated),
            new[]
            {
                new IsoAssignment(Guid.NewGuid(), IsEnabled: true, CustomOutputName: "TEAMSISO_A"),
                new IsoAssignment(Guid.NewGuid(), IsEnabled: false, CustomOutputName: null),
            });

        store.Save(input);
        var loaded = store.Load();

        loaded.Should().BeEquivalentTo(input);
    }

    [Fact]
    public void Load_WhenFileCorrupt_ReturnsDefault()
    {
        var path = Path.Combine(_dir, "config.json");
        File.WriteAllText(path, "not valid json {{{");

        var store = NewStore();
        var config = store.Load();
        config.Should().Be(EngineConfig.Default);
    }

    [Fact]
    public void Save_WritesAtomically_NoPartialFileVisible()
    {
        var store = NewStore();
        var path = Path.Combine(_dir, "config.json");

        store.Save(EngineConfig.Default);
        var firstWrite = File.ReadAllText(path);

        store.Save(new EngineConfig(
            FrameProcessingSettings.Default with { Framerate = TargetFramerate.Fps60 },
            Array.Empty<IsoAssignment>()));

        File.Exists(path).Should().BeTrue();
        File.ReadAllText(path).Should().NotBe(firstWrite);
        Directory.GetFiles(_dir).Should().HaveCount(1);
    }
}
