using TeleWave.Domain.Library;
using Xunit;

namespace TeleWave.Domain.Tests.Library;

public class CollectionTests
{
    private static IReadOnlyList<Guid> Order(Collection collection) =>
        collection.Items.OrderBy(i => i.Position).Select(i => i.ShowId).ToList();

    [Fact]
    public void AddShow_AppendsToEnd()
    {
        var collection = Collection.Create("Терминатор");
        var first = Guid.NewGuid();
        var second = Guid.NewGuid();

        collection.AddShow(first);
        collection.AddShow(second);

        Assert.Equal([first, second], Order(collection));
    }

    [Fact]
    public void AddShow_Duplicate_ReturnsNull()
    {
        var collection = Collection.Create("Терминатор");
        var showId = Guid.NewGuid();

        collection.AddShow(showId);

        Assert.Null(collection.AddShow(showId));
        Assert.Single(collection.Items);
    }

    [Fact]
    public void RemoveShow_ReturnsFalse_WhenNotPresent()
    {
        var collection = Collection.Create("Терминатор");

        Assert.False(collection.RemoveShow(Guid.NewGuid()));
    }

    [Fact]
    public void Reorder_AppliesRequestedOrder()
    {
        var collection = Collection.Create("Терминатор");
        var a = Guid.NewGuid();
        var b = Guid.NewGuid();
        var c = Guid.NewGuid();
        collection.AddShow(a);
        collection.AddShow(b);
        collection.AddShow(c);

        collection.Reorder([c, a, b]);

        Assert.Equal([c, a, b], Order(collection));
        Assert.Equal([0, 1, 2], collection.Items.OrderBy(i => i.Position).Select(i => i.Position));
    }

    [Fact]
    public void Reorder_KeepsUnmentionedAfterRequested_InOriginalOrder()
    {
        var collection = Collection.Create("Терминатор");
        var a = Guid.NewGuid();
        var b = Guid.NewGuid();
        var c = Guid.NewGuid();
        collection.AddShow(a);
        collection.AddShow(b);
        collection.AddShow(c);

        // Перетащили только один элемент — остальные не должны потеряться или перемешаться.
        collection.Reorder([c]);

        Assert.Equal([c, a, b], Order(collection));
    }

    [Fact]
    public void Reorder_IgnoresUnknownShows()
    {
        var collection = Collection.Create("Терминатор");
        var a = Guid.NewGuid();
        collection.AddShow(a);

        collection.Reorder([Guid.NewGuid(), a]);

        Assert.Equal([a], Order(collection));
    }

    [Fact]
    public void RemoveThenAdd_DoesNotReusePosition()
    {
        var collection = Collection.Create("Терминатор");
        var a = Guid.NewGuid();
        var b = Guid.NewGuid();
        collection.AddShow(a);
        collection.AddShow(b);

        collection.RemoveShow(a);
        var c = Guid.NewGuid();
        collection.AddShow(c);

        // Новая часть встаёт после существующих, а не занимает освободившийся номер.
        Assert.Equal([b, c], Order(collection));
    }
}
