using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Caching.Distributed;
using Api.SignToken;
using Microsoft.Extensions.Logging;
using MadRunFabric.Common;
using Microsoft.AspNetCore.Hosting;
using FileServerApi.Common;
using System.IO;
using Microsoft.AspNetCore.Http;
using System.Web;
using Microsoft.AspNetCore.StaticFiles;
using System.Text;

namespace FileServerApi.Controllers
{
    [ApiVersion("6.0")]
    //[Authorize]
    //[RequestSizeLimit(1073741822)]//1GB
    [DisableRequestSizeLimit]//无限制
    [Route("api/[controller]")]
    public class UploadController : BaseController
    {

        private readonly IConfiguration _configuration;
        private readonly IHostingEnvironment _hostingEnvironment;
        private readonly IDistributedCache _cache;
        private static IPermissionService _permissionService;
        private readonly ILogger<UploadController> _logger;

        public UploadController(IHostingEnvironment hostingEnvironment, IConfiguration configuration, IDistributedCache cache, IPermissionService permissionService, ILogger<UploadController> logger)
        {
            _hostingEnvironment = hostingEnvironment;
            _configuration = configuration;
            _cache = cache;
            _permissionService = permissionService;
            _logger = logger;
        }

        /// <summary>
        /// 获取附件/删除附件
        /// </summary>
        /// <param name="key"></param>
        /// <param name="isdel"></param>
        /// <returns></returns>
        [HttpGet("{key}")]
        public IActionResult Get(string key, int isdel = 0)
        {
            string pathname = DESEncrypt.DecryptDES(key);
            string[] strs = pathname.Split("||");
            if (isdel > 0)
            {
                System.IO.File.Delete(strs[0]);
                return Success("删除成功");
            }
            _logger.LogDebug("文件路径：" + pathname);
            //_logger.LogError("文件路径：" + pathname);
            if (System.IO.File.Exists(strs[0]))
            {
                //var stream = System.IO.File.OpenRead(strs[0]);

                var fileExt = Path.GetExtension(strs[1]);
                ////获取文件的ContentType
                //var provider = new FileExtensionContentTypeProvider();
                //var memi = provider.Mappings[fileExt];

                //return File(stream, memi, Path.GetFileName(strs[1]));

                //IE在处理 Response Header 的时候，对header的长度限制在150字节左右。而一个汉字编码成UTF-8是9个字节，那么17个字便是153个字节，所以会
                System.Net.Mime.ContentDisposition cd = new System.Net.Mime.ContentDisposition
                {
                    FileName = GetSubstr(strs[1]),   // Path.GetFileName(strs[1]),
                    Inline = false  // false = prompt the user for downloading;  true = browser to try to show the file inline
                };
                Response.Headers.Add("Content-Disposition", cd.ToString());
                Response.Headers.Add("X-Content-Type-Options", "nosniff");

                return File(System.IO.File.ReadAllBytes(strs[0]), "application/octet-stream");
            }
            else
            {
                string[] filetypes = new string[] { ".jpg", ".jpeg", ".gif", ".bmp", ".png" };

                var defaultbase64 = _configuration["File:defaultfile"].ToString();
                if (filetypes.Contains(Path.GetExtension(strs[1])))
                {
                    defaultbase64 = _configuration["File:defaultphoto"].ToString();
                }

                int delLength = defaultbase64.IndexOf(',') + 1;
                string strimg = defaultbase64.Substring(delLength, defaultbase64.Length - delLength);
                byte[] bData = Convert.FromBase64String(strimg);

                //return File(bData, "image/jpeg", "error.jpg");

                System.Net.Mime.ContentDisposition cd = new System.Net.Mime.ContentDisposition
                {
                    FileName = "error.jpg",
                    Inline = false  // false = prompt the user for downloading;  true = browser to try to show the file inline
                };
                Response.Headers.Add("Content-Disposition", cd.ToString());
                Response.Headers.Add("X-Content-Type-Options", "nosniff");

                return File(bData, "image/jpeg");
            }
        }

