using AyCode.Core.Helpers;
using AyCode.Core.Tests.TestModels;

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

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

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

        Assert.AreEqual(3, dataSource.Count);
        Assert.AreEqual("Product A", dataSource[0].ProductName);
        Assert.AreEqual("Product B", dataSource[1].ProductName);
        Assert.AreEqual("Product C", dataSource[2].ProductName);
    }

    [TestMethod]
    public virtual async Task LoadDataSource_ClearsChangeTracking_ByDefault()
    {
        var dataSource = CreateDataSource(_client, _crudTags);
        dataSource.Add(new TestOrderItem_All_True { Id = 999, ProductName = "Tracked" });

        Assert.AreEqual(1, dataSource.GetTrackingItems().Count);

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

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

        dataSource.Add(new TestOrderItem_All_True { Id = 999, ProductName = "Tracked" });
        await dataSource.LoadDataSource(clearChangeTracking: false);

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

    [TestMethod]
    public virtual async Task LoadDataSource_InvokesOnDataSourceLoaded()
    {
        var dataSource = CreateDataSource(_client, _crudTags);

        var callbackInvoked = false;
        dataSource.OnDataSourceLoaded = () => { callbackInvoked = true; return Task.CompletedTask; };
        await dataSource.LoadDataSource();

        Assert.IsTrue(callbackInvoked);
    }

    [TestMethod]
    public virtual async Task LoadDataSource_MultipleCalls_RefreshesData()
    {
        var dataSource = CreateDataSource(_client, _crudTags);

        await dataSource.LoadDataSource();
        var firstCount = dataSource.Count;

        await dataSource.LoadDataSource();
        var secondCount = dataSource.Count;

        Assert.AreEqual(firstCount, secondCount);
        Assert.AreEqual(3, secondCount);
    }

    #endregion

    #region LoadDataSourceAsync Tests

    [TestMethod]
    public virtual async Task LoadDataSourceAsync_LoadsDataViaCallback()
    {
        var dataSource = CreateDataSource(_client, _crudTags);

        var loadCompleted = false;
        dataSource.OnDataSourceLoaded = () =>
        {
            loadCompleted = true;
            return Task.CompletedTask;
        };

        await dataSource.LoadDataSourceAsync();

        Assert.IsTrue(TaskHelper.WaitTo(() => loadCompleted, 5000));
        Assert.AreEqual(3, dataSource.Count);
    }

    #endregion
}
