using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using JiShe.CollectBus.Common.Attributes;

namespace JiShe.CollectBus.Common.Helpers
{
    public static class CommonHelper
    {
        /// <summary>
        /// 获得无符号GUID
        /// </summary>
        /// <returns></returns>
        public static string GetGUID()
        {
            return Guid.NewGuid().ToString("N");
        }

        /// <summary>
        /// 获取时间戳
        /// </summary>
        /// <param name="isSeconds">是否返回秒，false返回毫秒</param>
        /// <returns></returns>
        public static long GetTimeStampTen(bool isSeconds)
        {
            if (isSeconds)
            {
                return DateTimeOffset.UtcNow.ToUnixTimeSeconds();
            }
            else
            {
                return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
            }
        }

        /// <summary>
        /// 获取指定长度的随机数
        /// </summary>
        /// <param name="length"></param>
        /// <returns></returns>
        public static string GetRandomNumber(int length = 8)
        {
            if (length <= 8)
            {
                length = 8;
            }

            if (length > 31)
            {
                length = 32;
            }

            var randomArray = RandomNumberGenerator.GetBytes(length);
            StringBuilder stringBuilder = new StringBuilder();
            foreach (var item in randomArray)
            {
                stringBuilder.Append(item);
            }

            return stringBuilder.ToString().Substring(0, length);
        }

        /// <summary>
        /// C#反射遍历对象属性获取键值对
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="model">对象</param>
        public static Dictionary<string, object> GetClassProperties<T>(T model)
        {
            Type t = model.GetType();
            List<PropertyInfo> propertyList = new List<PropertyInfo>();

            PropertyInfo[] tempPropertyList = t.GetProperties();
            if (tempPropertyList != null && tempPropertyList.Length > 0)
            {
                propertyList.AddRange(tempPropertyList);
            }

            var parentPropertyInfo = t.BaseType?.GetProperties();
            if (parentPropertyInfo != null && parentPropertyInfo.Length > 0)
            {
                foreach (var item in parentPropertyInfo)
                {
                    if (!propertyList.Any(d => d.Name == item.Name)) //如果子类已经包含父类的属性或者字段，跳过不处理
                    {
                        propertyList.Add(item);
                    }
                }
            }

            Dictionary<string, object> resultData = new Dictionary<string, object>();

            foreach (PropertyInfo item in propertyList)
            {
                resultData.Add(item.Name, item.GetValue(model, null));
            }

            return resultData;
        }

        /// <summary>
        /// C#反射遍历对象属性，将键值对赋值给属性
        /// </summary> 
        public static object SetClassProperties(string typeModel, Dictionary<string, object> keyValues)
        {
            if (keyValues.Count <= 0)
            {
                return null;
            }

            Type tType = Type.GetType(typeModel);


            PropertyInfo[] PropertyList = tType.GetProperties();

            object objModel = tType.Assembly.CreateInstance(tType.FullName);
            foreach (PropertyInfo item in PropertyList)
            {
                if (keyValues.ContainsKey(item.Name))
                {
                    object objectValue = keyValues[item.Name];
                    item.SetValue(objModel, objectValue);
                }
            }

            return objModel;
        }

        /// <summary>
        /// 取得某月的第一天
        /// </summary>
        /// <param name="datetime">要取得月份第一天的时间</param>
        /// <returns></returns>
        public static DateTime FirstDayOfMonth(this DateTime datetime)
        {
            return datetime.AddDays(1 - datetime.Day);
        }

        ///<summary>
        /// 取得某月的最后一天
        /// </summary>
        /// <param name="datetime">要取得月份最后一天的时间</param>
        /// <returns></returns>
        public static DateTime LastDayOfMonth(this DateTime datetime)
        {
            return datetime.AddDays(1 - datetime.Day).AddMonths(1).AddDays(-1);
        }

        /// <summary>
        /// 取得某月第一天0点以及最后一天的23:59:59时间范围
        /// </summary>
        /// <param name="datetime"></param>
        /// <returns></returns>
        public static Tuple<DateTime, DateTime> GetMonthDateRange(this DateTime datetime)
        {
            var lastDayOfMonthDate = LastDayOfMonth(datetime);
            return new Tuple<DateTime, DateTime>(datetime.FirstDayOfMonth(), new DateTime(lastDayOfMonthDate.Year, lastDayOfMonthDate.Month, lastDayOfMonthDate.Day, 23, 59, 59));
        }

