using ASHermed.SinoInterface.Api.ContractModel.App;
using ASHermed.SinoInterface.Api.IRepository;
using ASHermed.SinoInterface.Api.IService.App;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Text;
using ASHermed.SinoInterface.ContractModel;
using ASHermed.SinoInterface.Tools.Base;
using Microsoft.Extensions.Configuration;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using ASHermed.SinoInterface.Tools;
using System.Reflection;
using Newtonsoft.Json;
using System.Net;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using ASHermed.SinoInterface.IFramework;

namespace ASHermed.SinoInterface.Api.Service.App
{
    public class FileService : IFileService
    {
        private readonly IFileRepository _fileRepository;
        private readonly IConfiguration _configuration;
        private readonly IZhuTongSMSService _zhuTongSMSService;
        private string fileUrl = string.Empty;
        private string storage = string.Empty;

        public FileService(IFileRepository fileRepository, IConfiguration configuration, IZhuTongSMSService zhuTongSMSService)
        {
            _fileRepository = fileRepository;
            _configuration = configuration;
            fileUrl = _configuration["AppSettings:BaseAddress"];
            storage = _configuration["AppSettings:Storage"] + @":\";
            _zhuTongSMSService = zhuTongSMSService;
        }
        /// <summary>
        /// 获取文件列表，不包含Content字段
        /// </summary>
        /// <param name="Ids"></param>
        /// <returns></returns>
        public List<Sys_File> GetFiles(List<int> Ids)
        {
            //_fileRepository.UpdatePat(_fileRepository.GetPatList());
            //return new List<Sys_File>();
            return _fileRepository.GetFilesForContent(Ids);
        }

        public string DecodeDES(string str)
        {
            return DES.DecodeDES(str, DES.DESKey);
        }

        public string EncodeDES(string str)
        {
            return DES.EncodeDES(str, DES.DESKey);
        }

        /// <summary>
        /// 上传文件接口，到本地，存DB
        /// </summary>
        /// <param name="file"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public BaseResponse<string> UploadLocalhost(IFormFile file, int type)
        {
            var resu = new BaseResponse<string>();
            resu.Code = 1;
            //if (file.Length > 100 * 1024 * 1024)
            //{
            //    resu.Code = 0;
            //    resu.Msg = "图片超过10M，请重新选择";
            //    return resu;
            //}
            try
            {
                if (file != null)
                {
                    int lastSlashIndex = file.FileName.LastIndexOf("\\");
                    string fileName = file.FileName.Substring(lastSlashIndex + 1, file.FileName.Length - lastSlashIndex - 1);
                    string fix = string.Empty;//获取文件后缀
                    string fnames = string.Empty;//获取文件名
                    if (fileName.LastIndexOf(".") > 0)
                    {
                        fix = fileName.Substring(fileName.LastIndexOf(".") + 1).ToLower();
                        fnames = fileName.Substring(0, fileName.LastIndexOf("."));
                    }
                    if (type != 4 && type != 5)
                    {
                        var bytes = CompressImage(StreamToBytes(file.OpenReadStream()), 90, 400, true);
                        resu.Data = UploadLocalhost(bytes, fnames, fix, type).ToString();
                    }
                    else
                    {
                        resu.Data = UploadLocalhost(StreamToBytes(file.OpenReadStream()), fnames, fix, type).ToString();
                    }
                    resu.Msg = "操作成功";
                    return resu;
                }
                return resu;
            }
            catch (System.Exception ex)
            {
                resu.Code = 0;
                resu.Msg = ex.Message;
                return resu;
            }
        }

        public BaseResponse<string> CompressImage(IFormFile file)
        {
            BaseResponse<string> response = new BaseResponse<string>();
            var bytes = CompressImage(StreamToBytes(file.OpenReadStream()), 90, 400, true);
            response.Data = System.Convert.ToBase64String(bytes);
            response.Code = 1;
            response.Msg = "成功";
            return response;
        }

