using DeviceRepair.Models;
using DeviceRepair.Models.History;
using Newtonsoft.Json;
using NLog;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Reflection;
using DbType = SqlSugar.DbType;

namespace DeviceRepair.DataAccess.Data
{
    public class BaseDa
    {
        private static readonly Logger log = LogManager.GetCurrentClassLogger();


        #region 属性&字段

        private SqlSugarClient deviceDB;
        private SqlSugarClient deviceLogDB;
        private SqlSugarClient sfcDataDB;
        private SqlSugarClient sfcAddOnDB;
        private SqlSugarClient sfcSystemDB;

        internal OperationModel OperationInfo;

        private IDictionary<string, string> m_ApiParameters;

        /// <summary>
        /// API输入参数
        /// </summary>
        public IDictionary<string, string> ApiParameters
        {
            get { return m_ApiParameters; }
            private set { m_ApiParameters = value; }
        }

        /// <summary>
        /// 设备主表
        /// </summary>
        public SqlSugarClient devMain
        {
            get
            {
                if (deviceDB == null)
                {
                    SqlConnectionStringBuilder TsDevdb =
                        new SqlConnectionStringBuilder(DeviceRepair.Utils.Config.Configurations.Properties.Conn);
                    TsDevdb.InitialCatalog = "DriveMaintenance";

                    deviceDB = new SqlSugarClient(new ConnectionConfig()
                    {
                        ConnectionString = TsDevdb.ConnectionString,
                        DbType = DbType.SqlServer,
                        InitKeyType = InitKeyType.Attribute,
                        IsAutoCloseConnection = true,
                    });
                }

                return deviceDB;
            }
        }

        /// <summary>
        /// 设备日志
        /// </summary>
        public SqlSugarClient devLog
        {
            get
            {
                if (deviceLogDB == null)
                {
                    SqlConnectionStringBuilder TsDevdb =
                        new SqlConnectionStringBuilder(DeviceRepair.Utils.Config.Configurations.Properties.Conn);
                    TsDevdb.InitialCatalog = "DeviceMaintenanceLog";

                    deviceLogDB = new SqlSugarClient(new ConnectionConfig()
                    {
                        ConnectionString = TsDevdb.ConnectionString,
                        DbType = DbType.SqlServer,
                        InitKeyType = InitKeyType.Attribute,
                        IsAutoCloseConnection = true,
                    });
                }

                return deviceLogDB;
            }
        }

        /// <summary>
        /// SFC 数据表
        /// </summary>
        public SqlSugarClient sfcData
        {
            get
            {
                if (sfcDataDB == null)
                {
                    SqlConnectionStringBuilder TsSFCdb =
                        new SqlConnectionStringBuilder(DeviceRepair.Utils.Config.Configurations.Properties.SfcConn);
                    TsSFCdb.InitialCatalog = "SFCData";

                    sfcDataDB = new SqlSugarClient(new ConnectionConfig()
                    {
                        ConnectionString = TsSFCdb.ConnectionString,
                        DbType = DbType.SqlServer,
                        InitKeyType = InitKeyType.Attribute,
                        IsAutoCloseConnection = true,
                    });
                }

                return sfcDataDB;
            }
        }

        /// <summary>
        /// SFC AddOn 表
        /// </summary>
        public SqlSugarClient sfcAddOn
        {
            get
            {
                if (sfcAddOnDB == null)
                {
                    SqlConnectionStringBuilder TsSFCdb =
                        new SqlConnectionStringBuilder(DeviceRepair.Utils.Config.Configurations.Properties.SfcConn);
                    TsSFCdb.InitialCatalog = "SFCAddOn";

                    sfcAddOnDB = new SqlSugarClient(new ConnectionConfig()
                    {
                        ConnectionString = TsSFCdb.ConnectionString,
                        DbType = DbType.SqlServer,
                        InitKeyType = InitKeyType.Attribute,
                        IsAutoCloseConnection = true,
                    });
                }

                return sfcAddOnDB;
            }
        }

