using AsbCloudApp.Data;
using AsbCloudApp.Data.SAUB;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services;
using NSubstitute;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Xunit;

namespace AsbCloudInfrastructure.Tests.Services;

public class MessageServiceTest
{
    private static readonly List<TelemetryDto> telemetries = new List<TelemetryDto>()
    {
        new TelemetryDto()
        {
            Id = 1,
            IdWell = 1,
            TimeZone = new SimpleTimezoneDto()
            {
                Hours = 5
            }
        },
         new TelemetryDto()
         {
            Id = 2,
            IdWell = 2,
            TimeZone = new SimpleTimezoneDto()
            {
                Hours = 5
            }
         }
    };

    private static readonly List<TelemetryEventDto> events = new List<TelemetryEventDto>()
    {
        new TelemetryEventDto()
        {
            Id = 1,
            IdCategory = 1,
            MessageTemplate = "Шаблон сообщения 1 категории 1"
        },
        new TelemetryEventDto()
        {
            Id = 2,
            IdCategory = 1,
            MessageTemplate = "Шаблон сообщения 2 категории 1"
        },
        new TelemetryEventDto()
        {
            Id = 3,
            IdCategory = 1,
            MessageTemplate = "Шаблон сообщения 3 категории 1"
        },
        new TelemetryEventDto()
        {
            Id = 4,
            IdCategory = 2,
            MessageTemplate = "Шаблон сообщения 1 категории 2"
        },
        new TelemetryEventDto()
        {
            Id = 5,
            IdCategory = 2,
            MessageTemplate = "Шаблон сообщения 2 категории 2"
        },
        new TelemetryEventDto()
        {
            Id = 6,
            IdCategory = 3,
            MessageTemplate = "Шаблон сообщения 1 категории 3"
        }
    };

    /// <summary>
    /// Структура:
    /// Телеметрия 1:
    ///     Категория 1:
    ///         Событие 1: 
    ///             Сообщение 1
    ///             Сообщение 2
    ///             Сообщение 3
    ///         Событие 2: 
    ///             Сообщение 1
    ///             Сообщение 2
    ///             Сообщение 3
    ///         Событие 3: 
    ///             Сообщение 1
    ///             Сообщение 2
    ///             Сообщение 3
    ///      Категория 2:
    ///         Событие 2: 
    ///             Сообщение 1
    ///             Сообщение 2
    ///         Событие 3: 
    ///             Сообщение 1
    ///             Сообщение 2
    /// Телеметрия 2
    ///     Категория 3:
    ///         Событие 3: 
    ///             Сообщение 1
    ///             Сообщение 2
    ///             Сообщение 3
    ///             
    /// </summary>
    private static readonly List<TelemetryMessageDto> messages = new List<TelemetryMessageDto>()
    {
        new TelemetryMessageDto()
        {
            Id = 1,
            IdEvent = 1,
            IdTelemetry = 1
        },
        new TelemetryMessageDto()
        {
            Id = 2,
            IdEvent = 1,
            IdTelemetry = 1
        },
        new TelemetryMessageDto()
        {
            Id = 3,
            IdEvent = 1,
            IdTelemetry = 1
        },
        new TelemetryMessageDto()
        {
            Id = 4,
            IdEvent = 2,
            IdTelemetry = 1
        },
        new TelemetryMessageDto()
        {
            Id = 5,
            IdEvent = 2,
            IdTelemetry = 1
        },
        new TelemetryMessageDto()
        {
            Id = 6,
            IdEvent = 2,
            IdTelemetry = 1
        },
        new TelemetryMessageDto()
        {
            Id = 7,
            IdEvent = 3,
            IdTelemetry = 1
        },
        new TelemetryMessageDto()
        {
            Id = 8,
            IdEvent = 3,
            IdTelemetry = 1
        },
        new TelemetryMessageDto()
        {
            Id = 9,
            IdEvent = 3,
            IdTelemetry = 1
        },
        new TelemetryMessageDto()
        {
            Id = 10,
            IdEvent = 4,
            IdTelemetry = 1
        },
        new TelemetryMessageDto()
        {
            Id = 11,
            IdEvent = 4,
            IdTelemetry = 1
        },
        new TelemetryMessageDto()
        {
            Id = 12,
            IdEvent = 5,
            IdTelemetry = 1
        },
        new TelemetryMessageDto()
        {
            Id = 13,
            IdEvent = 5,
            IdTelemetry = 1
        },
        new TelemetryMessageDto()
        {
            Id = 14,
            IdEvent = 6,
            IdTelemetry = 2
        },
         new TelemetryMessageDto()
        {
            Id = 15,
            IdEvent = 6,
            IdTelemetry = 2
        },
          new TelemetryMessageDto()
        {
            Id = 16,
            IdEvent = 6,
            IdTelemetry = 2
        },
    };



    private readonly IMessageService messageServiceMock = Substitute.For<IMessageService>();
    private readonly IMessageRepository messageRepositoryMock = Substitute.For<IMessageRepository>();
    private readonly IEventRepository eventRepositoryMock = Substitute.For<IEventRepository>();
    private readonly ITelemetryService telemetryServiceMock = Substitute.For<ITelemetryService>();

    public MessageServiceTest()
    {
        messageServiceMock = new MessageService(messageRepositoryMock, telemetryServiceMock, eventRepositoryMock);

        telemetryServiceMock
            .GetOrDefaultTelemetriesByIdsWells(Arg.Any<IEnumerable<int>>())
            .Returns(telemetries);

        eventRepositoryMock
            .GetAsync(Arg.Any<TelemetryEventRequest>(), Arg.Any<CancellationToken>())
            .Returns(events);

        messageRepositoryMock
            .GetMessagesAsync(Arg.Any<MessageTelemetryRequest>(), Arg.Any<CancellationToken>())
            .Returns(messages);
    }


    [Fact]
    public async Task GetStatMessages_ShouldReturn_Success()
    {
        //act
        var baseRequest = new MessageRequestBase() { };
        var messageRequest = new MessageRequest(baseRequest, [1]);
        var result = await messageServiceMock.GetStatAsync(messageRequest, CancellationToken.None);

        Assert.Equal(6, result.Count());

        AssertStatByEvent(result, 1, events[0], 3);
        AssertStatByEvent(result, 1, events[1], 3);
        AssertStatByEvent(result, 1, events[2], 3);
        AssertStatByEvent(result, 1, events[3], 2);
        AssertStatByEvent(result, 1, events[4], 2);
        AssertStatByEvent(result, 2, events[5], 3);
    }

    private void AssertStatByEvent(IEnumerable<StatCriticalMessageDto> result, int idWell, TelemetryEventDto eventDto, int count)
    {
        var eventStats = result
             .Where(x => x.IdWell == idWell)
             .Where(x => x.IdCategory == eventDto.IdCategory)
             .Where(x => x.MessageTemplate == eventDto.MessageTemplate)
             .ToArray();

        Assert.Single(eventStats);
        var eventStat = eventStats.First();
        Assert.Equal(count, eventStat.MessagesCount);
    }


}