using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;

namespace ASHermed.SinoInterface.Tools
{
    public static class Extend
    {
        /// <summary>
        /// 加密
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="model"></param>
        public static T Encrypt<T>(this T model) where T : IDataModel, new()
        {
            if (model == null)
                return model;
            PropertyInfo[] propertys = model.GetType().GetProperties();
            if (propertys != null && propertys.Length > 0)
            {
                foreach (PropertyInfo p in propertys)
                {
                    object[] objAttrs = p.GetCustomAttributes(typeof(EncryptyAttibute), true);
                    if (objAttrs != null && objAttrs.Length > 0)
                    {
                        if (p.GetValue(model).IsNullSetEmpty().Contains(DES.DESKey)) { }
                        else
                        {
                            p.SetValue(model, DES.EncodeDES(p.GetValue(model).IsNullSetEmpty(), DES.DESKey));
                        }
                    }
                }
            }
            return model;
        }
        /// <summary>
        /// 加密
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <returns></returns>
        public static List<T> Encrypt<T>(this List<T> list) where T : IDataModel, new()
        {
            if (!list.Any())
                return list;
            List<PropertyInfo> prlist = new List<PropertyInfo>();
            Type t = typeof(T);
            Array.ForEach<PropertyInfo>(t.GetProperties(), p => { prlist.Add(p); });
            foreach (var item in list)
            {
                foreach (PropertyInfo p in prlist)
                {
                    object[] objAttrs = p.GetCustomAttributes(typeof(EncryptyAttibute), true);
                    if (objAttrs != null && objAttrs.Length > 0)
                    {
                        if (p.GetValue(item).IsNullSetEmpty().Contains(DES.DESKey)) { }
                        else
                        {
                            p.SetValue(item, DES.EncodeDES(p.GetValue(item).IsNullSetEmpty(), DES.DESKey));
                        }
                    }
                }
            }
            return list;
        }
        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string Encrypt(this string str)
        {
            if (string.IsNullOrEmpty(str))
                return str;
            var res = DES.EncodeDES(str, DES.DESKey);
            return res;
        }

        public static string PhoneDesensitization(this string str)
        {
            if (string.IsNullOrEmpty(str)) return string.Empty;
            return Regex.Replace(str, "(\\d{3})\\d{4}(\\d{4})", "$1****$2");
        }

        public static string NameDesensitization(this string str)
        {
            if (string.IsNullOrEmpty(str)) return string.Empty;

            string familyName = str.Substring(0, 1);
            string end = str.Substring(str.Length - 1, 1);
            string name = string.Empty;
            //长度为2
            if (str.Length <= 2) name = familyName + "*";
            //长度大于2
            else if (str.Length >= 3)
            {
                name = familyName.PadRight(str.Length - 1, '*') + end;
            }
            return name;
        }

        /// <summary>
        /// 解密
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="model"></param>
        public static T DeEncrypt<T>(this T model) where T : IDataModel, new()
        {
            if (model == null)
                return model;
            PropertyInfo[] propertys = model.GetType().GetProperties();
            if (propertys != null && propertys.Length > 0)
            {
                foreach (PropertyInfo p in propertys)
                {
                    object[] objAttrs = p.GetCustomAttributes(typeof(DeEncryptAttibute), true);
                    if (objAttrs != null && objAttrs.Length > 0)
                    {
                        if (p.GetValue(model).IsNullSetEmpty().Contains(DES.DESKey)) { }
                        else
                        {
                            p.SetValue(model, DES.DecodeDES(p.GetValue(model).IsNullSetEmpty(), DES.DESKey));
                        }
                    }
                }
            }
            return model;
        }
        /// <summary>
        /// 解密
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <returns></returns>
        public static List<T> DeEncrypt<T>(this List<T> list) where T : IDataModel, new()
        {
            if (!list.Any())
                return list;
            List<PropertyInfo> prlist = new List<PropertyInfo>();
            Type t = typeof(T);
            Array.ForEach<PropertyInfo>(t.GetProperties(), p => { prlist.Add(p); });
            foreach (var item in list)
            {
                foreach (PropertyInfo p in prlist)
                {
                    object[] objAttrs = p.GetCustomAttributes(typeof(DeEncryptAttibute), true);
                    if (objAttrs != null && objAttrs.Length > 0)
                    {
                        if (p.GetValue(item).IsNullSetEmpty().Contains(DES.DESKey)) { }
                        else
                        {
                            p.SetValue(item, DES.DecodeDES(p.GetValue(item).IsNullSetEmpty(), DES.DESKey));
                        }
                    }
                }
            }
            return list;
        }

        //public static string AppendSqlAdd<T>(this List<PropertyInfo> prlist, List<T> ls)
        //{

        //}


