namespace Hims.Infrastructure.Helpers
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Net;
    using System.Security.Policy;
    using System.Threading.Tasks;
    using Domain.Helpers;
    using Hims.Domain.Configurations;
    using Hims.Domain.Repositories.UnitOfWork;
    using Hims.Shared.EntityModels;
    using Microsoft.AspNetCore.Http;

    /// <inheritdoc />
    public class FtpHelper : IFtpHelper
    {
        /// <summary>
        /// The running environment.
        /// </summary>
        private readonly IRunningEnvironment runningEnvironment;

        /// <summary>
        /// The ftp configuration.
        /// </summary>
        private readonly INewFtpConfiguration newftpConfiguration;

        /// <summary>
        /// the unit of work
        /// </summary>
        private readonly IUnitOfWork unitOfWork;

        /// <inheritdoc />
        public FtpHelper(IRunningEnvironment runningEnvironment,
            INewFtpConfiguration NewftpConfiguration,
            IUnitOfWork unitOfWork)
        {
            this.runningEnvironment = runningEnvironment;
            this.newftpConfiguration = NewftpConfiguration;
            this.unitOfWork = unitOfWork;
        }

        public string GetFtpUrl(string category)
        {
            string url = "";
            if (category == "PatientProfile")
            {
                url = this.newftpConfiguration.FtpURL + this.runningEnvironment.CurrentEnvironment + "/" + this.newftpConfiguration.SubDirectoryAttachment + this.newftpConfiguration.SubDirectory1 + this.newftpConfiguration.SubDirectory1PatientProfiles;
            }
            else if (category == "PatientDocument")
            {
                url = this.newftpConfiguration.FtpURL + this.runningEnvironment.CurrentEnvironment + "/" + this.newftpConfiguration.SubDirectoryAttachment + this.newftpConfiguration.SubDirectory1 + this.newftpConfiguration.SubDirectory1PatientDocuments;
            }
            else if (category == "DoctorProfile")
            {
                url = this.newftpConfiguration.FtpURL + this.runningEnvironment.CurrentEnvironment + "/" + this.newftpConfiguration.SubDirectoryAttachment + this.newftpConfiguration.SubDirectory1 + this.newftpConfiguration.SubDirectory1DoctorProfiles;
            }
            else if (category == "UserProfile")
            {
                url = this.newftpConfiguration.FtpURL + this.runningEnvironment.CurrentEnvironment + "/" + this.newftpConfiguration.SubDirectoryAttachment + this.newftpConfiguration.SubDirectory1 + this.newftpConfiguration.SubDirectory1UserProfiles;
            }
            return url;
        }

        /// <summary>
        /// Delete File from FTP 
        /// </summary>
        /// <param name="fileNameWithDestinationPath">File name that will delete from FTP</param>
        /// <returns> string </returns>
        public async Task<string> DeleteFile(string fileNameWithDestinationPath)
        {
            string username = this.newftpConfiguration.Username;
            string password = this.newftpConfiguration.Password;
            FtpWebRequest ftp = (FtpWebRequest)FtpWebRequest.Create(fileNameWithDestinationPath);
            ftp.Credentials = new NetworkCredential(username, password);
            ftp.KeepAlive = true;
            ftp.UseBinary = true;
            ftp.UsePassive = true;
            ftp.Method = WebRequestMethods.Ftp.DeleteFile;
            FtpWebResponse response = (FtpWebResponse)await ftp.GetResponseAsync();
            response.Close();
            return "Document got deleted";
        }

        /// <summary>
        /// Fetch image Base64 from FTP 
        /// </summary>
        /// <param name="fileNameWithDestinationPath">File name that will delete from FTP</param>
        /// <returns> string </returns>
        public async Task<string> FetchImageBase64(int id, string url)
        {
            var base64 = "";
            var path = await this.unitOfWork.Patients.FindAsync();
            try
            {
                string username = this.newftpConfiguration.Username;
                string password = this.newftpConfiguration.Password;
                using WebClient request = new WebClient();
                request.Credentials = new NetworkCredential(username, @password);
                byte[] fileData = request.DownloadData(url);
                base64 = Convert.ToBase64String(fileData);
                return base64;
            }
            catch (Exception ex)
            {
                return ex.Message;
                //throw ex;
            }
        }

        public string FtpUploadProfileImage(string base64Image, string url, string fileName)
        {
            string ftpUrl = url;
            string filName = "";
            System.Net.FtpWebRequest ftp_web_request = null;
            System.Net.FtpWebResponse ftp_web_response = null;
            System.Net.FtpWebRequest ftp_web_request1 = null;
            System.Net.FtpWebResponse ftp_web_response1 = null;
            bool ifFolderExists = false;
            string username = this.newftpConfiguration.Username;
            string password = this.newftpConfiguration.Password;
            try
            {
                ftp_web_request = (FtpWebRequest)WebRequest.Create(@ftpUrl + "/");
                ftp_web_request.Method = WebRequestMethods.Ftp.ListDirectory;
                ftp_web_request.Credentials = new NetworkCredential(username, @password);
                FtpWebResponse response = (FtpWebResponse)ftp_web_request.GetResponse();
                ifFolderExists = true;
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("550"))
                {
                    ifFolderExists = false;
                }
                else if (ex.Message.Contains("530"))
                {
                    return ex.Message;
                }   
            }
            if (ifFolderExists == false)
            {
                FtpWebRequest request = (FtpWebRequest)WebRequest.Create(@ftpUrl);
                request.Method = WebRequestMethods.Ftp.MakeDirectory;
                request.Credentials = new NetworkCredential(username, @password);
                ftp_web_response = (FtpWebResponse)request.GetResponse();
                if (ftp_web_response != null)
                {
                    string ftp_response = ftp_web_response.StatusDescription;
                    string status_code = Convert.ToString(ftp_web_response.StatusCode);
                }
                ftp_web_response.Close();
            }
            filName = fileName + DateTime.UtcNow.Ticks + ".jpg";
            ftp_web_request1 =
                                (FtpWebRequest)WebRequest.Create(ftpUrl + "/" + filName);
            ftp_web_request1.Method = WebRequestMethods.Ftp.UploadFile;
            ftp_web_request1.Credentials = new NetworkCredential(username, @password);

            try
            {
                if (base64Image.StartsWith("data:image/png;base64"))
                {
                    base64Image = base64Image.Substring(22);
                }
                else if (base64Image.StartsWith("data:image/jpeg;base64"))
                {
                    base64Image = base64Image.Substring(23);
                }

                byte[] bytes = Convert.FromBase64String(base64Image);
                ftp_web_request1.ContentLength = bytes.Length;
                using (Stream s = ftp_web_request1.GetRequestStream())
                {
                    s.Write(bytes, 0, bytes.Length);
                }
                ftp_web_response1 = (FtpWebResponse)ftp_web_request1.GetResponse();

                if (ftp_web_response1 != null)
                {
                    var res = ftp_web_response1.StatusDescription;
                }
                ftp_web_response1.Close();
                if (ftp_web_response != null)
                {
                    ftp_web_response.Close();
                }
            }
            catch (Exception ex)
            {
                //Console.WriteLine(ex.ToString());
                throw ex;
            }
            return filName;
        }

        public string DeleteFtpFile(string url)
        {
            System.Net.FtpWebRequest ftp_web_request = null;
            System.Net.FtpWebResponse ftp_web_response = null;
            string username = this.newftpConfiguration.Username;
            string password = this.newftpConfiguration.Password;

            try
            {
                ftp_web_request = (FtpWebRequest)WebRequest.Create(url);
                ftp_web_request.Method = WebRequestMethods.Ftp.DeleteFile;
                ftp_web_request.Credentials = new NetworkCredential(username, password);

                ftp_web_response = (FtpWebResponse)ftp_web_request.GetResponse();

                if (ftp_web_response != null)
                {
                    var res = ftp_web_response.StatusDescription;
                }

                string ftp_response = ftp_web_response.StatusDescription;
                string status_code = Convert.ToString(ftp_web_response.StatusCode);

                ftp_web_response.Close();

                return "Document got deleted";
            }
            catch (Exception ex)
            {
                return ex.Message;
                //throw ex;
            }
        }

        public async Task<string> FetchDocumentBase64(int patientDocumentId, string url)
        {
            var base64 = "";
            string username = this.newftpConfiguration.Username;
            string password = this.newftpConfiguration.Password;
            var path = await this.unitOfWork.PatientDocuments.FindAsync(m => m.PatientDocumentId == patientDocumentId);
            var ftpfilepath = url + path.PatientId + "/" + path.DocumentUrl;
            try
            {
                using WebClient request = new WebClient();
                request.Credentials = new NetworkCredential(username, @password);
                byte[] fileData = request.DownloadData(ftpfilepath);
                base64 = Convert.ToBase64String(fileData);
            }
            catch (Exception ex)
            {
                //Console.WriteLine(ex.ToString());
                return ex.Message;
            }
            return base64;
        }

        public async Task<string> FtpUploadDocument(int patientId, IFormFile fileInfo, string url)
        {
            try
            {
                string ftpUrl;
                bool ifFolderExists = false;
                string username = this.newftpConfiguration.Username;
                string password = this.newftpConfiguration.Password;
                ftpUrl = url + patientId;
                try
                {
                    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpUrl + "/");
                    request.Method = WebRequestMethods.Ftp.ListDirectory;
                    request.Credentials = new NetworkCredential(username, @password);
                    FtpWebResponse response = (FtpWebResponse)request.GetResponse();
                    ifFolderExists = true;
                }
                catch (Exception)
                {
                    ifFolderExists = false;
                }
                if (ifFolderExists == false)
                {
                    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(@ftpUrl);
                    request.Method = WebRequestMethods.Ftp.MakeDirectory;
                    request.Credentials = new NetworkCredential(username, @password);
                    FtpWebResponse response = (FtpWebResponse)request.GetResponse();
                    if (response != null)
                    {
                        string ftp_response = response.StatusDescription;
                        string status_code = Convert.ToString(response.StatusCode);
                    }
                    response.Close();
                }
                FtpWebRequest request1 =
                                        (FtpWebRequest)WebRequest.Create(ftpUrl + "/" + fileInfo.FileName);
                request1.Method = WebRequestMethods.Ftp.UploadFile;
                request1.Credentials = new NetworkCredential(username, @password);
                using (Stream fileStream = fileInfo.OpenReadStream())
                using (Stream ftpStream = request1.GetRequestStream())
                {
                    await fileStream.CopyToAsync(ftpStream);
                }
                return ftpUrl + "/" + fileInfo.FileName;
            }
            catch (Exception ex)
            {
                //Console.WriteLine(ex.ToString());
                throw ex;
            }
        }




    }
}