using AsbCloudApp.Data.GTR;
using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using AsbCloudWebApi.SignalR;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Requests;

namespace AsbCloudWebApi.Controllers.SAUB
{

    [Route("api/[controller]")]
    [ApiController]
    public class GtrWitsController : ControllerBase

    {
        protected readonly IWellService wellService;
        private readonly ITelemetryService telemetryService;
        private readonly IGtrRepository gtrRepository;
        private readonly IHubContext<TelemetryHub> telemetryHubContext;

        public string SignalRMethodGetDataName { get; protected set; } = "ReceiveData";

        public GtrWitsController(
            ITelemetryService telemetryService,
            IGtrRepository gtrRepository,
            IWellService wellService,
            IHubContext<TelemetryHub> telemetryHubContext)
        {
            this.telemetryService = telemetryService;
            this.gtrRepository = gtrRepository;
            this.wellService = wellService;
            this.telemetryHubContext = telemetryHubContext;
        }

        /// <summary>
        /// Получить загруженные данные ГТИ по скважине
        /// </summary>
        /// <param name="idWell">Id скважины</param>
        /// <param name="request">Параметры запроса</param>
        /// <param name = "token" >Токен завершения задачи</param>
        /// <returns></returns>
        [HttpGet("{idWell}")]
        [Permission]
        public async Task<ActionResult<IEnumerable<WitsRecordDto>>> GetDataAsync([Required] int idWell, 
            [FromQuery] GtrWithGetDataRequest request,
            CancellationToken token)
        {
            int? idCompany = User.GetCompanyId();

            if (idCompany is null)
                return Forbid();

            bool isCompanyOwnsWell = await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
                idWell, token).ConfigureAwait(false);

            if (!isCompanyOwnsWell)
                return Forbid();

            var content = await gtrRepository.GetAsync(idWell, request.Begin,
              request.IntervalSec, request.ApproxPointsCount, token).ConfigureAwait(false);

            return Ok(content);
        }

        /// <summary>
        /// получение последних данных ГТИ по ключу record
        /// </summary>
        /// <param name="idWell">id скважины</param>
        /// <param name="idRecord">id record</param>
        /// <param name="token"></param>
        /// <returns></returns>
        [HttpGet("{idWell}/{idRecord}")]
        [Permission]
        public async Task<ActionResult<IEnumerable<WitsItemRecordDto>>> GetLastDataByRecordIdAsync(int idWell, int idRecord, CancellationToken token)
        {
            int? idCompany = User.GetCompanyId();

            if (idCompany is null)
                return Forbid();

            bool isCompanyOwnsWell = await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
                idWell, token).ConfigureAwait(false);

            if (!isCompanyOwnsWell)
                return Forbid();

            var content = gtrRepository.GetLastDataByRecordId(idWell, idRecord);

            return Ok(content);
        }

        /// <summary>
        /// Метод для получения WITS записи от панели оператора.
        /// Сохраняет в БД.        
        /// </summary>
        /// <param name="uid">уникальный идентификатор телеметрии</param>
        /// <param name="dtos">WITS запись</param>        
        /// <param name="token"></param>
        /// <returns></returns>
        [HttpPost("{uid}")]
        public async Task<IActionResult> PostDataAsync(
            string uid,
            [FromBody] IEnumerable<WitsRecordDto> dtos,
            CancellationToken token)
        {
            var telemetry = telemetryService.GetOrCreateTelemetryByUid(uid);
            await gtrRepository.SaveDataAsync(telemetry.Id, dtos, token).ConfigureAwait(false);
            var idWell = telemetryService.GetIdWellByTelemetryUid(uid);
            if (idWell is not null && dtos is not null)
                _ = Task.Run(() => telemetryHubContext.Clients.Group($"well_{idWell}_gtr")
                      .SendAsync(SignalRMethodGetDataName, dtos), CancellationToken.None);
            return Ok();
        }
    }

}