        /// <summary>
        /// 上传附件
        /// </summary>
        /// <param name="cols"></param>
        /// <returns></returns>
        //[Consumes("application/json", "multipart/form-data")]
        [HttpPost]
        public async Task<IActionResult> Post(IFormCollection cols)
        {
            try
            {
                string type = cols["uploadtype"];
                if (string.IsNullOrEmpty(type)) type = _configuration["File:type"].ToString();
                string webRootPath = _hostingEnvironment.WebRootPath;
                string contentRootPath = _hostingEnvironment.ContentRootPath;
                string urlpre = _configuration["File:url"].ToString() + "/api/Upload/";
                string pre = _configuration["File:path"].ToString();
                var path = (string.IsNullOrEmpty(pre) ? contentRootPath + "/upload/" : pre) + type + "/";
                path = path + DateTime.Now.ToString("yyyy") + "/" + DateTime.Now.ToString("MM") + "/" + DateTime.Now.ToString("dd") + "/";

                if (!Directory.Exists(path)) Directory.CreateDirectory(path);

                List<FileClass.FileInfo> strfiles = new List<FileClass.FileInfo>();

                string filesjson = cols["filesjson"];
                if (!string.IsNullOrEmpty(filesjson))
                {
                    List<FileClass.Base64Info> jsons = filesjson.ToList<FileClass.Base64Info>();
                    foreach (var l in jsons)
                    {
                        int delLength = l.fileurl.IndexOf(',') + 1;
                        string strimg = l.fileurl.Substring(delLength, l.fileurl.Length - delLength);
                        byte[] bData = Convert.FromBase64String(strimg);

                        string fileExt = Path.GetExtension(l.filename); //文件扩展名，含“.”
                        long fileSize = bData.Length; //获得文件大小，以字节为单位

                        string newFileName = System.Guid.NewGuid().ToString() + fileExt; //随机生成新的文件名
                        
                        using (var stream = new FileStream(path + newFileName, FileMode.Create))
                        {
                            await stream.WriteAsync(bData,0, bData.Length);
                        }
                        string filemd5 = Common.Common.GetMD5HashFromFile(path + newFileName);
                        string key = DESEncrypt.EncryptDES(path + newFileName + "||" + l.filename);


                        FileClass.FileInfo fl = new FileClass.FileInfo();
                        fl.fileext = fileExt;
                        fl.filename = l.filename;
                        fl.filesize = fileSize.ToString();
                        fl.fileurl = urlpre + key;

                        try
                        {
                            string slname = Common.Common.GetThumbImg(path, newFileName, fileExt);
                            if (slname != "")
                            {
                                string slkey = DESEncrypt.EncryptDES(path + slname + "||" + l.filename);
                                fl.filesmallurl = urlpre + slkey;
                            }
                        }
                        catch (Exception ex)
                        {
                            _logger.LogError("生成缩略图失败，原因：" + ex.ToString());
                            fl.filesmallurl = urlpre + key;
                        }
                        
                        fl.filemd5 = filemd5;

                        strfiles.Add(fl);
                    }
                }

                foreach (var file in cols.Files)
                {
                    string fileName = file.FileName;
                    string fileExt = Path.GetExtension(fileName); //文件扩展名，含“.”
                    long fileSize = file.Length; //获得文件大小，以字节为单位
                    string newFileName = System.Guid.NewGuid().ToString() + fileExt; //随机生成新的文件名

                    using (var stream = new FileStream(path + newFileName, FileMode.Create))
                    {
                        await file.CopyToAsync(stream);
                    }
                    string filemd5 = Common.Common.GetMD5HashFromFile(path + newFileName);
                    string key = DESEncrypt.EncryptDES(path + newFileName + "||" + fileName);

                    FileClass.FileInfo fl = new FileClass.FileInfo();
                    fl.fileext = fileExt;
                    fl.filename = fileName;
                    fl.filesize = fileSize.ToString();
                    fl.fileurl = urlpre + key;

                    try
                    {
                        string slname = Common.Common.GetThumbImg(path, newFileName, fileExt);
                        if (slname != "")
                        {
                            string slkey = DESEncrypt.EncryptDES(path + slname + "||" + fileName);
                            fl.filesmallurl = urlpre + slkey;
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError("生成缩略图失败，原因：" + ex.ToString());
                        fl.filesmallurl = urlpre + key;
                    }

                    fl.filemd5 = filemd5;

                    strfiles.Add(fl);
                }

                return Success("上传成功", strfiles);
            }
            catch(Exception ex)
            {
                return Error("上传失败，原因：" + ex.ToString());
            }
        }

        /// <summary>
        /// 获取缩短的文件标题 - 例如：aaaaaa..bbbb.pfd
        /// </summary>
        /// <param name="unicodeString"></param>
        /// <returns></returns>
        public string GetSubstr(string str)
        {

            try
            {
                //类型 .pdf - 截取.后面的字符串
                string Extension = str.Substring(str.LastIndexOf("."));
                //名称 - 截取.前面的字符串
                string title = str.Remove(str.LastIndexOf("."));
                //名称不为空
                if (!string.IsNullOrEmpty(title))
                {
                    if (title.Length > 9)
                    {
                        //IE在处理 Response Header 的时候，对header的长度限制在150字节左右。而一个汉字编码成UTF-8是9个字节，那么17个字便是153个字节，所以会
                        string Str_before = title.Substring(0, 5);
                        string Str_after = title.Substring(title.Length - 4, 4);
                        //拼接字符串 例如：aaaaaa..bbbb.pfd
                        return Str_before + ".." + Str_after + Extension;
                    }
                    return title + Extension;
                }
                return str;
            }
            catch (Exception ex)
            {
                return DateTimeHelper.GetDateTime();
            }
        }

        /// <summary>
        /// 删除附件
        /// </summary>
        /// <param name="keys"></param>
        /// <returns></returns>
        [HttpDelete]
        public IActionResult Delete(string keys)
        {
            foreach (string key in keys.Split(","))
            {
                string pathname = DESEncrypt.DecryptDES(key);
                string[] strs = pathname.Split("||");
                System.IO.File.Delete(strs[0]);
            }

            return Success("删除成功");
        }

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        [HttpGet("decrypt")]
        public IActionResult Decrypt(string key)
        {
            return Success("解密成功",DESEncrypt.DecryptDES(key));
        }

        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        [HttpGet("encrypt")]
        public IActionResult Encrypt(string path)
        {
            return Success("加密成功", DESEncrypt.EncryptDES(HttpUtility.UrlDecode(path)));
        }
    }
}
