using AsbCloudApp.Data;
using AsbCloudApp.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace AsbCloudWebApi.Controllers
{
    [Route("api/well/{idWell}/drillingProgram")]
    [ApiController]
    [Authorize]
    public class DrillingProgramController : ControllerBase
    {
        private readonly IDrillingProgramService drillingProgramService;
        private readonly IFileService fileService;
        private readonly IWellService wellService;

        public DrillingProgramController(IDrillingProgramService drillingProgramService, 
            IFileService fileService, IWellService wellService)
        {
            this.drillingProgramService = drillingProgramService;
            this.fileService = fileService;
            this.wellService = wellService;
        }
        
        /// <summary>
        /// Создает программу бурения
        /// </summary>
        /// <param name="idWell"> id скважины </param>
        /// <param name="token"> Токен отмены задачи </param>
        /// <returns> Возвращает файл программы бурения </returns>
        [HttpGet]
        [ProducesResponseType(typeof(FileResult), (int)System.Net.HttpStatusCode.OK)]
        public async Task<IActionResult> GetAsync(int idWell, CancellationToken token = default)
        {
            var idCompany = User.GetCompanyId();

            var fileChangerId = User.GetUserId();

            if (idCompany is null || fileChangerId is null || 
                !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
                    idWell, token).ConfigureAwait(false))
                return Forbid();
            
            var fileInfo = await drillingProgramService.GetOrCreateAsync(idWell, 
                    (int)fileChangerId, token)
                .ConfigureAwait(false);
            
            if (fileInfo is null)
                return NoContent();
            
            var relativePath = fileService.GetUrl(fileInfo);

            return PhysicalFile(Path.GetFullPath(relativePath), "application/octet-stream", fileInfo.Name);
        }

        /// <summary>
        /// Создает программу бурения
        /// </summary>
        /// <param name="idWell"> id скважины </param>
        /// <param name="fileShareService"></param>
        /// <param name="token"> Токен отмены задачи </param>
        /// <returns> Возвращает ссылку на файл программы бурения в облаке </returns>
        [HttpGet("webUrl")]
        [ProducesResponseType(typeof(string), (int)System.Net.HttpStatusCode.OK)]
        public async Task<IActionResult> GetOrCreateSharedUrlAsync(int idWell, [FromServices]IFileShareService fileShareService, CancellationToken token = default)
        {
            var idCompany = User.GetCompanyId();

            var idUser = User.GetUserId();

            if (idCompany is null || idUser is null || 
                !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
                    idWell, token).ConfigureAwait(false))
                return Forbid();
            
            var sharedUrl = await drillingProgramService.GetOrCreateSharedUrlAsync(idWell, 
                    (int)idUser, fileShareService, token)
                .ConfigureAwait(false);
            
            return Ok(sharedUrl);
        }

        /// <summary>
        /// Создает метку для файла входящего в проргамму бурения
        /// </summary>
        /// <param name="idWell"> id скважины </param>
        /// <param name="markDto">метка файла</param>
        /// <param name="token"> Токен отмены задачи </param>
        /// <returns></returns>
        [HttpPost("fileMark")]
        public async Task<IActionResult> CreateFileMarkAsync(int idWell, FileMarkDto markDto, CancellationToken token = default)
        {
            var idCompany = User.GetCompanyId();

            var idUser = User.GetUserId();

            if (idCompany is null || idUser is null || 
                !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
                    idWell, token).ConfigureAwait(false))
                return Forbid();
            
            var result = await drillingProgramService.CreateFileMarkAsync(markDto, (int)idUser, token)
                .ConfigureAwait(false);

            return Ok(result);
        }

        /// <summary>
        /// Помечает метку у файла входящего, в проргамму бурения, как удаленную
        /// </summary>
        /// <param name="idWell"> id скважины </param>
        /// <param name="idMark"> id метки </param>
        /// <param name="token"> Токен отмены задачи </param>
        /// <returns></returns>
        [HttpDelete("fileMark")]
        [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
        public async Task<IActionResult> DeleteFileMarkAsync(int idWell, int idMark,
            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 drillingProgramService.MarkFileMarkAsDeletedAsync(idMark, token)
                .ConfigureAwait(false);

            return Ok(result);
        }
    }
}