using Newtonsoft.Json;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Redis;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using Newtonsoft.Json.Linq;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.DncRepository.Response;
using Siger.Middlelayer.Log;

namespace Siger.ApiDNC.Utility
{
    public class DNCHttpUtility
    {
        private static readonly object obj = new object();
        private static string GetUrl(int CID, int PID, string APIName)
        {
            var dbName = RedisCache.Instance.GetDbName(CID, PID);
            var ip = dbName.SCService;
            var port = dbName.SCPort;
            return $"{ip}:{port}{APIName}";
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="CID"></param>
        /// <param name="PID"></param>
        /// <param name="machineid"></param>
        /// <param name="programcode"></param>
        /// <param name="type">非0不检测programcode是否为空</param>
        /// <returns></returns>
        public static string GetProgram(int CID, int PID, int machineid, string programcode, int type = 0)
        {
            if (machineid == 0)
            {
                throw new BadRequestException(RequestEnum.ParameterMiss);
            }
            if (type == 0 && string.IsNullOrEmpty(programcode))
            {
                throw new BadRequestException(RequestEnum.ParameterMiss);
            }
            string url = GetUrl(CID, PID, CommonConst.NCProgram);
            var parameter = new List<KeyValuePair<string, string>>
            {
                new KeyValuePair<string, string>("machineName", machineid.ToString()),
                new KeyValuePair<string, string>("programNumber", programcode.ToString())
            };
            var result = HttpHelper.Get(url, parameter);
            var ret = (ResponseGetNCValue)JsonConvert.DeserializeObject(result, typeof(ResponseGetNCValue));
            if (ret.ret == 0)
                ret.ret = 1;
            else
                throw new BadRequestException(RequestEnum.GetProgramFailed);
            return ret.data;
        }
        public static List<string> GetProgramList(int CID, int PID, List<KeyValuePair<string, string>> para)
        {
            try
            {
                string url = GetUrl(CID, PID, CommonConst.GetProgramList);
                if(string.IsNullOrEmpty(url))
                {
                    throw new BadRequestException(RequestEnum.File_urlNotNull);
                }
                var ret = HttpHelper.Get(url, para);
                var result = new List<string>();
                if (!string.IsNullOrWhiteSpace(ret))
                {
                    var retObj = (ResponseGetProgramList)JsonConvert.DeserializeObject(ret, typeof(ResponseGetProgramList));
                    if (retObj.ret != 0)
                    {
                        Logger.WriteLineError($"GetProgramList failed, result : {retObj.ret}");
                        var dncMessage = ConvertResult(retObj.ret);
                        throw new BadRequestException(dncMessage);
                        //throw new Exception($"GetProgramList failed, result : {retObj.ret}");
                    }

                    if (retObj.data == null)
                    {
                        throw new Exception("GetProgramList record not found.");
                    }
                    var data = JArray.Parse(retObj.data.ToString());
                    for (var i = 0; i < data.Count; i++)
                    {
                        result.Add(data[i].ToStr());
                    }
                }
                return result;
            }
            catch (Exception exception)
            {
                Logger.WriteLineError("DNCHttpUtility.GetProgramList failed, error:" + exception);
                throw;
            }
        }

        private static RequestEnum ConvertResult(int res)
        {
         
            switch (res)
            {
                case 1:
                    return RequestEnum.DncCallUnknown;
                case 2:
                    return RequestEnum.DncCallFailed;
                case 3:
                    return RequestEnum.DncCallOffLine;
                case 4:
                    return RequestEnum.DncCallParameterError;
                case 5:
                    return RequestEnum.DncCallOutTime;
                case 6:
                    return RequestEnum.DncCallMachineNotFound;
                case 7:
                    return RequestEnum.DncCallServerError;
                case 8:
                    return RequestEnum.DncCallClientRequestError;
                case 9:
                    return RequestEnum.DncCallDonotSupport;
                case 10:
                    return RequestEnum.DncCallGatewayFailed;
                case 11:
                    return RequestEnum.DncCallGatewayNotFound;
                default:
                    return RequestEnum.DncCallUnknown;
            }
        }

        public static string DownloadPrograFile(Dictionary<string, string> data)
        {
            //获取文件内容
            List<string> fileList = new List<string>();
            foreach (var item in data)
            {
                try
                {
                    // File.WriteAllText(fileName, ret.data);
                    var list=item.Value.Split("/");
                    var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "upload/dnc/programs/", list[list.Length - 1]);
                    var path2 = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "download/dnc/programs/zip/", item.Key);
                    File.Copy(path, path2, true);
                    fileList.Add(item.Key);
                }
                catch
                {
                    throw new BadRequestException(RequestEnum.DownloadError);
                }
            }

