using AsbCloudApp.Data.SAUB;
using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using AsbCloudWebApi.SignalR;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace AsbCloudWebApi.Controllers.SAUB;

/// <summary>
/// Инфо о передающих телеметрию устройствах
/// </summary>
[Route("api/telemetry")]
[ApiController]
public class TelemetryController : ControllerBase
{
    private readonly ITelemetryService telemetryService;
    private readonly IMessageRepository messageRepository;
    private readonly IEventRepository eventRepository;
    private readonly ITelemetryUserService telemetryUserService;
    private readonly IHubContext<TelemetryHub> telemetryHubContext;

    public TelemetryController(
        ITelemetryService telemetryService,
        IMessageRepository messageRepository,
        IEventRepository eventRepository,
        ITelemetryUserService telemetryUserService,
        IHubContext<TelemetryHub> telemetryHubContext)
    {
        this.telemetryService = telemetryService;
        this.messageRepository = messageRepository;
        this.eventRepository = eventRepository;
        this.telemetryUserService = telemetryUserService;
        this.telemetryHubContext = telemetryHubContext;
    }

    /// <summary>
    /// Информация о версиях ПО по телеметриям, данные от которых приходили не позднее From
    /// </summary>
    /// <returns></returns>
    [HttpGet("Active")]
    [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)]
    public async Task<IActionResult> GetTelemetriesInfoByLastData(CancellationToken token)
    {
        var from = DateTimeOffset.UtcNow.AddDays(-1);
        var stream = await telemetryService.GetTelemetriesInfoByLastData(from, token);
        return File(stream, "text/csv", $"Software versions by active telemetries from {from:yy-MM-dd hh-mm}.csv");
    }

    /// <summary>
    /// Принимает общую информацию по скважине
    /// </summary>
    /// <param name="uid">Уникальный идентификатор отправителя</param>
    /// <param name="info">Информация об отправителе</param>
    /// <param name="token">Токен отмены задачи</param>
    /// <returns></returns>
    [HttpPost("{uid}/info")]
    public async Task<IActionResult> PostInfoAsync(string uid, [FromBody] TelemetryInfoDto info,
        CancellationToken token)
    {
        await telemetryService.UpdateInfoAsync(uid, info, token).ConfigureAwait(false);
        return Ok();
    }

    /// <summary>
    /// Принимает список новых сообщений от телеметрии
    /// </summary>
    /// <param name="uid">Уникальный идентификатор отправителя</param>
    /// <param name="dtos">сообщения</param>
    /// <param name="token">Токен для отмены задачи</param>
    /// <returns></returns>
    [HttpPost("{uid}/message")]
    public async Task<IActionResult> PostMessagesAsync(string uid, [FromBody] IEnumerable<TelemetryMessageDto> dtos,
        CancellationToken token)
    {
        var idWell = telemetryService.GetIdWellByTelemetryUid(uid);
        await messageRepository.InsertAsync(uid, dtos, token).ConfigureAwait(false);

        if (dtos.Any())
            await Task.Run(() => telemetryHubContext.Clients.Group($"well_{idWell}")
            .SendAsync("ReceiveMessages", dtos), token).ConfigureAwait(false);

        return Ok();
    }

    /// <summary>
    /// Принимает справочник событий
    /// </summary>
    /// <param name="uid">Уникальный идентификатор отправителя</param>
    /// <param name="events">справочник событий</param>
    /// <param name="token">Токен для отмены задачи</param>
    /// <returns></returns>
    [HttpPost("{uid}/event")]
    public async Task<IActionResult> PostEventsAsync(string uid, [FromBody] List<EventDto> events,
        CancellationToken token)
    {
        await eventRepository.UpsertAsync(uid, events, token)
            .ConfigureAwait(false);
        return Ok();
    }

    /// <summary>
    /// Принимает справочник пользователей телеметрии
    /// </summary>
    /// <param name="uid">Уникальный идентификатор отправителя</param>
    /// <param name="users">справочник пользователей телеметрии</param>
    /// <param name="token"></param>
    /// <returns></returns>
    [HttpPost("{uid}/user")]
    public async Task<IActionResult> PostUsersAsync(string uid, [FromBody] List<TelemetryUserDto> users,
        CancellationToken token)
    {
        await telemetryUserService.UpsertAsync(uid, users, token);
        return Ok();
    }
}