using AyCode.Core.Enums;
using AyCode.Core.Tests.TestModels;

namespace AyCode.Services.Server.Tests.SignalRs.SignalRDatasources;

public abstract partial class SignalRDataSourceTestBase<TDataSource, TIList>
{
    #region Tracking Tests

    [TestMethod]
    public virtual void SetTrackingStateToUpdate_MarksItemForUpdate()
    {
        var dataSource = CreateDataSource(_client, _crudTags);

        dataSource.Add(new TestOrderItem_All_True { Id = 1, ProductName = "Test" });

        dataSource.SetTrackingStateToUpdate(dataSource[0]);

        Assert.AreEqual(1, dataSource.GetTrackingItems().Count);
        Assert.AreEqual(TrackingState.Update, dataSource.GetTrackingItems()[0].TrackingState);
    }

    [TestMethod]
    public virtual void SetTrackingStateToUpdate_DoesNotChangeAddState()
    {
        var dataSource = CreateDataSource(_client, _crudTags);

        dataSource.Add(new TestOrderItem_All_True { Id = 1, ProductName = "New Item" });
        dataSource.SetTrackingStateToUpdate(dataSource[0]);

        Assert.AreEqual(TrackingState.Add, dataSource.GetTrackingItems()[0].TrackingState);
    }

    [TestMethod]
    public virtual void TryGetTrackingItem_ReturnsTrue_WhenTracked()
    {
        var dataSource = CreateDataSource(_client, _crudTags);

        dataSource.Add(new TestOrderItem_All_True { Id = 1, ProductName = "Tracked" });
        var result = dataSource.TryGetTrackingItem(1, out var trackingItem);

        Assert.IsTrue(result);
        Assert.IsNotNull(trackingItem);
        Assert.AreEqual(TrackingState.Add, trackingItem.TrackingState);
    }

    [TestMethod]
    public virtual void TryGetTrackingItem_ReturnsFalse_WhenNotTracked()
    {
        var dataSource = CreateDataSource(_client, _crudTags);
        var result = dataSource.TryGetTrackingItem(9999, out var trackingItem);

        Assert.IsFalse(result);
        Assert.IsNull(trackingItem);
    }

    #endregion

    #region Rollback Tests

    [TestMethod]
    public virtual void TryRollbackItem_RevertsAddedItem()
    {
        var dataSource = CreateDataSource(_client, _crudTags);

        dataSource.Add(new TestOrderItem_All_True { Id = 1, ProductName = "Added" });
        var result = dataSource.TryRollbackItem(1, out var originalValue);

        Assert.IsTrue(result);
        Assert.AreEqual(0, dataSource.Count);
        Assert.AreEqual(0, dataSource.GetTrackingItems().Count);
    }

    [TestMethod]
    public virtual async Task TryRollbackItem_RevertsUpdatedItem()
    {
        var dataSource = CreateDataSource(_client, _crudTags);
        await dataSource.LoadDataSource();

        var originalName = dataSource[0].ProductName;
        dataSource[0] = new TestOrderItem_All_True { Id = dataSource[0].Id, ProductName = "Changed" };
        var result = dataSource.TryRollbackItem(dataSource[0].Id, out var originalValue);

        Assert.IsTrue(result);
        Assert.IsNotNull(originalValue);
    }

    [TestMethod]
    public virtual void Rollback_RevertsAllChanges()
    {
        var dataSource = CreateDataSource(_client, _crudTags);

        dataSource.Add(new TestOrderItem_All_True { Id = 1, ProductName = "Item1" });
        dataSource.Add(new TestOrderItem_All_True { Id = 2, ProductName = "Item2" });
        dataSource.Rollback();

        Assert.AreEqual(0, dataSource.Count);
        Assert.AreEqual(0, dataSource.GetTrackingItems().Count);
    }

    #endregion
}