        /// <summary>
        /// 取得某一天0点到当月最后一天的23:59:59时间范围
        /// </summary>
        /// <param name="datetime"></param>
        /// <returns></returns>
        public static Tuple<DateTime, DateTime> GetCurrentDateToLastDayRange(this DateTime datetime)
        {
            var lastDayOfMonthDate = LastDayOfMonth(datetime);
            return new Tuple<DateTime, DateTime>(datetime.Date, new DateTime(lastDayOfMonthDate.Year, lastDayOfMonthDate.Month, lastDayOfMonthDate.Day, 23, 59, 59));
        }

        /// <summary>
        /// 取得某一天0点到23:59:59时间范围
        /// </summary>
        /// <param name="datetime"></param>
        /// <returns></returns>
        public static Tuple<DateTime, DateTime> GetCurrentDateRange(this DateTime datetime)
        {
            return new Tuple<DateTime, DateTime>(datetime.Date, new DateTime(datetime.Year, datetime.Month, datetime.Day, 23, 59, 59));
        }

        /// <summary>
        /// 获取指定枚举的所有 Attribute 说明以及value组成的键值对
        /// </summary>
        /// <param name="type">对象类</param>
        /// <param name="getPropertie">false获取字段、true获取属性</param>
        /// <returns></returns>
        public static List<SelectResult> GetEnumAttributeList(Type type, bool getPropertie = false)
        {
            if (type == null)
            {
                return null;
            }

            List<SelectResult> selectResults = new List<SelectResult>();
            List<MemberInfo> memberInfos = new List<MemberInfo>();

            if (getPropertie == false)
            {
                FieldInfo[] fieldArray = type.GetFields();
                if (null == fieldArray || fieldArray.Length <= 0)
                {
                    return null;
                }

                memberInfos.AddRange(fieldArray);
                //获取父类的字段
                var parentFieldInfo = type.BaseType?.GetFields();
                if (parentFieldInfo != null && parentFieldInfo.Length > 0)
                {
                    foreach (var item in parentFieldInfo)
                    {
                        if (!memberInfos.Any(d => d.Name == item.Name)) //如果子类已经包含父类的属性或者字段，跳过不处理
                        {
                            memberInfos.Add(item);
                        }
                    }
                }
            }
            else
            {
                PropertyInfo[] properties = type.GetProperties();
                if (null == properties || properties.Length <= 0)
                {
                    return null;
                }

                memberInfos.AddRange(properties);
                //获取父类的属性
                var parentPropertyInfo = type.BaseType?.GetProperties();
                if (parentPropertyInfo != null && parentPropertyInfo.Length > 0)
                {
                    foreach (var item in parentPropertyInfo)
                    {
                        if (!memberInfos.Any(d => d.Name == item.Name)) //如果子类已经包含父类的属性或者字段，跳过不处理
                        {
                            memberInfos.Add(item);
                        }
                    }
                }
            }

            foreach (var item in memberInfos)
            {
                DescriptionAttribute[] EnumAttributes =
                    (DescriptionAttribute[])item.GetCustomAttributes(typeof(DescriptionAttribute), false);

                dynamic infoObject = null;
                if (getPropertie == false)
                {
                    infoObject = (FieldInfo)item;
                }
                else
                {
                    infoObject = (PropertyInfo)item;
                }

                if (EnumAttributes.Length > 0)
                {
                    SelectResult selectResult = new SelectResult()
                    {
                        Key = Convert.ToInt32(infoObject.GetValue(null)).ToString(),
                        Value = EnumAttributes[0].Description,
                    };

                    selectResults.Add(selectResult);
                }

                DisplayAttribute[] DisplayAttributes =
                    (DisplayAttribute[])item.GetCustomAttributes(typeof(DisplayAttribute), false);
                if (DisplayAttributes.Length > 0)
                {
                    SelectResult selectResult =
                        selectResults.FirstOrDefault(e => e.Key == Convert.ToInt32(infoObject.GetValue(null)).ToString());
                    if (selectResult != null)
                    {
                        selectResult.SecondValue = DisplayAttributes[0].Name;
                    }
                }
            }

            return selectResults;
        }