        public static string AppendSqlSelect<T>(this List<PropertyInfo> prlist, List<T> ls)
        {
            if (!ls.Any())
                return "";
            Type t = typeof(T);
            TableAttibute tableAttrs = t.GetCustomAttributes(typeof(TableAttibute), true)[0] as TableAttibute;
            var tableName = tableAttrs.RowName;

            string sql = string.Empty;
            foreach (var item in ls)
            {
                int idvalue = 0;
                string idrowName = string.Empty;
                sql += " Update " + tableName + " Set ";
                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) || (tabledetailAttrs != null && tabledetailAttrs.Length > 0))
                    {
                        //获取特性构造函数传入的DB字段名，用于将原有ALI OSS文件下载下来更新DB数据
                        TableAttibute attr = tabledetailAttrs[0] as TableAttibute;
                        var rowname = attr.RowName;
                        var value = p.GetValue(item).IsNullSetEmpty();
                        if (rowname.ToLower() == "Id".ToLower())
                        {
                            idvalue = int.Parse(value);
                            idrowName = rowname;
                        }
                        else
                        {
                            sql += "`" + rowname + "`" + " = '" + value + "',";
                        }
                    }
                }
                if (sql.Substring(sql.Length - 1, 1) == ",")
                {
                    sql = sql.Substring(0, sql.Length - 1);
                }
                sql += " Where " + "`" + idrowName + "`= " + idvalue + ";";
            }
            return sql;
        }

        public static string AppendSqlSelect<T>(this List<PropertyInfo> prlist, T model)
        {
            if (model == null)
                return "";
            Type t = typeof(T);
            TableAttibute tableAttrs = t.GetCustomAttributes(typeof(TableAttibute), true)[0] as TableAttibute;
            var tableName = tableAttrs.RowName;
            string sql = string.Empty;

            sql += " Update " + tableName + " Set ";
            int idvalue = 0;
            string idrowName = string.Empty;
            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) || (tabledetailAttrs != null && tabledetailAttrs.Length > 0))
                {
                    //获取特性构造函数传入的DB字段名，用于将原有ALI OSS文件下载下来更新DB数据
                    TableAttibute attr = tabledetailAttrs[0] as TableAttibute;
                    var rowname = attr.RowName;
                    var value = p.GetValue(model).IsNullSetEmpty();
                    if (rowname.ToLower() == "Id".ToLower())
                    {
                        idvalue = int.Parse(value);
                        idrowName = rowname;
                    }
                    else
                    {
                        sql += "`" + rowname + "`" + " = '" + value + "',";
                    }
                }
            }
            if (sql.Substring(sql.Length - 1, 1) == ",")
            {
                sql = sql.Substring(sql.Length - 1, 1);
            }
            sql += " Where " + "`" + idrowName + "`= " + idvalue + ";";
            return sql;
        }

        public static int[] ArrayAddelement(this int[] arr, int addele)
        {
            var newarr = arr.ToList();
            newarr.Add(addele);
            return newarr.ToArray(); ;
        }

        public static string IsNullSetEmpty(this object obj)
        {
            if (obj == null)
            {
                return "";
            }
            return obj.ToString();
        }
    }
    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
    public class EncryptyAttibute : Attribute
    {

    }
    public class DeEncryptAttibute : Attribute
    {

    }
    public class ContentAttibute : Attribute
    {
        public int Type;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="rowName"></param>
        /// <param name="type">存储地址 0 不使用，默认值 1 本地服务器(病情图片文件) 2 数据库(证件照) 3 数据库(保险卡) 4 本地服务器(IM聊天文件)</param>
        /// <param name="isChange">当前字段是否有过修改，配合查询时标记是否需要update当前字段</param>
        public ContentAttibute(int type = 0)
        {
            Type = type;
        }
    }
    public class TableAttibute : Attribute
    {
        public string RowName;
        /// <summary>
        /// 字段存储文件内容的类型，1默认值，缩略图，2压缩后的原图
        /// </summary>
        public int FileStorageType;
        public TableAttibute(string rowName, int fileStorageType = 1)
        {
            RowName = rowName;
            FileStorageType = fileStorageType;
        }
    }
    public interface IDataModel
    {

    }

    public interface IContentModel
    {

    }
    public class FileContenModel
    {
        public FileContenModel()
        {
            Content = new List<FileContentDetailModel>();
        }
        public string HashKey { get; set; }
        public List<FileContentDetailModel> Content { get; set; }
    }
    public class FileContentDetailModel
    {
        /// <summary>
        /// 文件表ID
        /// </summary>
        public int Id { get; set; }
        /// <summary>
        /// 文件类型 jpg pdf之类的
        /// </summary>
        public string Key { get; set; }
        /// <summary>
        /// 文件base64（源文件的缩略图）
        /// </summary>
        public string Content { get; set; }
    }
}
