using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Repository.Models
{
    /// <summary>
    /// Encryption Decryption Function - 加解密
    /// </summary>
    /// 
    public class EDFunctionKey
    {
        public string AES_KEY //AES_KEY金鑰
        {
            get {
                return "TAIPEIDO";
            }
        }

        public string AES_IV //AES_IV初始化向量字串
        {
            get {
                return "TAIPEIDO";
            }
        }
    }
    

    public class EDFunction
    {
        const string SHA256_KEY = "DOMETAIPEI"; //自訂金鑰
        const string DES_KEY = "TAIPEIDO"; //DES_KEY金鑰(8位字元)
        const string DES_IV = "TAIPEIDO"; //DES_IV初始化向量字串(8位字元)

        EDFunctionKey EDFunctionKey = new EDFunctionKey();
        //const string AES_KEY = "HUMANESA"; //AES_KEY金鑰
        //const string AES_IV = "HUMANESA"; //AES_IV初始化向量字串

        /// <summary>
        /// 單向加密SHA256
        /// </summary>
        /// <param name="text">加密字串</param>
        /// <returns></returns>
        public string GetSHA256Encryption(string text)
        {
            string signRet = string.Empty;
            byte[] key_byte = Encoding.Default.GetBytes(SHA256_KEY);

            using (HMACSHA256 mac = new HMACSHA256(key_byte))
            {
                byte[] source = Encoding.Default.GetBytes(text);//將字串轉為Byte[]
                byte[] crypto = mac.ComputeHash(source);//進行SHA256加密
                signRet = Convert.ToBase64String(crypto);//把加密後的字串從Byte[]轉為字串
            }

            return signRet;
        }

        /// <summary>
        /// DES加密
        /// </summary>
        /// <param name="text">待加密資料</param>
        /// <returns></returns>
        public string DESEncrypt(string text)
        {
            try
            {
                byte[] byKey = Encoding.ASCII.GetBytes(DES_KEY); //密鑰
                byte[] byIV = Encoding.ASCII.GetBytes(DES_IV); //IV值
                byte[] data = Encoding.Unicode.GetBytes(text);

                DESCryptoServiceProvider cryptoProvider = new DESCryptoServiceProvider();//加密、解密對象
                MemoryStream MStream = new MemoryStream();//內存流對象

                //用內存流實例化加密流對象
                CryptoStream CStream = new CryptoStream(MStream, cryptoProvider.CreateEncryptor(byKey, byIV), CryptoStreamMode.Write);
                CStream.Write(data, 0, data.Length);//向加密流中寫入數據
                CStream.FlushFinalBlock();//將數據壓入基礎流
                byte[] temp = MStream.ToArray();//從內存流中獲取字節序列
                CStream.Close();//關閉加密流
                MStream.Close();//關閉內存流

                return Convert.ToBase64String(temp);//返回加密後的字符串
            }
            catch
            {
                return text;
            }
        }

        /// <summary>
        /// DES解密
        /// </summary>
        /// <param name="text">待解密字符串</param>
        /// <returns></returns>
        public string DESDecrypt(string text)
        {
            try
            {
                byte[] byKey = Encoding.ASCII.GetBytes(DES_KEY); //DES密鑰
                byte[] byIV = Encoding.ASCII.GetBytes(DES_IV); //IV值
                byte[] data = Convert.FromBase64String(text);

                DESCryptoServiceProvider descsp = new DESCryptoServiceProvider();
                MemoryStream MStream = new MemoryStream();

                //用內存流實例化解密流對象
                CryptoStream CStream = new CryptoStream(MStream, descsp.CreateDecryptor(byKey, byIV), CryptoStreamMode.Write);
                CStream.Write(data, 0, data.Length);//向加密流中寫入數據
                CStream.FlushFinalBlock();//將數據壓入基礎流
                byte[] temp = MStream.ToArray();//從內存流中獲取字節序列
                CStream.Close();//關閉加密流
                MStream.Close();//關閉內存流

                return Encoding.Unicode.GetString(temp);//返回解密後的字符串

            }
            catch
            {
                return text;
            }
        }

        /// <summary>
        /// AES加密
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public string AESEncrypt(string text)
        {
            var encrypt = "";
            try
            {
                AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
                MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
                SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider();

                
                byte[] keyData = sha256.ComputeHash(Encoding.UTF8.GetBytes(EDFunctionKey.AES_KEY));
                byte[] ivData = md5.ComputeHash(Encoding.UTF8.GetBytes(EDFunctionKey.AES_IV));
                byte[] dataByteArray = Encoding.UTF8.GetBytes(text);

                using (MemoryStream ms = new MemoryStream())
                {
                    using (
                        CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(keyData, ivData), CryptoStreamMode.Write)
                    )
                    {
                        cs.Write(dataByteArray, 0, dataByteArray.Length);
                        cs.FlushFinalBlock();
                        encrypt = Convert.ToBase64String(ms.ToArray());
                    }
                }

                return encrypt;
            }
            catch
            {
                return text;
            }
        }

        /// <summary>
        /// AES解密
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public string AESDecrypt(string text)
        {
            var decrypt = "";
            try
            {
                SymmetricAlgorithm aes = new AesCryptoServiceProvider();
                MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
                SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider();
                byte[] keyData = sha256.ComputeHash(Encoding.UTF8.GetBytes(EDFunctionKey.AES_KEY));
                byte[] ivData = md5.ComputeHash(Encoding.UTF8.GetBytes(EDFunctionKey.AES_IV));
                byte[] dataByteArray = Convert.FromBase64String(text);

                using (MemoryStream ms = new MemoryStream())
                {
                    using (
                        CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(keyData, ivData), CryptoStreamMode.Write)
                    )
                    {
                        cs.Write(dataByteArray, 0, dataByteArray.Length);
                        cs.FlushFinalBlock();
                        decrypt = Encoding.UTF8.GetString(ms.ToArray());
                    }
                }

                return decrypt;
            }
            catch
            {
                return text;
            }
        }
    }

    /// <summary>
    /// 回傳結果
    /// </summary>
    /// <typeparam name="T">資料型別</typeparam>
    public class ApiResult<T>
    {
        public string Code { get; set; }
        public string Msg { get; set; }
        public T Data { get; set; }
    }

    /// <summary>
    /// 資料夾
    /// </summary>
    public class FolderFunction
    {
        /// <summary>
        /// 創建資料夾
        /// </summary>
        /// <param name="folderPath"></param>
        /// <param name="tempType">0:找到資料夾也不刪除 1:找到資料夾並且刪除</param>
        public void CreateFolder(string folderPath, int type)
        {
            DirectoryInfo dInfo = new DirectoryInfo(folderPath);

            if (dInfo.Exists) //找到
            {
                if (type == 1)
                {
                    dInfo.Delete(true); //如果資料夾裡面有檔案給bool參數就可以直接刪除,沒給bool參數會報錯誤
                }

                dInfo.Create();
            }
            else //沒找到
            {
                dInfo.Create(); //建立新的資料夾
            }
        }

        /// <summary>
        /// 刪除檔案
        /// </summary>
        /// <param name="filePath"></param>
        public void DeleteFile(string filePath)
        {
            System.IO.FileInfo file = new System.IO.FileInfo(filePath);
            if (File.Exists(filePath)) //找到
            {
                //do something
                file.Delete();
            }
            else //沒找到
            {
                //do something
            }
        }
    }
}