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

namespace AsbCloudWebApi.Controllers
{
    /// <summary>
    /// Контроллер для режимов бурения
    /// </summary>
    [Route("api/drillParams/{idWell}")]
    [ApiController]
    public class DrillParamsController : ControllerBase
    {
        private readonly IDrillParamsService drillParamsService;
        private readonly IWellService wellService;

        public DrillParamsController(IDrillParamsService drillParamsService,
            IWellService wellService)
        {
            this.drillParamsService = drillParamsService;
            this.wellService = wellService;
        }

        /// <summary>
        /// Возвращает автоматически расчитанные значения для режимов бурения
        /// </summary>
        /// <param name="idWell"> id скважины </param>
        /// <param name="startDepth"> Стартовая глубина </param>
        /// <param name="endDepth"> Конечная глубина </param>
        /// <param name="token"> Токен отмены задачи </param>
        /// <returns> Значения по умолчанию для режимов бурения </returns>
        [HttpGet("autoParams")]
        [ProducesResponseType(typeof(DrillParamsDto), (int) System.Net.HttpStatusCode.OK)]
        public async Task<IActionResult> GetDefaultAsync(int idWell, 
            double startDepth, double endDepth, CancellationToken token = default)
        {
            var idCompany = User.GetCompanyId();

            if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
                idWell, token).ConfigureAwait(false))
                return Forbid();
            
            var drillParamsDo = await drillParamsService.GetDefaultDrillParamsAsync(idWell, 
                 startDepth, endDepth, token);

            return Ok(drillParamsDo);
        }
        
        /// <summary>
        /// Возвращает все значения для режимов бурения на скважине
        /// </summary>
        /// <param name="idWell"> id скважины </param>
        /// <param name="token"> Токен отмены задачи </param>
        /// <returns> Список параметров для режимов бурения на скважине </returns>
        [HttpGet]
        [ProducesResponseType(typeof(IEnumerable<DrillParamsDto>), (int) System.Net.HttpStatusCode.OK)]
        public async Task<IActionResult> GetAllAsync(int idWell, 
            CancellationToken token = default)
        {
            var idCompany = User.GetCompanyId();
        
            if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
                idWell, token).ConfigureAwait(false))
                return Forbid();

            var dto = await drillParamsService.GetAllAsync(idWell, token);
        
            return Ok(dto);
        }
        
        /// <summary>
        /// Сохраняет значения для режимов бурения по секции на скважине
        /// </summary>
        /// <param name="idWell"> id скважины </param>
        /// <param name="drillParamsDto"> Параметры режимов бурений для секции</param>
        /// <param name="token"> Токен отмены задачи </param>
        /// <returns></returns>
        [HttpPost]
        [ProducesResponseType(typeof(int), (int) System.Net.HttpStatusCode.OK)]
        public async Task<IActionResult> InsertAsync(int idWell, 
            DrillParamsDto drillParamsDto, CancellationToken token = default)
        {
            var idCompany = User.GetCompanyId();

            if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
                idWell, token).ConfigureAwait(false))
                return Forbid();

            var result = await drillParamsService.InsertAsync(idWell, drillParamsDto, token);

            return Ok(result);
        }
        
        /// <summary>
        /// Добавляет массив объектов режимов бурений
        /// </summary>
        /// <param name="idWell"> id скважины </param>
        /// <param name="drillParams"> Массив объектов параметров режима бурений для секции</param>
        /// <param name="token"> Токен отмены задачи </param>
        /// <returns></returns>
        [HttpPost("range")]
        [ProducesResponseType(typeof(int), (int) System.Net.HttpStatusCode.OK)]
        public async Task<IActionResult> InsertRangeAsync(int idWell, 
            IEnumerable<DrillParamsDto> drillParams, CancellationToken token = default)
        {
            var idCompany = User.GetCompanyId();
        
            if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
                idWell, token).ConfigureAwait(false))
                return Forbid();

            var result = await drillParamsService.InsertRangeAsync(idWell, drillParams,
                token);
        
            return Ok(result);
        }
        
        /// <summary>
        /// Изменяет значения выбранного режима бурения
        /// </summary>
        /// <param name="idWell"> id скважины </param>
        /// <param name="drillParamsDto"> Параметры режимов бурений для секции</param>
        /// <param name="token"> Токен отмены задачи </param>
        /// <returns></returns>
        [HttpPut]
        [ProducesResponseType(typeof(int), (int) System.Net.HttpStatusCode.OK)]
        public async Task<IActionResult> EditAsync(int idWell, 
            DrillParamsDto drillParamsDto, CancellationToken token = default)
        {
            var idCompany = User.GetCompanyId();
        
            if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
                idWell, token).ConfigureAwait(false))
                return Forbid();

            var result = await drillParamsService.UpdateAsync(idWell, 
                drillParamsDto, token);
        
            return Ok(result);
        }
        
        /// <summary>
        /// Удаляет объект значений выбранного режима бурения
        /// </summary>
        /// <param name="idWell"> id скважины </param>
        /// <param name="drillParamsId"> Id объекта параметров режима бурений для секции</param>
        /// <param name="token"> Токен отмены задачи </param>
        /// <returns></returns>
        [HttpDelete]
        [ProducesResponseType(typeof(int), (int) System.Net.HttpStatusCode.OK)]
        public async Task<IActionResult> DeleteAsync(int idWell, 
            int drillParamsId, CancellationToken token = default)
        {
            var idCompany = User.GetCompanyId();
        
            if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
                idWell, token).ConfigureAwait(false))
                return Forbid();
            
            var result = await drillParamsService.DeleteAsync(drillParamsId, 
                token);
        
            return Ok(result);
        }
        
        /// <summary>
        /// Возвращает значения для режимов бурения на композитной скважине
        /// </summary>
        /// <param name="idWell"> id скважины </param>
        /// <param name="token"> Токен отмены задачи </param>
        /// <returns> Список параметров для режимов бурения на композитной скважине </returns>
        [HttpGet("composite")]
        [ProducesResponseType(typeof(IEnumerable<DrillParamsDto>), (int) System.Net.HttpStatusCode.OK)]
        public async Task<IActionResult> GetCompositeAllAsync(int idWell, CancellationToken token = default)
        {
            var idCompany = User.GetCompanyId();
        
            if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
                idWell, token).ConfigureAwait(false))
                return Forbid();

            var dto = await drillParamsService.GetCompositeAllAsync(idWell, token);
        
            return Ok(dto);
        }
    }
}