        public SqlSugarClient sfcSystem
        {
            get
            {
                if (sfcSystemDB == null)
                {
                    SqlConnectionStringBuilder TsSFCdb =
                        new SqlConnectionStringBuilder(DeviceRepair.Utils.Config.Configurations.Properties.SfcConn);
                    TsSFCdb.InitialCatalog = "SFCSystem";

                    sfcSystemDB = new SqlSugarClient(new ConnectionConfig()
                    {
                        ConnectionString = TsSFCdb.ConnectionString,
                        DbType = DbType.SqlServer,
                        InitKeyType = InitKeyType.Attribute,
                        IsAutoCloseConnection = true,
                    });
                }

                return sfcSystemDB;
            }
        }

        #endregion

        #region 函数

        public BaseDa()
        {
        }

        public BaseDa(IDictionary<string, string> apiParams)
        {
            m_ApiParameters = apiParams;
            OperationInfo = new OperationModel().InstanceModel(apiParams);
        }

        #endregion

        #region 方法

        /// <summary>
        /// 操作历史
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="his">操作历史对象</param>
        /// <param name="OperationType">操作描述</param>
        /// <param name="TableName">表名</param>
        /// <param name="CurrentDate">操作时间</param>
        public void OperationHistory<T>(T his, EnumOperationType OperationType, string TableName, DateTime? CurrentDate = null) where T : HistoryBase
        {
            try
            {
                if (!CurrentDate.HasValue)
                    CurrentDate = DateTime.Now;

                his.OperationComputer = OperationInfo.ComputerName;
                his.OperationIP = OperationInfo.IPAddress;
                his.Operator = OperationInfo.TsSFCUserId;
                his.OperationType = OperationType.ToDescription();
                his.OperationDate = CurrentDate.Value;

                var dic = ToDictionary(his);

                //var js = JsonConvert.SerializeObject(his);
                //Dictionary<string, object> dic = JsonConvert.DeserializeObject<Dictionary<string, object>>(js);
                devLog.Insertable(dic).AS(TableName).ExecuteCommandAsync();
            }
            catch (Exception ex)
            {
                log.Error(ex);
                throw ex;
            }
        }

        Dictionary<string, object> ToDictionary(object obj)
        {
            if (obj == null)
                throw new ArgumentNullException(nameof(obj));
            var props = obj.GetType()
                .GetProperties(BindingFlags.Public | BindingFlags.Instance);

            return props
                .ToDictionary(
                    prop => prop.Name,
                    prop => prop.GetValue(obj, null)
                );
        }


