using System.Data;
using System.Reflection;

namespace ThingsGateway.SqlSugar
{
    public partial class AdoAccessory
    {
        // 数据库类型绑定接口
        protected IDbBind _DbBind;
        // 数据库反向生成实体接口
        protected IDbFirst _DbFirst;
        // 数据库建库接口
        protected ICodeFirst _CodeFirst;
        // 数据库维护接口
        protected IDbMaintenance _DbMaintenance;
        // 数据库连接接口
        protected IDbConnection _DbConnection;

        /// <summary>
        /// 将对象类型的参数转换为 SugarParameter 数组
        /// </summary>
        /// <param name="parameters">参数对象，可以是匿名对象、字典、SugarParameter 数组或列表</param>
        /// <param name="propertyInfo">可选的属性信息数组，若为空则通过反射获取</param>
        /// <param name="sqlParameterKeyWord">SQL参数前缀，例如 "@"</param>
        /// <returns>SugarParameter 数组</returns>
        protected virtual IReadOnlyCollection<SugarParameter> GetParameters(object parameters, PropertyInfo[] propertyInfo, string sqlParameterKeyWord)
        {
            if (parameters != null)
            {
                var entityType = parameters.GetType();

                // 判断是否是字典类型，利用 UtilConstants.DicArraySO / DicArraySS 判断
                var isDictionary = entityType.IsIn(UtilConstants.DicArraySO, UtilConstants.DicArraySS);

                if (isDictionary)
                {
                    // 字典类型转参数
                    return DictionaryToParameters(parameters, sqlParameterKeyWord, entityType);
                }
                else if (parameters is IReadOnlyCollection<SugarParameter> sugarParamArray)
                {
                    // 如果是 SugarParameter 数组，转 List
                    return sugarParamArray;
                }
                else
                {
                    // 如果不是匿名对象，抛异常
                    if (!entityType.IsAnonymousType())
                        throw new SqlSugarException("参数格式错误。{\n}请使用 new{xx=xx, xx2=xx2} 或 \nDictionary<string, object> 或 \nSugarParameter [] ");

                    // 反射对象属性转参数
                    return PropertyToParameter(parameters, propertyInfo, sqlParameterKeyWord, entityType).ToArray();
                }
            }
            return new List<SugarParameter>();
        }

        /// <summary>
        /// 将对象的属性转换为参数集合
        /// </summary>
        protected IEnumerable<SugarParameter> PropertyToParameter(object parameters, PropertyInfo[] propertyInfo, string sqlParameterKeyWord, Type entityType)
        {
            var properties = propertyInfo ?? entityType.GetProperties();

            foreach (PropertyInfo propertyty in properties)
            {
                var value = propertyty.GetValue(parameters, null);

                // 如果是枚举类型，转成 long
                if (propertyty.PropertyType.IsEnum())
                    value = Convert.ToInt64(value);

                // DateTime.MinValue 处理为 DBNull
                if (value?.Equals(DateTime.MinValue) != false)
                    value = DBNull.Value;

                // 特殊处理 HIERARCHYID 类型
                if (propertyty.Name.Contains("hierarchyid", StringComparison.OrdinalIgnoreCase))
                {
                    var parameter = new SugarParameter(sqlParameterKeyWord + propertyty.Name, SqlDbType.Udt)
                    {
                        UdtTypeName = "HIERARCHYID",
                        Value = value
                    };
                    yield return parameter;
                }
                else
                {
                    // 常规参数
                    var parameter = new SugarParameter(sqlParameterKeyWord + propertyty.Name, value);
                    yield return parameter;
                }
            }
        }

        /// <summary>
        /// 将字典类型的参数转换为参数集合
        /// </summary>
        protected IReadOnlyCollection<SugarParameter> DictionaryToParameters(object parameters, string sqlParameterKeyWord, Type entityType)
        {
            if (entityType == UtilConstants.DicArraySO)
            {
                // Dictionary<string, object> 转参数
                var dictionaryParameters = (Dictionary<string, object>)parameters;
                var sugarParameters = dictionaryParameters.Select(it => new SugarParameter(sqlParameterKeyWord + it.Key, it.Value));
                return sugarParameters.ToArray();
            }
            else
            {
                // Dictionary<string, string> 转参数
                var dictionaryParameters = (Dictionary<string, string>)parameters;
                var sugarParameters = dictionaryParameters.Select(it => new SugarParameter(sqlParameterKeyWord + it.Key, it.Value));
                return sugarParameters.ToArray();
            }
        }
    }
}