        /// <summary>
        /// 获取指定枚举的所有 Attribute 说明以及value组成的键值对
        /// </summary>
        /// <param name="type">对象类</param>
        /// <param name="thirdAttributeType">第三个标签类型</param>
        /// <param name="thirdAttributePropertieName">第三个标签类型取值名称</param>
        /// <param name="getPropertie">false获取字段、true获取属性</param>
        /// <returns></returns>
        public static List<SelectResult> GetEnumAttributeListWithThirdValue(Type type, Type thirdAttributeType, string thirdAttributePropertieName, bool getPropertie = false)
        {
            if (type == null)
            {
                return null;
            }

            List<SelectResult> selectResults = new List<SelectResult>();
            List<MemberInfo> memberInfos = new List<MemberInfo>();

            if (getPropertie == false)
            {
                FieldInfo[] EnumInfo = type.GetFields();
                if (null == EnumInfo || EnumInfo.Length <= 0)
                {
                    return null;
                }
                memberInfos.AddRange(EnumInfo);
                var parentFieldInfo = type.BaseType?.GetFields();
                if (parentFieldInfo != null && parentFieldInfo.Length > 0)
                {
                    memberInfos.AddRange(parentFieldInfo);
                }
            }
            else
            {
                PropertyInfo[] EnumInfo = type.GetProperties();
                if (null == EnumInfo || EnumInfo.Length <= 0)
                {
                    return null;
                }
                memberInfos.AddRange(EnumInfo);
                var parentPropertyInfo = type.BaseType?.GetProperties();
                if (parentPropertyInfo != null && parentPropertyInfo.Length > 0)
                {
                    memberInfos.AddRange(parentPropertyInfo);
                }
            }

            foreach (var item in memberInfos)
            {
                var thirdAttributes = item.
               GetCustomAttributes(thirdAttributeType, false);
                if (thirdAttributes == null || thirdAttributes.Length <= 0)
                {
                    continue;
                }

                DescriptionAttribute[] descriptionAttributes = (DescriptionAttribute[])item.
                GetCustomAttributes(typeof(DescriptionAttribute), false);

                dynamic infoObject = null;
                if (getPropertie == false)
                {
                    infoObject = (FieldInfo)item;
                }
                else
                {
                    infoObject = (PropertyInfo)item;
                }

                if (descriptionAttributes.Length > 0)
                {
                    SelectResult selectResult = new SelectResult()
                    {
                        Key = infoObject.Name,
                        Value = descriptionAttributes[0].Description,
                    };

                    selectResults.Add(selectResult);
                }

                DisplayAttribute[] displayAttributes = (DisplayAttribute[])item.
                   GetCustomAttributes(typeof(DisplayAttribute), false);
                if (displayAttributes.Length > 0)
                {
                    SelectResult selectResult = selectResults.FirstOrDefault(e => e.Key == infoObject.Name);
                    if (selectResult != null)
                    {
                        selectResult.SecondValue = displayAttributes[0].Name;
                    }
                }

                if (thirdAttributes.Length > 0 && !string.IsNullOrWhiteSpace(thirdAttributePropertieName))
                {
                    foreach (var attr in thirdAttributes)
                    {
                        // 使用反射获取特性的属性值
                        var properties = thirdAttributeType.GetProperties();
                        foreach (var prop in properties)
                        {
                            // 假设你要获取特性的某个属性值，例如 TypeName
                            if (prop.Name == thirdAttributePropertieName)
                            {
                                object value = prop.GetValue(attr);
                                SelectResult selectResult = selectResults.FirstOrDefault(e => e.Key == infoObject.Name);
                                if (selectResult != null)
                                {
                                    selectResult.ThirdValue = value?.ToString(); // 将属性值赋给 ThirdValue
                                }
                                break; // 如果找到了需要的属性，可以跳出循环
                            }
                        }
                    }
                }
            }

            return selectResults;
        }

