using FasdDesktopUi.Basics.Services.Models;

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

public class TicketOverviewCountProcessorTest
{
    private static readonly string[] OverviewKeys = ["TicketsNew", "IncidentNew"];

    [Fact]
    public void Calculate_PersonalScope_UpdatesOnlyPersonalAndReturnsDeltaChanges()
    {
        // Arrange
        Dictionary<string, TileCounts> current = new(StringComparer.OrdinalIgnoreCase)
        {
            ["TicketsNew"] = new TileCounts(1, 7),
            ["IncidentNew"] = new TileCounts(2, 8)
        };
        Dictionary<string, int> incoming = new(StringComparer.OrdinalIgnoreCase)
        {
            ["TicketsNew"] = 5,
            ["IncidentNew"] = 2
        };

        // Act
        ScopeCountProcessingResult result = TicketOverviewCountProcessor.Calculate(
            current,
            OverviewKeys,
            TileScope.Personal,
            incoming,
            hasInitializedScope: true);

        // Assert
        Assert.False(result.IsInitialization);
        Assert.Equal(5, result.UpdatedCounts["TicketsNew"].Personal);
        Assert.Equal(7, result.UpdatedCounts["TicketsNew"].Role);
        Assert.Equal(2, result.UpdatedCounts["IncidentNew"].Personal);
        Assert.Equal(8, result.UpdatedCounts["IncidentNew"].Role);

        Assert.Single(result.Changes);
        TileCountChange change = result.Changes[0];
        Assert.Equal("TicketsNew", change.Key);
        Assert.Equal(TileScope.Personal, change.Scope);
        Assert.Equal(1, change.OldCount);
        Assert.Equal(5, change.NewCount);
        Assert.Equal(4, change.Delta);
    }

    [Fact]
    public void Calculate_RoleScope_UpdatesOnlyRoleAndReturnsDeltaChanges()
    {
        // Arrange
        Dictionary<string, TileCounts> current = new(StringComparer.OrdinalIgnoreCase)
        {
            ["TicketsNew"] = new TileCounts(10, 3),
            ["IncidentNew"] = new TileCounts(4, 6)
        };
        Dictionary<string, int> incoming = new(StringComparer.OrdinalIgnoreCase)
        {
            ["TicketsNew"] = 3,
            ["IncidentNew"] = 9
        };

        // Act
        ScopeCountProcessingResult result = TicketOverviewCountProcessor.Calculate(
            current,
            OverviewKeys,
            TileScope.Role,
            incoming,
            hasInitializedScope: true);

        // Assert
        Assert.False(result.IsInitialization);
        Assert.Equal(10, result.UpdatedCounts["TicketsNew"].Personal);
        Assert.Equal(3, result.UpdatedCounts["TicketsNew"].Role);
        Assert.Equal(4, result.UpdatedCounts["IncidentNew"].Personal);
        Assert.Equal(9, result.UpdatedCounts["IncidentNew"].Role);

        Assert.Single(result.Changes);
        TileCountChange change = result.Changes[0];
        Assert.Equal("IncidentNew", change.Key);
        Assert.Equal(TileScope.Role, change.Scope);
        Assert.Equal(6, change.OldCount);
        Assert.Equal(9, change.NewCount);
        Assert.Equal(3, change.Delta);
    }

    [Fact]
    public void Calculate_FirstInitialization_DoesNotReturnDeltaChanges()
    {
        // Arrange
        Dictionary<string, TileCounts> current = new(StringComparer.OrdinalIgnoreCase)
        {
            ["TicketsNew"] = new TileCounts(0, 0),
            ["IncidentNew"] = new TileCounts(0, 0)
        };
        Dictionary<string, int> incoming = new(StringComparer.OrdinalIgnoreCase)
        {
            ["TicketsNew"] = 4,
            ["IncidentNew"] = 1
        };

        // Act
        ScopeCountProcessingResult result = TicketOverviewCountProcessor.Calculate(
            current,
            OverviewKeys,
            TileScope.Personal,
            incoming,
            hasInitializedScope: false);

        // Assert
        Assert.True(result.IsInitialization);
        Assert.Empty(result.Changes);
        Assert.Equal(4, result.UpdatedCounts["TicketsNew"].Personal);
        Assert.Equal(1, result.UpdatedCounts["IncidentNew"].Personal);
    }

    [Fact]
    public void Calculate_MissingIncomingValues_DefaultsToZero()
    {
        // Arrange
        Dictionary<string, TileCounts> current = new(StringComparer.OrdinalIgnoreCase)
        {
            ["TicketsNew"] = new TileCounts(5, 1),
            ["IncidentNew"] = new TileCounts(2, 4)
        };
        Dictionary<string, int> incoming = new(StringComparer.OrdinalIgnoreCase)
        {
            ["TicketsNew"] = 5
        };

        // Act
        ScopeCountProcessingResult result = TicketOverviewCountProcessor.Calculate(
            current,
            OverviewKeys,
            TileScope.Personal,
            incoming,
            hasInitializedScope: true);

        // Assert
        Assert.Equal(5, result.UpdatedCounts["TicketsNew"].Personal);
        Assert.Equal(1, result.UpdatedCounts["TicketsNew"].Role);
        Assert.Equal(0, result.UpdatedCounts["IncidentNew"].Personal);
        Assert.Equal(4, result.UpdatedCounts["IncidentNew"].Role);

        Assert.Single(result.Changes);
        Assert.Equal("IncidentNew", result.Changes[0].Key);
        Assert.Equal(2, result.Changes[0].OldCount);
        Assert.Equal(0, result.Changes[0].NewCount);
    }
}