        /// <summary>
        /// 取字符串参数
        /// </summary>
        /// <param name="Key">键</param>
        /// <param name="Caption">字段标题</param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public string GetParamString(string Key, string Caption)
        {
            try
            {
                if (!ApiParameters.ContainsKey(Key))
                {
                    throw new ArgumentException($"参数【{Caption}】不能为空！");
                }

                return (ApiParameters[Key] + "").Trim();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 取整数型参数
        /// </summary>
        /// <param name="Key">键</param>
        /// <param name="Caption">字段标题</param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public int GetParamInt(string Key, string Caption)
        {
            try
            {
                if (!ApiParameters.ContainsKey(Key))
                {
                    throw new ArgumentException($"参数【{Caption}】不能为空！");
                }

                int value = 0;
                if (!int.TryParse(ApiParameters[Key], out value))
                {
                    throw new ArgumentException($"参数【{Caption}】传入值转整数型出错！");
                }

                return value;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 取时间类型参数
        /// </summary>
        /// <param name="Key">键</param>
        /// <param name="Caption">字段标题</param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public DateTime GetParamDateTime(string Key, string Caption)
        {
            try
            {
                if (!ApiParameters.ContainsKey(Key))
                {
                    throw new ArgumentException($"参数【{Caption}】不能为空！");
                }

                DateTime value;
                if (!DateTime.TryParse(ApiParameters[Key] + "", out value))
                {
                    throw new ArgumentException($"参数【{Caption}】传入值转时间类型出错！");
                }

                return value;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 通用唯一识别码类型参数
        /// </summary>
        /// <param name="Key">键</param>
        /// <param name="Caption">字段标题</param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public Guid GetParamGuid(string Key, string Caption)
        {
            try
            {
                if (!ApiParameters.ContainsKey(Key))
                {
                    throw new ArgumentException($"参数【{Caption}】不能为空！");
                }

                Guid value;
                if (!Guid.TryParse(ApiParameters[Key] + "", out value))
                {
                    throw new ArgumentException($"参数【{Caption}】传入值转通用唯一识别码类型出错！");
                }
                return value;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 集合 转 DataTable
        /// </summary>
        /// <param name="varlist"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public DataTable IListToDataTable<T>(IEnumerable<T> varlist)
        {
            DataTable dtReturn = new DataTable();
            PropertyInfo[] oProps = null;

            foreach (T rec in varlist)
            {
                if (oProps == null)
                {
                    oProps = ((Type)rec.GetType()).GetProperties();

                    foreach (PropertyInfo pi in oProps)
                    {
                        Type colType = pi.PropertyType;
                        if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
                        {
                            colType = colType.GetGenericArguments()[0];
                        }

                        dtReturn.Columns.Add(new DataColumn(pi.Name, colType));
                    }
                }

                DataRow dr = dtReturn.NewRow();
                foreach (PropertyInfo pi in oProps)
                {
                    dr[pi.Name] = pi.GetValue(rec, null) == null ? DBNull.Value : pi.GetValue(rec, null);
                }

                dtReturn.Rows.Add(dr);
            }

            return (dtReturn);
        }

        /// <summary>
        /// 集合 转 DataTable
        /// </summary>
        /// <param name="varlist"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public DataTable ListToDataTable<T>(List<T> varlist)
        {
            DataTable dtReturn = new DataTable();
            PropertyInfo[] oProps = typeof(T).GetProperties();
            dtReturn.TableName = typeof(T).Name;

            foreach (PropertyInfo pi in oProps)
            {
                Type colType = pi.PropertyType;
                if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
                {
                    colType = colType.GetGenericArguments()[0];
                }

                dtReturn.Columns.Add(new DataColumn(pi.Name, colType));
            }

            foreach (T rec in varlist)
            {
                DataRow dr = dtReturn.NewRow();
                foreach (PropertyInfo pi in oProps)
                {
                    dr[pi.Name] = pi.GetValue(rec, null) == null ? DBNull.Value : pi.GetValue(rec, null);
                }

                dtReturn.Rows.Add(dr);
            }

            return (dtReturn);
        }


        /// <summary>
        /// 对象转换为字典
        /// </summary>
        /// <param name="obj">待转化的对象</param>
        /// <returns></returns>
        public Dictionary<string, string> ObjectToMap(object obj)
        {
            Dictionary<string, string> map = new Dictionary<string, string>(); //

            Type t = obj.GetType(); // 获取对象对应的类， 对应的类型string

            PropertyInfo[] pi = t.GetProperties(BindingFlags.Public | BindingFlags.Instance); // 获取当前type公共属性io

            foreach (PropertyInfo p in pi)
            {
                MethodInfo m = p.GetGetMethod();
                if (m != null && m.IsPublic)
                {
                    // 进行判NULL处理
                    if (m.Invoke(obj, new object[] { }) != null)
                    {
                        map.Add(p.Name, m.Invoke(obj, new object[] { }).ToString()); // 向字典添加元素
                    }
                }
            }
            return map;
        }

        public bool CompareDictionaries(Dictionary<string, string> d1, Dictionary<string, string> d2)
        {
            //比较d2>=d1
            if (d1.Count != d2.Count) return false;
            foreach (string key in d1.Keys)
            {
                if (!d2.ContainsKey(key)) return false;
                if (d1[key]?.Trim() != d2[key].Trim()) return false;
            }
            return true;
        }

        #endregion
    }
}