        /// <summary>
        /// 获取指定类、指定常量值的Description说明
        /// 包含直接继承的父级字段
        /// </summary>
        /// <param name="t">对象类</param> 
        /// <param name="getPropertie"></param> 
        /// <returns></returns>
        public static List<Tuple<string, string, int>> GetTypeDescriptionListToTuple(Type t, bool getPropertie = false)
        {
            if (t == null)
            {
                return null;
            }

            List<MemberInfo> memberInfos = new List<MemberInfo>();

            if (getPropertie == false)
            {
                FieldInfo[] fieldInfo = t.GetFields();
                if (null == fieldInfo || fieldInfo.Length <= 0)
                {
                    return null;
                }

                memberInfos.AddRange(fieldInfo);
                var parentFieldInfo = t.BaseType?.GetFields();
                if (parentFieldInfo != null && parentFieldInfo.Length > 0)
                {
                    foreach (var item in parentFieldInfo)
                    {
                        if (!memberInfos.Any(d => d.Name == item.Name)) //如果子类已经包含父类的属性或者字段，跳过不处理
                        {
                            memberInfos.Add(item);
                        }
                    }
                }
            }
            else
            {
                PropertyInfo[] fieldInfo = t.GetProperties();
                if (null == fieldInfo || fieldInfo.Length <= 0)
                {
                    return null;
                }

                memberInfos.AddRange(fieldInfo);
                var parentPropertyInfo = t.BaseType?.GetProperties();
                if (parentPropertyInfo != null && parentPropertyInfo.Length > 0)
                {
                    foreach (var item in parentPropertyInfo)
                    {
                        if (!memberInfos.Any(d => d.Name == item.Name)) //如果子类已经包含父类的属性或者字段，跳过不处理
                        {
                            memberInfos.Add(item);
                        }
                    }
                }
            }

            List<Tuple<string, string, int>> tuples = new List<Tuple<string, string, int>>();

            foreach (var item in memberInfos)
            {
                DescriptionAttribute[] descriptionAttribute =
                    (DescriptionAttribute[])item.GetCustomAttributes(typeof(DescriptionAttribute), false);

                NumericalOrderAttribute[] indexAttributes =
                    (NumericalOrderAttribute[])item.GetCustomAttributes(typeof(NumericalOrderAttribute), false);


                if (descriptionAttribute.Length > 0 && indexAttributes.Length > 0)
                {
                    Tuple<string, string, int> tuple = new Tuple<string, string, int>(item.Name,
                        descriptionAttribute[0].Description, indexAttributes[0].Index);
                    tuples.Add(tuple);
                }
            }

            return tuples;
        }

        /// <summary>
        /// 获取指定类、指定常量值的常量说明
        /// </summary>
        /// <param name="fieldName">常量字段名称</param>
        ///<param name="getPropertie">属性还是字段</param>        
        /// <returns></returns>
        public static string GetTypeDescriptionName<T>(string fieldName, bool getPropertie = false)
        {
            if (string.IsNullOrEmpty(fieldName))
            {
                return "";
            }

            MemberInfo memberInfo = null;
            if (getPropertie == false)
            {
                memberInfo = typeof(T).GetField(fieldName);
            }
            else
            {
                memberInfo = typeof(T).GetProperty(fieldName);
            }

            if (null == memberInfo)
            {
                return "";
            }

            DescriptionAttribute[] EnumAttributes =
                (DescriptionAttribute[])memberInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
            if (EnumAttributes.Length <= 0)
            {
                return "";
            }

            return EnumAttributes[0].Description;
        }

        /// <summary>
        /// 获取指定命名空间下指定常量值的常量说明
        /// </summary>
        /// <param name="fieldName">常量字段名称</param>
        /// <param name="assemblyName">命名空间，主要用来找到对应程序集</param>
        ///<param name="getPropertie">属性还是字段</param>        
        /// <returns></returns>
        public static string GetTypeDescriptionName(string fieldName, string assemblyName, bool getPropertie = false)
        {
            if (string.IsNullOrWhiteSpace(fieldName) || string.IsNullOrWhiteSpace(assemblyName))
            {
                return null;
            }

            string desc = "";
            foreach (var item in GetEnumList(assemblyName))
            {
                desc = GetTypeDescriptionName(item, fieldName, getPropertie);
                if (!string.IsNullOrEmpty(desc))
                {
                    break;
                }
            }

            return desc;
        }

