using NPOI.SS.Formula.Functions;
using OASystem.Domain.ViewModels.Financial;
using OASystem.Domain.ViewModels.Groups;
using System.Globalization;
using System.Reflection;
using System.Reflection.Metadata;

namespace OASystem.Infrastructure.Tools;

/// <summary>
/// 工具类
/// </summary>
public static class CommonFun
{
    public static string GUID => Guid.NewGuid().ToString("N");
    public static bool IsNull(this string s)
    {
        return string.IsNullOrWhiteSpace(s);
    }
    public static bool NotNull(this string s)
    {
        return !string.IsNullOrWhiteSpace(s);
    }
    public static int GetRandom(int minNum, int maxNum)
    {
        var seed = BitConverter.ToInt32(Guid.NewGuid().ToByteArray(), 0);
        return new Random(seed).Next(minNum, maxNum);
    }
    public static string GetSerialNumber(string prefix = "")
    {
        return prefix + DateTime.Now.ToString("yyyyMMddHHmmssfff") + GetRandom(1000, 9999).ToString();
    }
    public static string ToJson(this object obj)
    {
        return JsonSerializer.Serialize(obj);
    }
    public static T ToObject<T>(this string json)
    {
        return JsonSerializer.Deserialize<T>(json);
    }
    public static object GetDefaultVal(string typename)
    {
        return typename switch
        {
            "Boolean" => false,
            "DateTime" => default(DateTime),
            "Date" => default(DateTime),
            "Double" => 0.0,
            "Single" => 0f,
            "Int32" => 0,
            "String" => string.Empty,
            "Decimal" => 0m,
            _ => null,
        };
    }
    public static void CoverNull<T>(T model) where T : class
    {
        if (model == null)
        {
            return;
        }
        var typeFromHandle = typeof(T);
        var properties = typeFromHandle.GetProperties();
        var array = properties;
        for (var i = 0; i < array.Length; i++)
        {
            var propertyInfo = array[i];
            if (propertyInfo.GetValue(model, null) == null)
            {
                propertyInfo.SetValue(model, GetDefaultVal(propertyInfo.PropertyType.Name), null);
            }
        }
    }
    public static void CoverNull<T>(List<T> models) where T : class
    {
        if (models.Count == 0)
        {
            return;
        }
        foreach (var model in models)
        {
            CoverNull(model);
        }
    }
    public static bool ToBool(this object thisValue, bool errorvalue = false)
    {
        if (thisValue != null && thisValue != DBNull.Value && bool.TryParse(thisValue.ToString(), out bool reval))
        {
            return reval;
        }
        return errorvalue;
    }

    #region 文件操作
    public static FileInfo[] GetFiles(string directoryPath)
    {
        if (!IsExistDirectory(directoryPath))
        {
            throw new DirectoryNotFoundException();
        }
        var root = new DirectoryInfo(directoryPath);
        return root.GetFiles();
    }
    public static bool IsExistDirectory(string directoryPath)
    {
        return Directory.Exists(directoryPath);
    }
    public static string ReadFile(string Path)
    {
        string s;
        if (!File.Exists(Path))
            s = "不存在相应的目录";
        else
        {
            var f2 = new StreamReader(Path, Encoding.Default);
            s = f2.ReadToEnd();
            f2.Close();
            f2.Dispose();
        }
        return s;
    }
    public static void FileMove(string OrignFile, string NewFile)
    {
        File.Move(OrignFile, NewFile);
    }
    public static void CreateDir(string dir)
    {
        if (dir.Length == 0) return;
        if (!Directory.Exists(dir))
            Directory.CreateDirectory(dir);
    }
    #endregion

    #region IP
    /// <summary>
    /// 是否为ip
    /// </summary>
    /// <param name="ip"></param>
    /// <returns></returns>
    public static bool IsIP(string ip)
    {
        return Regex.IsMatch(ip, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$");
    }
    public static string GetIP(HttpRequest request)
    {
        if (request == null)
        {
            return "";
        }

        var ip = request.Headers["X-Real-IP"].FirstOrDefault();
        if (ip.IsNull())
        {
            ip = request.Headers["X-Forwarded-For"].FirstOrDefault();
        }
        if (ip.IsNull())
        {
            ip = request.HttpContext?.Connection?.RemoteIpAddress?.ToString();
        }
        if (ip.IsNull() || !IsIP(ip))
        {
            ip = "127.0.0.1";
        }

        return ip;
    }
    #endregion

    #region 随机数

    /// <summary>
    /// 根据自定义随机包含的字符获取指定长度的随机字符
    /// </summary>
    /// <param name="length">随机字符长度</param>
    /// <returns>随机字符</returns>
    public static string GetRandomStr(int length)
    {
        string a = "ABCDEFGHJKLMNPQRSTUVWXYZ012356789";
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++)
        {
            sb.Append(a[new Random(Guid.NewGuid().GetHashCode()).Next(0, a.Length - 1)]);
        }

        return sb.ToString();
    }