        /// <summary>
        /// 文件转换，上传文件返回的ID，通过此方法转换为Base64字符，并返回
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ls"></param>
        /// <returns></returns>
        public List<T> GetFileContentAdd<T>(List<T> ls) where T : IContentModel, new()
        {
            List<PropertyInfo> prlist = new List<PropertyInfo>();
            Type t = typeof(T);
            Array.ForEach<PropertyInfo>(t.GetProperties(), p => { prlist.Add(p); });
            foreach (var item in ls)
            {
                foreach (PropertyInfo p in prlist)
                {
                    object[] objAttrs = p.GetCustomAttributes(typeof(ContentAttibute), true);
                    object[] tabledetailAttrs = p.GetCustomAttributes(typeof(TableAttibute), true);
                    if (objAttrs != null && objAttrs.Length > 0)
                    {
                        TableAttibute attr = tabledetailAttrs[0] as TableAttibute;
                        if (attr.RowName.ToLower() != "Id".ToLower())
                        {
                            var value = p.GetValue(item).IsNullSetEmpty();
                            try
                            {
                                p.SetValue(item, GetFileContentAddValue(value, attr.FileStorageType));
                            }
                            catch (System.Exception e)
                            {
                                p.SetValue(item, value);
                            }
                        }
                    }
                }
            }
            return ls;
        }
        /// <summary>
        /// 文件转换，上传文件返回的ID，通过此方法转换为Base64字符，并返回
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="model"></param>
        /// <returns></returns>
        public T GetFileContentAdd<T>(T model) where T : IContentModel, new()
        {
            PropertyInfo[] propertys = model.GetType().GetProperties();
            if (propertys != null && propertys.Length > 0)
            {
                foreach (PropertyInfo p in propertys)
                {
                    object[] objAttrs = p.GetCustomAttributes(typeof(ContentAttibute), true);
                    object[] tabledetailAttrs = p.GetCustomAttributes(typeof(TableAttibute), true);
                    if (objAttrs != null && objAttrs.Length > 0)
                    {
                        TableAttibute attr = tabledetailAttrs[0] as TableAttibute;
                        var rowname = attr.RowName;
                        if (rowname.ToLower() != "Id".ToLower())
                        {
                            var value = p.GetValue(model).IsNullSetEmpty();
                            try
                            {
                                p.SetValue(model, GetFileContentAddValue(value, attr.FileStorageType));
                            }
                            catch (System.Exception e)
                            {
                                p.SetValue(model, value);
                            }
                        }
                    }
                }
            }
            return model;
        }

        /// <summary>
        /// 文件转换，查询DB文件值，并将ALI OSS以前的文件下载到本地并更新DB
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ls"></param>
        /// <returns></returns>
        public List<T> GetFileContentSelect<T>(List<T> ls) where T : IContentModel, new()
        {
            List<T> updatels = new List<T>();

            List<PropertyInfo> prlist = new List<PropertyInfo>();
            Type t = typeof(T);
            Array.ForEach<PropertyInfo>(t.GetProperties(), p => { prlist.Add(p); });
            foreach (var item in ls)
            {
                var isChange = false;
                foreach (PropertyInfo p in prlist)
                {
                    object[] objAttrs = p.GetCustomAttributes(typeof(ContentAttibute), true);
                    object[] tabledetailAttrs = p.GetCustomAttributes(typeof(TableAttibute), true);
                    if (objAttrs != null && objAttrs.Length > 0)
                    {
                        TableAttibute tableattr = tabledetailAttrs[0] as TableAttibute;
                        ContentAttibute attr = objAttrs[0] as ContentAttibute;
                        //如果传入的集合数据没有Id，那么直接忽略本条数据的特殊处理
                        if (string.IsNullOrEmpty(p.GetValue(item).IsNullSetEmpty()))
                        {
                            break;
                        }
                        var value = p.GetValue(item).IsNullSetEmpty();
                        //用存在防止Contains检索全文
                        if (value.Contains(DES.HashKey)) { }
                        else
                        {
                            p.SetValue(item, DownLoadAliOSSFileSaveLocalAndDB(value, attr.Type).ToJson());
                            isChange = true;
                        }
                    }
                }
                if (isChange)
                    updatels.Add(item);
            }
            if (updatels.Any())
                _fileRepository.PerformSql(prlist.AppendSqlSelect<T>(updatels));
            return ls;
        }
        /// <summary>
        ///  文件转换，查询DB文件值，并将ALI OSS以前的文件下载到本地并更新DB
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="model"></param>
        /// <returns></returns>
        public T GetFileContentSelect<T>(T model) where T : IContentModel, new()
        {
            List<PropertyInfo> prlist = new List<PropertyInfo>();
            Type t = typeof(T);
            Array.ForEach<PropertyInfo>(t.GetProperties(), p => { prlist.Add(p); });
            var isChange = false;
            foreach (PropertyInfo p in prlist)
            {
                object[] objAttrs = p.GetCustomAttributes(typeof(ContentAttibute), true);
                object[] tabledetailAttrs = p.GetCustomAttributes(typeof(TableAttibute), true);
                if (objAttrs != null && objAttrs.Length > 0)
                {
                    TableAttibute tableattr = tabledetailAttrs[0] as TableAttibute;
                    ContentAttibute attr = objAttrs[0] as ContentAttibute;
                    if (string.IsNullOrEmpty(p.GetValue(model).IsNullSetEmpty()))
                    {
                        break;
                    }
                    var value = p.GetValue(model).IsNullSetEmpty();
                    //用存在防止Contains检索全文,文件hash在字符前几位
                    if (value.Contains(DES.HashKey)) { }
                    else
                    {
                        p.SetValue(model, DownLoadAliOSSFileSaveLocalAndDB(value, attr.Type).ToJson());
                        isChange = true;
                    }
                }
            }
            if (isChange)
                _fileRepository.PerformSql(prlist.AppendSqlSelect<T>(model));
            return model;
        }