        /// <summary>
        /// 获取指定类、指定常量值的常量说明
        /// </summary>
        /// <param name="t">对象类</param>
        /// <param name="fieldName">常量字段名称</param>
        ///<param name="getPropertie">属性还是字段</param>        
        /// <returns></returns>
        public static string GetTypeDescriptionName(this Type t, string fieldName, bool getPropertie = false)
        {
            if (string.IsNullOrWhiteSpace(fieldName))
            {
                return "";
            }

            MemberInfo memberInfo = null;
            if (getPropertie == false)
            {
                memberInfo = t.GetField(fieldName);
            }
            else
            {
                memberInfo = t.GetProperty(fieldName);
            }

            if (null != memberInfo)
            {
                DescriptionAttribute[] EnumAttributes =
                    (DescriptionAttribute[])memberInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
                if (EnumAttributes.Length > 0)
                {
                    return EnumAttributes[0].Description;
                }
            }

            return "";
        }

        /// <summary>        
        /// 扩展方法，获得枚举值集合
        ///</summary>        
        ///<returns>枚举的DisplayName</returns>        
        public static List<T> GetEnumList<T>() where T : Enum
        {
            List<T> enumList = new List<T>();
            foreach (T value in Enum.GetValues(typeof(T)))
            {
                enumList.Add(value);
            }

            return enumList;
        }

        private static List<Type> GetEnumList(string assemblyName)
        {
            if (!String.IsNullOrEmpty(assemblyName))
            {
                Assembly assembly = Assembly.Load(assemblyName);
                List<Type> ts = assembly.GetTypes().Where(x => x.GetTypeInfo().IsClass).ToList();
                return ts;
            }

            return new List<Type>();
        }

        /// <summary>        
        /// 扩展方法，获得枚举的Display值
        ///</summary>        
        ///<param name="value">枚举值</param>        
        ///<param name="nameInstead">当枚举值没有定义DisplayNameAttribute，是否使用枚举名代替，默认是使用</param>        
        ///<param name="getPropertie">属性还是字段</param>        
        ///<returns>枚举的DisplayName</returns>        
        public static string GetDisplayName(this Enum value, Boolean nameInstead = true, bool getPropertie = false)
        {
            Type type = value.GetType();
            string name = Enum.GetName(type, value);
            if (name == null)
            {
                return null;
            }

            DisplayAttribute attribute = null;

            if (getPropertie == false)
            {
                attribute = Attribute.GetCustomAttribute(type.GetField(name), typeof(DisplayAttribute)) as DisplayAttribute;
            }
            else
            {
                attribute =
                    Attribute.GetCustomAttribute(type.GetProperty(name), typeof(DisplayAttribute)) as DisplayAttribute;
            }


            if (attribute == null && nameInstead == true)
            {
                return name;
            }

            return attribute == null ? null : attribute.Name;
        }

        /// <summary>
        /// 获取枚举的描述信息
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string GetEnumDescription(this Enum value)
        {
            var name = value.ToString();
            var field = value.GetType().GetField(name);
            if (field == null) return name;

            var att = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute), false);

