using C4IT.FASD.Base;
using FasdDesktopUi.Basics.CustomEvents;
using FasdDesktopUi.Basics.Services.RelationService;
using FasdDesktopUi.Basics.Services.SupportCase;
using NSubstitute;

namespace F4SD.Cockpit.Client.Test.Basics.Sevices.SupportCase;

public class SupportCaseTest
{
    private readonly ISupportCase _supportCase;
    private readonly IRelationService _relationService;

    public SupportCaseTest()
    {
        _relationService = Substitute.For<IRelationService>();
        cF4sdIdentityEntry primaryIdentity = new() { Class = enumFasdInformationClass.User, Id = Guid.NewGuid() };
        _supportCase = SupportCaseFactory.Get(primaryIdentity, _relationService, null);
    }

    [Fact]
    public void GetCaseRelations_Contains_AddCaseRelations()
    {
        var actualRelations = _supportCase.GetCaseRelations();
        Assert.Empty(actualRelations);

        ILookup<enumFasdInformationClass, cF4sdApiSearchResultRelation> relations = new List<cF4sdApiSearchResultRelation>()
        {
            new() { Type = enumF4sdSearchResultClass.Computer, Name = "My computer", Identities = [
                new() { Id = Guid.NewGuid(), Class = enumFasdInformationClass.Computer }
                ] }
        }.ToLookup(r => cF4sdIdentityEntry.GetFromSearchResult(r.Type), r => r);

        _supportCase.AddCaseRelations(relations);

        actualRelations = _supportCase.GetCaseRelations();
        Assert.Single(actualRelations);
        Assert.Contains(relations.FirstOrDefault(), actualRelations);
    }

    [Fact]
    public void AddCaseRelations_Raise_CaseRelationsAdded()
    {
        ILookup<enumFasdInformationClass, cF4sdApiSearchResultRelation> relations = new List<cF4sdApiSearchResultRelation>()
        {
            new()
            {
                Type = enumF4sdSearchResultClass.Computer,
                Name = "My computer",
                Identities =
                [
                    new() { Id = Guid.NewGuid(), Class = enumFasdInformationClass.Computer }
                ]
            }
        }.ToLookup(r => cF4sdIdentityEntry.GetFromSearchResult(r.Type), r => r);

        var raisedEvent = Assert.Raises<RelationEventArgs>(
            h => _supportCase.CaseRelationsAdded += h,
            h => _supportCase.CaseRelationsAdded -= h,
            () => _supportCase.AddCaseRelations(relations));

        Assert.NotNull(raisedEvent);
        Assert.Equal(_supportCase, raisedEvent.Sender);
        Assert.Equal(relations, raisedEvent.Arguments.Relations);
    }

    [Fact]
    public void UpdateSupportCaseDataCache_Raise_SupportCaseDataCacheHasChanged()
    {
        cF4sdApiSearchResultRelation relation = new()
        {
            Type = enumF4sdSearchResultClass.Computer,
            Name = "My computer",
            Identities =
            [
                new() { Id = Guid.NewGuid(), Class = enumFasdInformationClass.Computer }
            ]
        };

        List<cF4SDHealthCardRawData.cHealthCardTable> tables =
            [
                new() { Name = "TestTable1", Columns = [], TableType = eDataHistoryTableType.History },
            ];

        var raisedEvent = Assert.Raises<SupportCaseDataEventArgs>(
            h => _supportCase.SupportCaseDataCacheHasChanged += h,
            h => _supportCase.SupportCaseDataCacheHasChanged -= h,
            () => _supportCase.UpdateSupportCaseDataCache(relation, tables));
        Assert.NotNull(raisedEvent);
        Assert.Equal(_supportCase, raisedEvent.Sender);
        Assert.Equal(relation, raisedEvent.Arguments.Relation);
        Assert.Equal(tables, raisedEvent.Arguments.DataTables);
    }

    [Fact]
    public void GetSupportCaseData_Contains_UpdateSupportCaseDataCacheData()
    {
        // Arrange
        const string columnValue = "Hello world";
        const string tableName = "TestTable1";
        const string columnName = "TestColumn1";
        List<object> expected = [columnValue];


        cF4sdApiSearchResultRelation relation = new()
        {
            Type = enumF4sdSearchResultClass.Computer,
            Name = "My computer",
            Identities =
            [
                new() { Id = Guid.NewGuid(), Class = enumFasdInformationClass.Computer }
            ]
        };

        cF4SDHealthCardRawData.cHealthCardTable dataTable = new()
        {
            Name = tableName,
            TableType = eDataHistoryTableType.History
        };
        dataTable.Columns = new()
        {
            [columnName] = new(dataTable) { Values = expected }
        };

        // Act
        _supportCase.UpdateSupportCaseDataCache(relation, [dataTable]);

        // Assert
        var actual = _supportCase.GetSupportCaseHealthcardData(relation, new cValueAddress() { ValueTable = tableName, ValueColumn = columnName });

        Assert.Equal(expected, actual);
    }

    [Fact]
    public void GetSupportCaseData_ReturnsNull_When_NoDataExists()
    {
        // Arrange
        cF4sdApiSearchResultRelation relation = new()
        {
            Type = enumF4sdSearchResultClass.Computer,
            Name = "My computer",
            Identities =
            [
                new() { Id = Guid.NewGuid(), Class = enumFasdInformationClass.Computer }
            ]
        };
        // Act
        var actual = _supportCase.GetSupportCaseHealthcardData(relation, new cValueAddress() { ValueTable = "NonExistentTable", ValueColumn = "NonExistentColumn" });
        // Assert
        Assert.Null(actual);
    }
}