        /// <summary>
        /// 通过文件ID，获取文件详情，并将缩略图填充返回的文件字段
        /// </summary>
        /// <param name="value">文件ID，半圆角,区分</param>
        /// <returns></returns>
        private string GetFileContentAddValue(string value, int fileStorageType = 1)
        {
            FileContenModel fileConten = new FileContenModel();
            //读取FileId
            List<int> Ids = value.Split(',').ToList().Select<string, int>(x => Convert.ToInt32(x)).ToList();
            //通过FileId获取FileContent
            var file = _fileRepository.GetFilesForThumbnail(Ids);
            int[] ids = new int[] { };
            List<FileContentDetailModel> detail = new List<FileContentDetailModel>();
            file.ForEach(w =>
            {
                if (fileStorageType == 1)
                    detail.Add(new FileContentDetailModel { Key = w.ContentType, Content = string.IsNullOrEmpty(w.Thumbnail) ? w.Content : w.Thumbnail, Id = w.Id });
                else
                    detail.Add(new FileContentDetailModel { Key = w.ContentType, Content = w.Content, Id = w.Id });
            });
            fileConten.Content = detail;
            fileConten.HashKey = DES.HashKey;
            return fileConten.ToJson();
        }
        /// <summary>
        /// 下载aliOSS文件到本地，并保存到DB
        /// </summary>
        /// <param name="url"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public FileContenModel DownLoadAliOSSFileSaveLocalAndDB(string url, int type)
        {
            FileContenModel fileConten = new FileContenModel();
            fileConten.HashKey = DES.HashKey;
            foreach (var item in url.Split(','))
            {
                var filenamels = url.Split('/').ToList();
                if (!filenamels.Any())
                {
                    filenamels = url.Split('\\').ToList();
                }
                string filename = filenamels[filenamels.Count - 1];

                string fnames = filename.Substring(0, filename.LastIndexOf("."));
                string fix = filename.Substring(filename.LastIndexOf(".") + 1);

                var bytes = CompressImage(DownloadFile(item));
                //图片压缩
                string thumbnail = GetThumbnail(bytes);

                fileConten.Content.Add(new FileContentDetailModel { Key = fix, Content = thumbnail, Id = UploadLocalhost(bytes, fnames, fix, type) });
            }
            return fileConten;
        }
        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public byte[] DownloadFile(string url)
        {
            byte[] bytes;
            HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url);
            req.Method = "GET";
            using (WebResponse wr = req.GetResponse())
            {
                StreamReader responseStream = new StreamReader(wr.GetResponseStream(), Encoding.UTF8);
                int length = (int)wr.ContentLength;
                byte[] bs = new byte[length];

                HttpWebResponse response = wr as HttpWebResponse;
                Stream stream = response.GetResponseStream();

                MemoryStream stmMemory = new MemoryStream();
                byte[] buffer1 = new byte[length];
                int i;
                while ((i = stream.Read(buffer1, 0, buffer1.Length)) > 0)
                {
                    stmMemory.Write(buffer1, 0, i);
                }
                bytes = stmMemory.ToArray();
                stmMemory.Close();
            }
            return bytes;
        }
        /// <summary>
        /// 保存文件到本地，并存储到DB
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="fnames">文件名</param>
        /// <param name="fix">后缀</param>
        /// <param name="type">存储地址 0 不使用，默认值 1 本地服务器(病情图片文件) 2 数据库(证件照) 3 数据库(保险卡) 4 本地服务器(IM聊天文件)</param>
        /// <returns></returns>
        public int UploadLocalhost(byte[] bytes, string fnames, string fix, int type)
        {
            string url = string.Empty;
            var content = string.Empty;
            var thumbnail = string.Empty;

            string filename = fnames + "_" + UploadHelper.newCode() + DateTime.Now.ToString("yyyyMMddHHmmssfff") + "." + fix;
            switch (type)
            {
                case 1:
                    if ("bmp,jpg,jpeg,png,tif,gif,pcx,tga,exif,fpx,svg,psd,cdr,pcd,dxf,ufo,eps,ai,raw,WMF,webp,avif,apng".Split(',').ToList().Where(w => w.ToLower() == fix.ToLower()).Any())
                    {
                        filename = @"IllnessPic\" + filename;
                    }
                    else
                    {
                        filename = @"IllnessFile\" + filename;
                    }
                    break;
                case 2:
                    filename = @"IDCard\" + filename;
                    break;
                case 3:
                    filename = @"InsuranceCard\" + filename;
                    break;
                case 5:
                    filename = @"InsuranceCard\" + "体检问卷" + DateTime.Now.ToString("yyyy-MM-ddHHmmssfff") + "." + fix;
                    break;
                default:
                    filename = @"IMFile\" + filename;
                    break;
            }
            if ("bmp,jpg,jpeg,png,tif,gif,pcx,tga,exif,fpx,svg,psd,cdr,pcd,dxf,ufo,eps,ai,raw,WMF,webp,avif,apng".Split(',').ToList().Where(w => w.ToLower() == fix.ToLower()).Any())
            {
                thumbnail = GetThumbnail(bytes);
            }
            //｛
            //bytes转成IMG IMG 打上水印 转成  bytes
            //    ｝
            content = Convert.ToBase64String(bytes);
            FileStream fs = new FileStream(storage + filename, FileMode.Create);
            fs.Write(bytes, 0, bytes.Length);
            fs.Dispose();

            //FileStream fss = new FileStream(storage + @"IMFile\暗哨isho.png", FileMode.Create);
            //fss.Write(thumbnailbytes, 0, thumbnailbytes.Length);
            //fss.Dispose();

            url = filename;
            var id = _fileRepository.InsertFile(new Sys_File { FileUrl = url, Content = content, FileType = type, IP = fileUrl, ContentType = fix, Thumbnail = thumbnail });
            return id;
        }
        public byte[] StreamToBytes(Stream stream)
        {
            byte[] bytes = new byte[stream.Length];
            stream.Read(bytes, 0, bytes.Length);
            stream.Seek(0, SeekOrigin.Begin);
            return bytes;
        }