            return att == null ? field.Name : ((DescriptionAttribute)att).Description;
        }



        /// <summary>
        /// 将传入的字符串中间部分字符替换成特殊字符
        /// </summary>
        /// <param name="value">需要替换的字符串</param>
        /// <param name="startLen">前保留长度</param>
        /// <param name="endLen">尾保留长度</param>
        /// <param name="specialChar">特殊字符</param>
        /// <returns>被特殊字符替换的字符串</returns>
        public static string ReplaceWithSpecialChar(this string value, int startLen = 1, int endLen = 1,
            char specialChar = '*')
        {
            if (string.IsNullOrEmpty(value))
            {
                return value;
            }

            try
            {

                if (value.Length <= startLen + endLen)
                {
                    var temStartVal = value.Substring(0, startLen);
                    return $"{temStartVal}{"".PadLeft(endLen, specialChar)}";
                }

                if (value.Length == 10 && endLen == 1)
                {
                    endLen = 3;
                }

                var startVal = value.Substring(0, startLen);
                var endVal = value.Substring(value.Length - endLen);
                if (value.Length == 2)
                {
                    endVal = "";
                }

                value = $"{startVal}{endVal.PadLeft(value.Length - startLen, specialChar)}";
            }
            catch (Exception)
            {
                throw;
            }

            return value;
        }

        /// <summary>
        /// Linux下字体名称转换
        /// </summary>
        /// <param name="fontValue"></param>
        /// <returns></returns>
        public static string GetLinuxFontFamily(this string fontValue)
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                if (fontValue == "楷体")
                {
                    fontValue = "KaiTi";
                }
                else if (fontValue == "隶书")
                {
                    fontValue = "LiSu";
                }
                else if (fontValue == "宋体")
                {
                    fontValue = "SimSun";
                }
                else if (fontValue == "微软雅黑")
                {
                    fontValue = "Microsoft YaHei";
                }
                else if (fontValue == "新宋体")
                {
                    fontValue = "NSimSun";
                }
                else if (fontValue == "仿宋")
                {
                    fontValue = "FangSong";
                }
                else if (fontValue == "黑体")
                {
                    fontValue = "SimHei";
                }

            }

            return fontValue;
        }

        /// <summary>
        /// 获取任务标识
        /// </summary>
        /// <param name="afn"></param>
        /// <param name="fn"></param>
        /// <param name="pn"></param>
        /// <param name="msa"></param>
        /// <param name="seq"></param>
        /// <returns></returns>
        public static string GetTaskMark(int afn, int fn, int pn, int msa,int seq)
        {
            var makstr = $"{afn.ToString().PadLeft(2, '0')}{fn.ToString().PadLeft(2, '0')}{pn.ToString().PadLeft(2, '0')}{msa.ToString().PadLeft(2, '0')}{seq.ToString().PadLeft(2, '0')}";

            return makstr;// Convert.ToInt32(makstr) << 32 | msa;
        }

        /// <summary>
        /// 判断是生成月
        /// </summary>
        /// <param name="eachMonthWith"></param>
        /// <param name="curTime"></param>
        /// <returns></returns>
        public static bool JudgeIsGenerate_Month(string eachMonthWith, DateTime curTime)
        {
            var arr = eachMonthWith.Split(',');
            if (arr.Contains(curTime.Day.ToString()))
                return true;
            return false;
        }

        /// <summary>
        /// 判断是生成一次
        /// </summary>
        /// <param name="onceWithDate"></param>
        /// <param name="curTime"></param>
        /// <returns></returns>
        public static bool JudgeIsGenerate_Once(DateTime onceWithDate, DateTime curTime) => curTime.Date.Equals(onceWithDate);//为当天时发送

        /// <summary>
        /// 判断是生成日
        /// </summary>
        /// <param name="eachDayWithout"></param>
        /// <param name="curTime"></param>
        /// <returns></returns>
        public static bool JudgeIsGenerate_Day(string eachDayWithout, DateTime curTime)
        {
            var weekName = strWeeks[(int)curTime.DayOfWeek];
            var arr = eachDayWithout.Split(',');
            return !arr.Contains(weekName);
        }

        public static readonly List<string> strWeeks = new List<string>() { "周日", "周一", "周二", "周三", "周四", "周五", "周六" };

        /// <summary>
        /// 判断是生成周
        /// </summary>
        /// <param name="eachWeekWith"></param>
        /// <param name="curTime"></param>
        /// <returns></returns>
        public static bool JudgeIsGenerate_Week(string eachWeekWith, DateTime curTime)
        {
            if (string.IsNullOrWhiteSpace(eachWeekWith))
            {
                return false;
            }

            var weekName = strWeeks[(int)curTime.DayOfWeek];
            var arr = eachWeekWith.Split(',');
            return arr.Contains(weekName);

        }

   
    }
}