    /// <summary>
    /// 根据自定义随机包含的字符获取指定长度的随机字符
    /// </summary>
    /// <param name="length">随机字符长度</param>
    /// <returns>随机字符</returns>
    public static string GetRandomAllStr(int length)
    {
        string a = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjklmnpqrstuvwxyz012356789";
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++)
        {
            sb.Append(a[new Random(Guid.NewGuid().GetHashCode()).Next(0, a.Length - 1)]);
        }

        return sb.ToString();
    }


    /// <summary>
    /// 根据自定义随机包含的字符获取指定长度的随机字母(含大小写)
    /// </summary>
    /// <param name="length">随机字符长度</param>
    /// <returns>随机字符</returns>
    public static string GetRandomLetter(int length)
    {
        string a = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjklmnpqrstuvwxyz";
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++)
        {
            sb.Append(a[new Random(Guid.NewGuid().GetHashCode()).Next(0, a.Length - 1)]);
        }

        return sb.ToString();
    }

    /// <summary>
    /// 生成不重复随机数字
    /// 操作者:037
    /// 2021-07-26 15:39
    /// </summary>
    /// <param name="CodeCount">输入字符串长度</param>
    /// <returns>字符串</returns>
    public static string GetRandomNumber(int len)
    {
        string allChar = "0,1,2,3,4,5,6,7,8,9";
        string[] allCharArray = allChar.Split(',');
        string RandomCode = "";
        int temp = -1;
        Random rand = new Random();

        for (int i = 0; i < len; i++)
        {
            if (temp != -1)
            {
                rand = new Random(temp * i * ((int)DateTime.Now.Ticks));
            }
            int t = rand.Next(allCharArray.Length - 1);
            while (temp == t)

            {
                t = rand.Next(allCharArray.Length - 1);
            }
            temp = t;
            RandomCode += allCharArray[t];
        }
        return RandomCode;
    }

    #endregion

    #region decimal 截取
    /// <summary>
    /// 
    /// </summary>
    /// <param name="d"></param>
    /// <param name="n"></param>
    /// <returns></returns>
    public static decimal CutDecimalWithN(decimal d, int n)
    {
        string strDecimal = d.ToString();
        int index = strDecimal.IndexOf(".");
        if (index == -1 || strDecimal.Length < index + n + 1)
        {
            strDecimal = string.Format("{0:F" + n + "}", d);
        }
        else
        {
            int length = index;
            if (n != 0)
            {
                length = index + n + 1;
            }
            strDecimal = strDecimal.Substring(0, length);
        }
        return Decimal.Parse(strDecimal);
    }

    public static decimal CutDecimalWithN(decimal? d, int n)
    {
        if (d == null)
        {
            return Decimal.MinValue;
        }
        return CutDecimalWithN(Convert.ToDecimal(d), n);
    }

    #endregion

    #region decimal 保留两位小数

    /// <summary>
    /// decimal 保留两位小数 不四舍五入
    /// </summary>
    /// <param name="number"></param>
    /// <returns></returns>
    public static decimal DecimalsKeepTwo(this decimal myDecimal)
    {
        var subDecimal = Math.Floor(myDecimal * 100) / 100;//保留两位小数,直接截取
        return subDecimal;
    }

    #endregion

    #region 团组模块 - 汇率相关存储解析
    /// <summary>
    /// 团组模块 - 汇率相关 To List
    /// </summary>
    /// <param name="rateStr"></param>
    /// <returns></returns>
    public static List<CurrencyInfo> GetCurrencyChinaToList(string? rateStr)
    {
        List<CurrencyInfo> currencyInfos = new List<CurrencyInfo>();

        if (string.IsNullOrEmpty(rateStr)) return currencyInfos;

        if (rateStr.Contains("|"))
        {
            string[] currencyArr = rateStr.Split("|");
            foreach (string currency in currencyArr)
            {
                string[] currency1 = currency.Split(":");
                string[] currency2 = currency1[0].Split("(");

                CurrencyInfo rateInfo = new CurrencyInfo()
                {
                    CurrencyCode = currency2[1].Replace(")", "").TrimEnd(),
                    CurrencyName = currency2[0],
                    Rate = decimal.Parse(currency1[1]),
                };
                currencyInfos.Add(rateInfo);
            }
        }
        return currencyInfos;
    }

    /// <summary>
    /// 团组模块 - 汇率相关存储解析 To String
    /// </summary>
    /// <param name="rates"></param>
    /// <returns></returns>
    public static string  GetCurrencyChinaToString(List<CurrencyInfo> rates)
    {
        
        string rateStr = string.Empty;

        if (rates.Count <= 0) return rateStr;

        if (rates.Count == 1 )
        {
            var rate = rates[0];
            return string.Format("{0}({1}):{2}|", rate.CurrencyName, rate.CurrencyCode, rate.Rate);
        }

        foreach (CurrencyInfo rate in rates)
        {
            //存储方式: 美元(USD):6.2350|.......|墨西哥比索(MXN):1.0000
            rateStr += string.Format("{0}({1}):{2}|", rate.CurrencyName, rate.CurrencyCode, rate.Rate);
        }

        if (rateStr.Length > 0)
        {
            rateStr = rateStr.Substring(0, rateStr.Length - 1);
        }

        return rateStr;
    }
    #endregion

    #region 验证身份证号码
    /// <summary>
    /// 正则表达式
    /// 验证身份证号码
    /// </summary>
    /// <param name="idNumber"></param>
    /// <returns></returns>
    public static bool IsValidChineseId(this string idNumber)
    {
        string pattern = @"^[1-9]\d{5}(18|19|20|21|22)?\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}(\d|[Xx])$";
        Regex regex = new Regex(pattern);
        return regex.IsMatch(idNumber);
    }

    /// <summary>
    /// 通过身份证提取生日
    /// </summary>
    /// <param name="identityCard"></param>
    /// <returns></returns>
    public static DateTime? GetBirthDateFromIdentityCard(string identityCard)
    {
        // 身份证号码正则表达式验证,支持18位身份证号码
        if (!Regex.IsMatch(identityCard, @"^\d{17}(\d|X|x)$"))
        {
            return null;
        }

        // 获取出生日期(8位数字)
        string birthDateString = identityCard.Substring(6, 8);

        // 尝试将出生日期字符串转换为DateTime类型
        if (DateTime.TryParse(birthDateString, out DateTime birthDate))
        {
            return birthDate;
        }

        return null;
    }

    /// <summary>
    /// 通过身份证判断性别
    /// </summary>
    /// <param name="idNumber"></param>
    /// <returns>0 男1 女 -1 未设置</returns>
    /// <exception cref="ArgumentException"></exception>
    public static int GetGenderFromIdentityCard(string idNumber)
    {
        if (string.IsNullOrEmpty(idNumber) || idNumber.Length != 18)
            return -1;

        char genderChar = idNumber[16];
        return int.Parse(genderChar.ToString()) % 2 == 0 ? 1 :0;
    }


    #endregion

    #region string格式日期格式化

    /// <summary>
    /// string格式日期格式化
    /// </summary>
    /// <param name="dateStr"></param>
    /// <param name="format">
    /// 格式化标准
    /// yyyy-MM-dd  yyyy/MM/dd
    /// </param>
    /// <returns></returns>
    public static string DateFormat(this string dateStr, string format)
    {
        if (!string.IsNullOrEmpty(dateStr))
        {
            if (!string.IsNullOrEmpty(format))
            {
                DateTime result;
                if (DateTime.TryParse(dateStr, out result))
                {
                    return result.ToString(format);
                }
            }
        }

        return "";
    }

    #endregion

    /// <summary>
    /// List to DataTable
    /// 集合转换成datatable
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="aIList"></param>
    /// <returns></returns>
    public static DataTable GetDataTableFromIList<T>(List<T> aIList)
    {

        DataTable _returnTable = new DataTable();

        if (aIList != null && aIList.Count > 0)
        {

            object _baseObj = aIList[0];

            Type objectType = _baseObj.GetType();

            PropertyInfo[] properties = objectType.GetProperties();

            DataColumn _col;

            foreach (PropertyInfo property in properties)
            {

                _col = new DataColumn();

                _col.ColumnName = (string)property.Name;

                _col.DataType = property.PropertyType;

                _returnTable.Columns.Add(_col);

            }

            //Adds the rows to the table

            DataRow _row;

            foreach (object objItem in aIList)
            {

                _row = _returnTable.NewRow();

                foreach (PropertyInfo property in properties)
                {

                    _row[property.Name] = property.GetValue(objItem, null);

                }

                _returnTable.Rows.Add(_row);

            }

        }

        return _returnTable;

    }


}