        private string Base64StringToFile(string content, string filename, string filetype)
        {
            if (filename.Length > 40)
            {
                string[] ar = Regex.Split(filename, "_20", RegexOptions.IgnoreCase);
                filename = Guid.NewGuid() + ar[1];
            }
            filename = filename + "." + filetype;
            StringBuilder txtstring = new StringBuilder();
            byte[] array = Encoding.ASCII.GetBytes(content);
            MemoryStream stream1 = new MemoryStream(array);
            System.IO.StreamReader sr = new System.IO.StreamReader(stream1, Encoding.Default);
            String line;
            while ((line = sr.ReadLine()) != null)
            {
                txtstring.Append(line.ToString());
            }
            try
            {
                string strbase64 = txtstring.ToString();
                strbase64 = strbase64.Replace(' ', '+');
                System.IO.MemoryStream stream = new System.IO.MemoryStream(Convert.FromBase64String(strbase64));
                var res = UploadHelper.UploadToStream(stream, filename);
                return res;
            }
            catch (System.Exception e)
            {
            }
            return "";
        }
        /// <summary>
        /// 生成缩略图
        /// </summary>
        /// <param name="Width"></param>
        /// <param name="Height"></param>
        /// <param name="streamByte"></param>
        /// <returns></returns>
        private static Image GetReducedImage(int Width, int Height, byte[] streamByte)
        {
            try
            {
                Image ReducedImage;
                System.IO.MemoryStream ms = new System.IO.MemoryStream(streamByte);
                Image img = Image.FromStream(ms);
                Image.GetThumbnailImageAbort callb = new Image.GetThumbnailImageAbort(ThumbnailCallback);
                ReducedImage = img.GetThumbnailImage(Width, Height, callb, IntPtr.Zero);

                return ReducedImage;
            }
            catch
            {
                return null;
            }
        }

