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

namespace AsbCloudWebApi.Controllers
{
    /// <summary>
    /// Контроллер сбора данных от буровых
    /// </summary>
    [Route("api/telemetry")]
    [ApiController]
    public class TelemetryController : ControllerBase
    {
        private readonly IDataService DataService;
        private readonly ITelemetryService telemetryService;
        private readonly IMessageService messageService;
        private readonly IEventService eventService;
        private readonly ITelemetryUserService telemetryUserService;
        private readonly IHubContext<TelemetryHub> telemetryHubContext;
        private readonly ITelemetryTracker telemetryTracker;

        public TelemetryController(
            ITelemetryService telemetryService,
            IDataService DataService,
            IMessageService messageService,
            IEventService eventService,
            ITelemetryUserService telemetryUserService,
            IHubContext<TelemetryHub> telemetryHubContext,
            ITelemetryTracker telemetryTracker)
        {
            this.DataService = DataService;
            this.telemetryService = telemetryService;
            this.messageService = messageService;
            this.eventService = eventService;
            this.telemetryUserService = telemetryUserService;
            this.telemetryHubContext = telemetryHubContext;
            this.telemetryTracker = telemetryTracker;
        }

        /// <summary>
        /// Принимает общую информацию по скважине
        /// </summary>
        /// <param name="uid">Уникальный идентификатор отправителя</param>
        /// <param name="info">нформация об отправителе</param>
        /// <returns></returns>
        [HttpPost]
        [Route("{uid}/info")]
        public IActionResult PostInfo(string uid, [FromBody] TelemetryInfoDto info)
        {
            telemetryService.UpdateInfo(uid, info);
            telemetryTracker.SaveRequestDate(uid);
            return Ok();
        }

        /// <summary>
        /// Принимает данные от разных систем по скважине
        /// </summary>
        /// <param name="uid">Уникальный идентификатор отправителя</param>
        /// <param name="dtos">Данные</param>
        /// <param name="token">Токен для отмены задачи</param>
        /// <returns></returns>
        [HttpPost]
        [Route("{uid}/data")]
        public async Task<IActionResult> PostDataAsync(string uid, [FromBody] IEnumerable<DataSaubBaseDto> dtos,
            CancellationToken token = default)
        {
            var idWell = telemetryService.GetidWellByTelemetryUid(uid);
            await DataService.UpdateDataAsync(uid, dtos, token).ConfigureAwait(false);

            if (idWell != null && dtos.Any())
                await Task.Run(() => telemetryHubContext.Clients.Group($"well_{idWell}")
                    .SendAsync(nameof(ITelemetryHubClient.ReceiveDataSaub), dtos), token).ConfigureAwait(false);

            telemetryTracker.SaveRequestDate(uid);
            return Ok();
        }

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

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

            telemetryTracker.SaveRequestDate(uid);
            return Ok();
        }

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

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

        ///// <summary>
        ///// Загрузка архива (sqlite3).
        ///// <example>
        ///// var fileName = @"C:\temp\default.sqlite3";
        ///// var fileStream = System.IO.File.OpenRead(fileName);
        ///// var file = new FileParameter(fileStream, System.IO.Path.GetFileName(fileName));
        ///// cli.ApiTelemetryDbAsync("1", new List&lt;FileParameter&gt; { file }).Wait();
        ///// </example>
        ///// </summary>
        ///// <param name="uid"></param>
        ///// <param name="files"></param>
        ///// <returns></returns>
        //[HttpPost]
        //[Route("{uid}/db")]
        //public IActionResult PostDb(string uid, IFormFileCollection files)
        //{
        //    foreach (var file in files)
        //    {
        //        var fileName = string.IsNullOrEmpty(file.FileName)
        //            ? System.IO.Path.GetTempFileName()
        //            : file.FileName;
        //        using (var stream = System.IO.File.Create(fileName))
        //            file.CopyTo(stream);
        //    }
        //    return Ok();
        //}

    }
}