            return ZipResult(fileList);
        }

       

        internal static string ZipResults(string filePath,string name )
        {
            var zip = $"{name}";
            var list = filePath.Split("/");
            var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "upload/dnc/programs/", list[list.Length - 1]);
            var path2 = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "download/dnc/programs/zip/", zip);
            File.Copy(path, path2, true);
            return $"Files/{zip}";
        }
        public static List<string > HCPrograFile(int CID, int PID, int machineid, Dictionary<string, string> data)
        {

            //程序运行物理路径
            string rootPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            string finalPath = Path.Combine(rootPath, CommonConst.UploadProgramFilePath);

            if (!Directory.Exists(finalPath))
                Directory.CreateDirectory(finalPath);
            //获取文件内容
            List<string> fileList = new List<string>();
            foreach (var item in data)
            {
                string url = GetUrl(CID, PID, CommonConst.NCProgram);
                var parameter = new List<KeyValuePair<string, string>>();
                parameter.Add(new KeyValuePair<string, string>("machineName", machineid.ToString()));
                parameter.Add(new KeyValuePair<string, string>("programNumber", item.Key));
                var result = HttpHelper.Get(url, parameter);
                var ret = (ResponseGetNCValue)JsonConvert.DeserializeObject(result, typeof(ResponseGetNCValue));
                if (ret.ret != 0)
                    continue;
                var fileName = $"{finalPath}/{item.Key}.{item.Value}";
                try
                {
                    File.WriteAllText(fileName, ret.data);
                    fileList.Add($"{item.Key}.{item.Value}");
                }
                catch (Exception)
                {
                    throw new BadRequestException(RequestEnum.DownloadError);
                }
            }
            return fileList;
        }
        public static string DownloadProgramzip(int CID, int PID, int machineid, Dictionary<string, string> data)
        {
            //程序运行物理路径
            string rootPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            string finalPath = Path.Combine(rootPath, CommonConst.DownloadProgramFilePath);
            if (!Directory.Exists(finalPath))
                Directory.CreateDirectory(finalPath);
            //获取文件内容
            List<string> fileList = new List<string>();
            foreach (var item in data)
            {
                string url = GetUrl(CID, PID, CommonConst.NCProgram);
                var parameter = new List<KeyValuePair<string, string>>();
                parameter.Add(new KeyValuePair<string, string>("machineName", machineid.ToString()));
                parameter.Add(new KeyValuePair<string, string>("programNumber", item.Key));
                var result = HttpHelper.Get(url, parameter);
                var ret = (ResponseGetNCValue)JsonConvert.DeserializeObject(result, typeof(ResponseGetNCValue));
                if (ret.ret != 0)
                    continue;


                var fileName =string.Empty;
                //是否已经存在后缀
                //var fileName = $"{finalPath}/{item.Key}.{item.Value}";
                if (item.Key.LastIndexOf(".")>0)
                {
                    fileName = $"{finalPath}/{item.Key}";
                    fileList.Add($"{item.Key}");
                }
                else
                {
                    fileName = $"{finalPath}/{item.Key}.{item.Value}";
                    fileList.Add($"{item.Key}.{item.Value}");
                }
                try
                {
                    File.WriteAllText(fileName, ret.data);
                    //fileList.Add($"{item.Key}.{item.Value}");
                }
                catch (Exception)
                {
                    throw new BadRequestException(RequestEnum.DownloadError);
                }
            }
            //压缩文件

            var zipPath = Path.Combine(rootPath, CommonConst.DownloadProgramZIPFilePath);
            if (!Directory.Exists(zipPath))
            {
                Directory.CreateDirectory(zipPath);
            }
            var zipFullPath = $"{zipPath}program.zip";
            lock (obj)
            {
                if (File.Exists(zipFullPath))
                    File.Delete(zipFullPath);
            }

            using (FileStream zipToOpen = new FileStream(zipFullPath, FileMode.Create))
            {
                using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update))
                {
                    foreach (var item in fileList)
                    {
                        string fileName = $"{finalPath}/{item}";
                        ZipArchiveEntry readmeEntry = archive.CreateEntry(item, CompressionLevel.Optimal);
                        using (StreamWriter writer = new StreamWriter(readmeEntry.Open()))
                        {
                            var fileContext = File.ReadAllText(fileName);
                            writer.WriteLine(fileContext);
                        }
                        File.Delete(fileName);
                    }
                }
            }
            return $"Files/program.zip";
        }

        public static string DownloadZip(List<ResponseProgramFileList> programList)
        {
            var count = 1;
            string rootPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            //压缩文件
            var zipPath = Path.Combine(rootPath, CommonConst.DownloadProgramZIPFilePath);
            if (!Directory.Exists(zipPath))
            {
                Directory.CreateDirectory(zipPath);
            }
            var zipFullPath = $"{zipPath}program.zip";
            lock (obj)
            {
                if (File.Exists(zipFullPath))
                    File.Delete(zipFullPath);
            }

            using (FileStream zipToOpen = new FileStream(zipFullPath, FileMode.Create))
            {
                using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update))
                {
                    foreach (var item in programList)
                    {

                        string fileName = FileUtility.GetTruePath(item.file_url);
                        //ZipArchiveEntry readmeEntry = archive.CreateEntry(count.ToString()+"-"+item.file_name, CompressionLevel.Optimal);
                        ZipArchiveEntry readmeEntry = archive.CreateEntry(item.file_name, CompressionLevel.Optimal);
                        using (StreamWriter writer = new StreamWriter(readmeEntry.Open()))
                        {
                            var fileContext = File.ReadAllText(fileName);
                            writer.WriteLine(fileContext);
                        }
                        count++;
                        //File.Delete(fileName);
                    }
                }
            }
            return $"Files/program.zip";
        }

        static string ZipResult(List<string> fileList)
        {
            string rootPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
          //  string finalPath = Path.Combine(rootPath, CommonConst.DownloadProgramFilePath);
            var finalPath = Path.Combine(rootPath, CommonConst.DownloadProgramZIPFilePath);
            if (!Directory.Exists(finalPath))
            {
                Directory.CreateDirectory(finalPath);
            }
            var zipFullPath = $"{finalPath}program.zip";
            lock (obj)
            {
                if (File.Exists(zipFullPath))
                    File.Delete(zipFullPath);
            }

            using (FileStream zipToOpen = new FileStream(zipFullPath, FileMode.Create))
            {
                using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update))
                {
                    foreach (var item in fileList)
                    {
                        string fileName = $"{finalPath}/{item}";
                        ZipArchiveEntry readmeEntry = archive.CreateEntry(item, CompressionLevel.Optimal);
                        using (StreamWriter writer = new StreamWriter(readmeEntry.Open()))
                        {
                            var fileContext = File.ReadAllText(fileName);
                            writer.WriteLine(fileContext);
                        }
                        File.Delete(fileName);
                    }
                }
            }
            return $"Files/program.zip";
        }
        /// <summary>
        /// 解压DNC文件
        /// </summary>
        /// <param name="source"></param>
        public static void ExtractToDirectory(string source)
        {
            string rootPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            string finalPath = Path.Combine(rootPath, CommonConst.DownloadProgramFilePath);

            var zipPath = Path.Combine(rootPath, CommonConst.UploadProgramFilePath);
            if (!Directory.Exists(zipPath))
            {
                Directory.CreateDirectory(zipPath);
            }
            ZipFile.ExtractToDirectory(source, zipPath,true);
         
        }

        public static string DeleteProgram(int CID, int PID, int machineid, List<string> pros)
        {
            var successList = new List<string>();
            string url = GetUrl(CID, PID, CommonConst.DeleteProgram);
            foreach (var item in pros)
            {
                var parameter = new List<KeyValuePair<string, string>>();
                parameter.Add(new KeyValuePair<string, string>("machineName", machineid.ToString()));
                parameter.Add(new KeyValuePair<string, string>("programNumber", item));
                var result = HttpHelper.Get(url, parameter);
                var ret = (ResponseNCDelete)JsonConvert.DeserializeObject(result, typeof(ResponseNCDelete));
                if (ret.ret == 0)
                    successList.Add(item);
            }
            if (successList.Any())
            {
                return string.Join(',', successList);
            }
            else
                throw new BadRequestException(RequestEnum.DeleteError);
        }
    }
}