        private static bool ThumbnailCallback()
        {
            return false;
        }

        /// <summary>
        /// img转byte[]
        /// </summary>
        /// <param name="img"></param>
        /// <returns></returns>
        private static byte[] GetByteImage(Image img)
        {
            byte[] bt = null;
            if (!img.Equals(null))
            {
                using (MemoryStream mostream = new MemoryStream())
                {
                    Bitmap bmp = new Bitmap(img);
                    bmp.Save(mostream, System.Drawing.Imaging.ImageFormat.Bmp);

                    bt = new byte[mostream.Length];
                    mostream.Position = 0;
                    mostream.Read(bt, 0, Convert.ToInt32(bt.Length));
                }
            }
            return bt;
        }

        private static string GetThumbnail(byte[] bytes)
        {
            //查询时下载oss文件，并将图片压缩,返回base64
            string thumbnail = Convert.ToBase64String(GetByteImage(GetReducedImage(80, 80, bytes)));
            return thumbnail;
        }

        /// <summary>
        /// 无损压缩图片
        /// </summary>
        /// <param name="bytes">图片文件byte</param>
        /// <param name="flag">压缩质量（数字越小压缩率越高）1-100</param>
        /// <param name="size">压缩后图片的最大大小KB</param>
        /// <param name="sfsc">是否是第一次调用</param>
        /// <returns></returns>
        public byte[] CompressImage(byte[] bytes, int flag = 90, int size = 400, bool sfsc = true)
        {
            //如果是第一次调用，原始图像的大小小于要压缩的大小，则直接复制文件，并且返回true
            if (sfsc == true && bytes.Length < size * 1024)
            {
                return bytes;
            }

            System.IO.MemoryStream ms = new System.IO.MemoryStream(bytes);
            Image iSource = Image.FromStream(ms);
            ImageFormat tFormat = iSource.RawFormat;
            int dHeight = iSource.Height / 2;
            int dWidth = iSource.Width / 2;
            int sW = 0, sH = 0;
            //按比例缩放
            Size tem_size = new Size(iSource.Width, iSource.Height);
            if (tem_size.Width > dHeight || tem_size.Width > dWidth)
            {
                if ((tem_size.Width * dHeight) > (tem_size.Width * dWidth))
                {
                    sW = dWidth;
                    sH = (dWidth * tem_size.Height) / tem_size.Width;
                }
                else
                {
                    sH = dHeight;
                    sW = (tem_size.Width * dHeight) / tem_size.Height;
                }
            }
            else
            {
                sW = tem_size.Width;
                sH = tem_size.Height;
            }

            Bitmap ob = new Bitmap(dWidth, dHeight);
            Graphics g = Graphics.FromImage(ob);

            g.Clear(Color.WhiteSmoke);
            g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

            g.DrawImage(iSource, new Rectangle((dWidth - sW) / 2, (dHeight - sH) / 2, sW, sH), 0, 0, iSource.Width, iSource.Height, GraphicsUnit.Pixel);

            g.Dispose();

            //以下代码为保存图片时，设置压缩质量
            EncoderParameters ep = new EncoderParameters();
            long[] qy = new long[1];
            qy[0] = flag;//设置压缩的比例1-100
            EncoderParameter eParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qy);
            ep.Param[0] = eParam;
            var path = storage + @"Compress\" + Guid.NewGuid().ToString() + ".jpg";
            try
            {
                ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders();
                ImageCodecInfo jpegICIinfo = null;
                for (int x = 0; x < arrayICI.Length; x++)
                {
                    if (arrayICI[x].FormatDescription.Equals("JPEG"))
                    {
                        jpegICIinfo = arrayICI[x];
                        break;
                    }
                }
                if (jpegICIinfo != null)
                {
                    ob.Save(path, jpegICIinfo, ep);
                    bytes = File.ReadAllBytes(path);
                    File.Delete(path);
                    if (bytes.Length > size * 1024)
                    {
                        flag = flag - 10;
                        bytes = CompressImage(bytes, flag, size, false);
                    }
                }
                else
                {
                    ob.Save(path, tFormat);
                }
                return bytes;
            }
            catch
            {

            }
            finally
            {
                iSource.Dispose();
                ob.Dispose();
            }
            return bytes;
        }

    }
}
