using DocumentFormat.OpenXml.Presentation;
using Hims.Api.Models;
using Hims.Api.Utilities;
using Hims.Domain.Configurations;
using Hims.Domain.Entities;
using Hims.Domain.Helpers;
using Hims.Domain.Services;
using Hims.Infrastructure.Helpers;
using Hims.Shared.DataFilters;
using Hims.Shared.EntityModels;
using Hims.Shared.Library.Enums;
using Hims.Shared.UserModels;
using Hims.Shared.UserModels.Filters;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Npgsql;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace Hims.Api.Controllers
{

    /// <inheritdoc />
    [Authorize]
    [Route("api/diet-guidlines")]
    [Consumes("application/json")]
    [Produces("application/json")]
    public class DietGuidLinesController : BaseController
    {
        /// <summary>
        /// The idproof services.
        /// </summary>
        private readonly IDietGuidLinesService dietGuidLinesService;

        /// <summary>
        /// The audit log services.
        /// </summary>
        private readonly IAuditLogService auditLogServices;
        /// <summary>
        /// The amazon s3 helper.
        /// </summary>
        private readonly IDocumentHelper documentHelper;

        /// <summary>
        /// The ftp helper.
        /// </summary>
        private readonly IFtpHelper ftpHelper;

        private readonly IFtpUploadHelper ftpUploadHelper;

        private readonly IRunningEnvironment runningEnvironment;
        /// <inheritdoc />
        public DietGuidLinesController(IDietGuidLinesService dietGuidLinesService, IAuditLogService auditLogService, IDocumentHelper documentHelper, IFtpHelper ftpHelper, IFtpUploadHelper ftpUploadHelper, IRunningEnvironment runningEnvironment)

        {
            this.dietGuidLinesService = dietGuidLinesService;
            this.auditLogServices = auditLogService;
            this.documentHelper = documentHelper;
            this.ftpHelper = ftpHelper;
            this.ftpUploadHelper = ftpUploadHelper;
            this.runningEnvironment = runningEnvironment;

        }

        /// <summary>
        /// Inserts the hoc asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="header">The location header.</param> 
        /// <returns></returns>
        [HttpPost]
        [Route("add")]
        [Consumes("multipart/form-data")]
        [Produces("application/json")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(400)]
        [ProducesResponseType(417)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> InsertAsync([FromForm] DietGuidLinesModel model, [FromHeader] LocationHeader header)
        {
            model = (DietGuidLinesModel)EmptyFilter.Handler(model);
            var files = this.Request.Form.Files;
            if (files == null || files.Count == 0)
            {
                return this.BadRequest("We're sorry. There are no files to upload.");
            }
            var contentTypes = this.documentHelper.FetchContentTypes().ToList();
            if (!ListFilter.ContainsAll(contentTypes, files.Select(m => m.ContentType).Distinct()))
            {
                return this.Failed($"Only {string.Join(", ", contentTypes)} files are allowed.");
            }
            var dietDocuments = new List<DietGuidLinesModel>();

            var index = 0;
            foreach (var file in files)
            {
                var request = new DietGuidLinesModel
                {
                    DietGuidLinesName = model.DietGuidLinesName,
                    CreatedBy = model.CreatedBy,
                    PdfLink = model.PdfLink,
                    ContentType = file.ContentType,
                    Size = file.Length,
                    DietTypeId=model.DietTypeId
                };

                var filePath = $@"{this.runningEnvironment.CurrentEnvironment}/{model.DietGuidLinesName}";

                try
                {
                    await this.ftpUploadHelper.CreateDirectory(filePath);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
                var dbPath = $@"{model.DietGuidLinesName}_{DateTime.UtcNow.Ticks}{Path.GetExtension(file.FileName)}";
                filePath += $@"/{dbPath}";
                var uploadResponse = await this.ftpUploadHelper.UploadFromFileAsync(filePath, file);
                if (uploadResponse <= 0)
                {
                    return this.BadRequest();
                }

                request.PdfLink = this.documentHelper.GetThumbnail(file.ContentType);
                request.DocumentUrl = dbPath;

                dietDocuments.Add(request);
                index++;

            }
            var response = await this.dietGuidLinesService.AddAsync(dietDocuments);
            var auditLogModel = new AuditLogModel
            {
                AccountId = model.CreatedBy,
                LogTypeId = (int)LogTypes.DietGuidelines,
                LogFrom = (int)AccountType.Administrator,
                LogDate = DateTime.UtcNow.AddMinutes(330),
                LogDescription = $" <b>{model.CreatedByName}</b> has <b>added</b> the guideline <b>{model.DietGuidLinesName}</b> on {DateTime.UtcNow.AddMinutes(330)}",
                LocationId = Convert.ToInt32(header.LocationId)
            };
            await this.auditLogServices.LogAsync(auditLogModel);
            return this.Success(response);
        }

        [HttpGet]
        [AllowAnonymous]
        [Route("download-file-ftp-get")]
        public async Task<ActionResult> DownloadFileFromFTPAsync(int id, string url)
        {
            if (id == 0 || string.IsNullOrEmpty(url))
            {
                return this.ServerError();
            }

            var checkIf = this.ftpUploadHelper.CheckIfFileExistsOnServer(url);
            if (!checkIf)
            {
                return this.BadRequest();
            }

            var patientData = await this.dietGuidLinesService.GetDietDocumentOnIdAsync(id);

            var memoryStream = await this.ftpUploadHelper.DownloadSmallFilesAsync(url);
            return File(new MemoryStream(memoryStream), patientData.ContentType, patientData.DocumentUrl);
        }
        /// <summary>
        /// Downloads the file from FTP and send as base64 asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [AllowAnonymous]
        [Route("download-file-ftp")]
        public async Task<ActionResult> DownloadFileFromFTPAndSendAsBase64Async([FromBody] DietGuidLinesModel model)
        {
            model = (DietGuidLinesModel)EmptyFilter.Handler(model);
            var checkIf = this.ftpUploadHelper.CheckIfFileExistsOnServer(model.DocumentUrl);
            if (!checkIf)
            {
                return this.BadRequest();
            }
            var documentsDownload = await this.ftpUploadHelper.DownloadBase64DataAsync(model.DocumentUrl);
            return this.Success(new DocumentViewModel { Base64 = documentsDownload });
        }

        [HttpPost]
        [Route("update")]
        public async Task<ActionResult> UpdateAsync([FromBody] DietGuidLinesModel model, [FromHeader] LocationHeader header)
        {
            model = (DietGuidLinesModel)EmptyFilter.Handler(model);
            var response = await this.dietGuidLinesService.UpdateAsync(model);
            //try
            //{
            //    if (response > 0)
            //    {
            //        var auditLog = new AuditLogModel
            //        {
            //            AccountId = model.CreatedBy,
            //            LogTypeId = (int)LogTypes.IdProof,
            //            LogDate = DateTime.Now,
            //            LogFrom = short.Parse(model.LoginRoleId.ToString()),                        
            //            LogDescription = $"{model.CreatedByName} has updated <b>Id Proof</b> of <strong>{model.IdProofName}</strong> successfully.",
            //            LocationId =Convert.ToInt32(header.LocationId)
            //        };
            //        await this.auditLogServices.LogAsync(auditLog);
            //    }
            //}
            //catch (Exception ex)
            //{
            //    //ignore
            //}
            var auditLogModel = new AuditLogModel
            {
                AccountId = model.ModifiedBy,
                LogTypeId = (int)LogTypes.DietGuidelines,
                LogFrom = (int)AccountType.Administrator,
                LogDate = DateTime.UtcNow.AddMinutes(330),
                LogDescription = $" <b>{model.ModifiedByName}</b> has <b>updated</b> the guideline <b>{model.DietGuidLinesName}</b> on {DateTime.UtcNow.AddMinutes(330)}",
                LocationId = Convert.ToInt32(header.LocationId)
            };
            await this.auditLogServices.LogAsync(auditLogModel);
            return this.Success(response);
        }

        /// <summary>
        /// Fetches all asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [HttpPost]
        [Route("fetch")]
        public async Task<ActionResult> FetchAsync([FromBody] DietGuidLinesModel model)
        {
            model = (DietGuidLinesModel)EmptyFilter.Handler(model);
            var response = await this.dietGuidLinesService.FetchAsync(model);
            return this.Success(response);
        }

        [HttpPost]
        [Route("modify-status")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(409)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> ModifyStatusAsync([FromBody] DietGuidLinesModel model, [FromHeader] LocationHeader header)
        {
            model = (DietGuidLinesModel)EmptyFilter.Handler(model);
            var response = await this.dietGuidLinesService.ModifyStatusAsync(model);
            if (response == 0)
            {
                return this.ServerError();
            }
            var auditLog = new AuditLogModel
            {
                AccountId = model.ModifiedBy,
                LogTypeId = (int)LogTypes.DietGuidelines,
                LogFrom = (int)AccountType.Administrator,
                LogDate = DateTime.UtcNow.AddMinutes(330),
                LogDescription = $@"<b>{model.ModifiedByName}</b> has <b>{((bool)model.Active ? "Activated" : "Deactivated")}</b> the guideline <b>{model.DietGuidLinesName}</b> successfully",
                LocationId = Convert.ToInt32(header.LocationId)
            };
            await this.auditLogServices.LogAsync(auditLog);
            return this.Success(response);

        }

        /// <summary>
        /// delete
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("delete")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(409)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> DeleteAsync([FromBody] DietGuidLinesModel model, [FromHeader] LocationHeader header)
        {
            try
            {
                model = (DietGuidLinesModel)EmptyFilter.Handler(model);
                var response = await this.dietGuidLinesService.DeleteAsync(model);
                if (response == null)
                {
                    return this.ServerError();
                }
                if (!string.IsNullOrEmpty(model.DocumentUrl))
                {
                    await this.ftpUploadHelper.DeleteFile(model.DocumentUrl);
                }
                var auditLog = new AuditLogModel
                {
                    AccountId = model.ModifiedBy,
                    LogTypeId = (int)LogTypes.DietGuidelines,
                    LogFrom = (int)AccountType.Administrator,
                    LogDate = DateTime.UtcNow.AddMinutes(330),
                    LogDescription = $" <b>{model.ModifiedByName}</b> has <b>deleted</b> the guideline <b>{model.DietGuidLinesName}</b> on {DateTime.UtcNow.AddMinutes(330)}",
                    LocationId = Convert.ToInt32(header.LocationId)
                };
                await this.auditLogServices.LogAsync(auditLog);
                return this.Success(response);               
            }
            catch (Exception)
            {
                return this.Success(-3);
            }
        }
    }
}


