using AsbCloudApp.Data;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace AsbCloudInfrastructure.Services;


public class MessageService : IMessageService
{
    private readonly IMessageRepository messageRepository;
    private readonly ITelemetryService telemetryService;
    private readonly IEventRepository eventRepository;

    public MessageService(
        IMessageRepository messageRepository,
        ITelemetryService telemetryService,
        IEventRepository eventRepository)
    {
        this.messageRepository = messageRepository;
        this.telemetryService = telemetryService;
        this.eventRepository = eventRepository;
    }

    public async Task<PaginationContainer<MessageDto>> GetPaginatedMessagesAsync(MessageRequest request, CancellationToken token)
    {
        var messageTelemetryRequest = await CreateMessageTelemetryRequest(request, token);

        var result = await messageRepository.GetPaginatedMessagesAsync(messageTelemetryRequest, token);
        return result;
    }

    public async Task<IEnumerable<StatCriticalMessageDto>> GetStatAsync(MessageRequest request, CancellationToken token)
    {
        var messageTelemetryRequest = await CreateMessageTelemetryRequest(request, token);

        var telemetryMessages = await messageRepository.GetMessagesAsync(messageTelemetryRequest, token);

        var groupedMessages = telemetryMessages.GroupBy(x => new { x.IdTelemetry, x.IdEvent });
        var events = messageTelemetryRequest.Events
            .GroupBy(e => e.Id)
            .ToDictionary(e => e.Key, e => e.FirstOrDefault());

        var idsWellsDict = messageTelemetryRequest.Telemetries.ToDictionary(e => e.Id, e => e.IdWell);

        var result = groupedMessages
            .Select(m => new
            {
                IdWell = idsWellsDict.GetValueOrDefault(m.Key.IdTelemetry),
                events.GetValueOrDefault(m.Key.IdEvent)?.IdCategory,
                events.GetValueOrDefault(m.Key.IdEvent)?.MessageTemplate,
                Count = m.Count(),
            })
            .Where(m => m.IdCategory != null)
            .Where(m => m.IdWell != null)
            .Where(m => m.MessageTemplate != null)
            .GroupBy(m => new { m.IdWell, m.IdCategory, m.MessageTemplate })
            .Select(m => new StatCriticalMessageDto()
            {
                IdWell = m.First().IdWell!.Value,
                IdCategory = m.Key.IdCategory,
                MessageTemplate = m.Key.MessageTemplate,
                MessagesCount = m.Select(z => z.Count).Sum()
            });

        return result;
    }

    public async Task<MessageTelemetryRequest> CreateMessageTelemetryRequest(MessageRequest request, CancellationToken token)
    {
        var telemetries = telemetryService.GetOrDefaultTelemetriesByIdsWells(request.IdsWell);
        
        var telemetryEventRequest = new TelemetryEventRequest()
        {
            IdsTelemetries = telemetries.Select(t => t.Id),
            IdsCategories = request.IdsCategories,
            SearchString = request.SearchString,
        };
        var events = await eventRepository.GetAsync(telemetryEventRequest, token);
        
        var messageTelemetryRequest = new MessageTelemetryRequest(request, events, telemetries);

        return messageTelemetryRequest;
    }
}