using AsbCloudApp.Data;
using AsbCloudApp.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using System.Threading;
using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
using System.ComponentModel.DataAnnotations;
using AsbCloudApp.Repositories;

namespace AsbCloudWebApi.Controllers
{
#nullable enable
    /// <summary>
    /// Дело скважины
    /// </summary>
    [Route("api/[controller]")]
    [ApiController]
    [Authorize]
    public class WellFinalDocumentsController : ControllerBase
    {
        private readonly IWellFinalDocumentsService wellFinalDocumentsService;
        private readonly IWellService wellService;
        private readonly IFileCategoryService fileCategoryService;
        private readonly IWellFinalDocumentsRepository wellFinalDocumentsRepository;

        public WellFinalDocumentsController(
            IWellFinalDocumentsService wellFinalDocumentsService, 
            IWellService wellService, 
            IFileCategoryService fileCategoryService,
            IWellFinalDocumentsRepository wellFinalDocumentsRepository)
        {
            this.wellFinalDocumentsService = wellFinalDocumentsService;
            this.wellService = wellService;
            this.fileCategoryService = fileCategoryService;
            this.wellFinalDocumentsRepository = wellFinalDocumentsRepository;
        }

        /// <summary>
        /// Получение всех записей
        /// </summary>
        /// <param name="idWell"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [HttpGet("{idWell}")]
        [Permission]
        [ProducesResponseType(typeof(WellCaseDto), (int)System.Net.HttpStatusCode.OK)]
        public async Task<IActionResult> GetAsync(int idWell, CancellationToken token)
        {
            if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false))
                return Forbid();

            var idUser = User!.GetUserId()!;
            var data = await wellFinalDocumentsRepository.GetByWellIdAsync(idWell, idUser.Value, token);
            return Ok(data);
        }

        /// <summary>
        /// Получение списка ответственных
        /// </summary>
        /// <param name="idWell"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [HttpGet("{idWell}/availableUsers")]
        [Permission]
        [ProducesResponseType(typeof(IEnumerable<UserDto>), (int)System.Net.HttpStatusCode.OK)]
        public async Task<IActionResult> GetAvailableUsersAsync(int idWell, CancellationToken token )
        {
            if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false))
                return Forbid();

            var data = await wellFinalDocumentsRepository.GetAvailableUsersAsync(idWell, token);
            return Ok(data);
        }

        /// <summary>
        /// Обновление всех записей по скважине
        /// </summary>
        /// <param name="idWell"></param>
        /// <param name="dtos"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [HttpPut("{idWell}")]
        [Permission("WellFinalDocuments.editPublisher")]
        [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
        public async Task<IActionResult> UpdateRangeAsync(int idWell, [Required] IEnumerable<WellFinalDocumentInputDto> dtos, CancellationToken token )
        {
            if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false))
                return Forbid();
            var data = await wellFinalDocumentsService.UpdateRangeAsync(idWell, dtos, token);
            return Ok(data);
        }

        /// <summary>
        /// Повторно оповестить ответственных за загрузку
        /// </summary>
        /// <param name="idWell"></param>
        /// <param name="idCategory"></param>
        /// <param name="token"></param>
        /// <returns>количество оповещенных публикаторов</returns>
        [HttpPut("{idWell}/reNotifyPublishers")]
        [Permission("WellFinalDocuments.editPublisher")]
        [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
        public async Task<IActionResult> ReNotifyPublishersAsync(int idWell, [Required] int idCategory, CancellationToken token )
        {
            if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false))
                return Forbid();

            var idUser = User!.GetUserId()!;
            var data = await wellFinalDocumentsService.ReNotifyPublishersAsync(idWell, idUser.Value, idCategory, token);
            return Ok(data);
        }

        /// <summary>
        /// Получение истории файлов
        /// </summary>
        /// <param name="idWell"></param>
        /// <param name="idCategory"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [HttpGet("{idWell}/history")]
        [Permission]
        [ProducesResponseType(typeof(WellFinalDocumentsHistoryDto), (int)System.Net.HttpStatusCode.OK)]
        public async Task<IActionResult> GetFilesHistoryByIdCategoryAsync(int idWell, 
            [Required] int idCategory, 
            CancellationToken token )
        {
            if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false))
                return Forbid();

            var data = await this.wellFinalDocumentsService.GetFilesHistoryByIdCategoryAsync(idWell, idCategory, token);
            return Ok(data);
        }

        /// <summary>
        /// Сохранение файла
        /// </summary>
        /// <param name="idWell"></param>
        /// <param name="idCategory"></param>
        /// <param name="file"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [HttpPost("{idWell}")]
        [Permission]
        [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
        public async Task<IActionResult> SaveCategoryFileAsync(int idWell, [Required] int idCategory, [Required] IFormFile file, CancellationToken token )
        {
            if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false))
                return Forbid();

            var idUser = User!.GetUserId()!;
            var fileStream = file.OpenReadStream();
            var data = await this.wellFinalDocumentsService.SaveCategoryFileAsync(idWell, idCategory, idUser.Value, fileStream, file.FileName, token);
            return Ok(data);
        }

        /// <summary>
        /// Получение справочника категорий файлов
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Route("wellCaseCategories")]
        [Permission]
        public async Task<IActionResult> GetWellCaseCategoriesAsync(CancellationToken token = default)
        {
            var data = await fileCategoryService.GetWellCaseCategoriesAsync(token);
            return Ok(data);
        }

        private async Task<bool> CanUserAccessToWellAsync(int idWell, CancellationToken token )
        {
            int? idCompany = User.GetCompanyId();
            return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
                idWell, token).ConfigureAwait(false);
        }
    }
#nullable disable
}