using Microsoft.Data.SqlClient;
using System.Data;
using System.Data.Common;
using RB_MES_API.Context;

namespace RB_MES_API.Controllers
{
    /// <summary>
    /// SQL帮助类
    /// </summary>
    public class KDSqlHelper : IKDSqlHelper
    {
        private readonly RBContext _context;
        /// <summary>
        /// 依赖性注入
        /// </summary>
        /// <param name="context"></param>
        /// <param name="configuration"></param>
        public KDSqlHelper(RBContext context)
        {
            _context = context;
        }
        private string Myconnstr(bool KD)
        {
            return KD ? ConnectionString.GetConfig("ConnectionStrings", "ERP_Conn") : ConnectionString.GetConfig("ConnectionStrings", "RBConn");
        }
        /// <inheritdoc/>
        public async Task<string> ExecuteNonQueryAsync(string cmdText, CommandType cmdType, SqlParameter[]? sqlParams, bool KD = false)
        {
            string mess = null;
            if (cmdText.Trim() == null) return "-1";
            string connstr = Myconnstr(KD);
            using SqlConnection connection = new SqlConnection(connstr);
            try
            {
                connection.Open();
                using var cmd = connection.CreateCommand();
                //cmd.CommandTimeout = 0;
                PrepareCommand(cmd, cmdType, cmdText, sqlParams);
                cmd.Transaction = connection.BeginTransaction();
                try
                {
                    await cmd.ExecuteNonQueryAsync();
                    cmd.Transaction.Commit();
                    mess = "OK";
                }
                catch (Exception ex)
                {
                    cmd.Transaction.Rollback();
                    //将错误写到错误日志
                    mess = ex.Message;
                    LogHelper.WriteLog(string.Format("直接执行编译好的SQL语句的ExecuteNonQueryAsync方法发生错误在：{0}", mess + "\n" + cmdText));
                    //throw;
                }
                finally
                {
                    cmd.Dispose();
                }
            }
            catch (Exception ex)
            {
                //将错误写到错误日志，连不上数据库，只能写在磁盘文件中...
                mess = ex.Message;
                LogHelper.WriteLog(string.Format("直接执行编译好的SQL语句的ExecuteNonQueryAsync方法发生错误：{0}", mess));
            }
            finally
            {
                connection.Dispose();
            }
            return mess;
            //throw new NotImplementedException();
        }
        /// <inheritdoc/>

        public object? ExecuteScalar(CommandType cmdType, string cmdText, SqlParameter[]? sqlParams, ref string? mess, bool KD = false)
        {
            mess = null;
            object? result = null;
            if (string.IsNullOrEmpty(cmdText.Trim())) return null;
            string connstr = Myconnstr(KD);
            using SqlConnection connection = new SqlConnection(connstr);
            try
            {
                connection.Open();
                using var cmd = connection.CreateCommand();
                //cmd.CommandTimeout = 0;
                PrepareCommand(cmd, cmdType, cmdText, sqlParams);
                //cmd.Transaction = connection.BeginTransaction();
                try
                {
                    result = cmd.ExecuteScalar();
                    //cmd.Transaction.Commit();
                }
                catch (Exception ex)
                {
                    cmd.Transaction.Rollback();
                    //将错误写到错误日志
                    mess = ex.Message;
                    LogHelper.WriteLog(string.Format("并返回由查询返回的结果集中第一行的第一列的ExecuteScalar方法发生错误在：{0}", ex.Message + "\n" + cmdText));
                }
                finally
                {
                    cmd.Dispose();
                }
            }
            catch (Exception ex)
            {
                //将错误写到错误日志，连不上数据库，只能写在磁盘文件中...
                mess = ex.Message;
                LogHelper.WriteLog(string.Format("并返回由查询返回的结果集中第一行的第一列的ExecuteScalar方法发生错误：{0}", ex.Message));
            }
            finally
            {
                connection.Dispose();
            }
            //result = result is DBNull ? null : result;
            return result;
            //throw new NotImplementedException();
        }
        /// <inheritdoc/>

        public DataSet? GetDataSet(CommandType cmdType, string? cmdText, SqlParameter[]? sqlParams, ref string? mess, bool KD = false)
        {
            mess = null;
            if (cmdText == null || cmdText == "")
            {
                mess = "不执行空的查询脚本";
                return null;
            }
            var data = new DataSet();
            string connstr = Myconnstr(KD);
            using SqlConnection connection = new SqlConnection(connstr);
            try
            {
                connection.Open();
                using var cmd = connection.CreateCommand();
                //cmd.CommandTimeout = 0;
                PrepareCommand(cmd, cmdType, cmdText, sqlParams);
                cmd.Transaction = connection.BeginTransaction();
                SqlDataAdapter adapter = new(cmd);
                try
                {
                    adapter.Fill(data);
                    cmd.Transaction.Commit();
                }
                catch (Exception ex)
                {
                    cmd.Transaction.Rollback();
                    //将错误写到错误日志
                    mess = ex.Message;
                    LogHelper.WriteLog(string.Format("获取多个结果集的GetDataSet方法发生错误在：{0}", ex.Message + "\n" + cmdText));

                }
                finally
                {
                    adapter.Dispose();
                    cmd.Dispose();
                }
            }
            catch (Exception ex)
            {
                //将错误写到错误日志，连不上数据库，只能写在磁盘文件中...
                mess = ex.Message;
                LogHelper.WriteLog(string.Format("获取多个结果集的GetDataSet方法发生错误：{0}", ex.Message));
            }
            finally
            {
                connection.Dispose();
            }
            return data;
            //throw new NotImplementedException();
        }
        /// <inheritdoc/>

        public Dictionary<object, object> GetProcedurePairs(string cmdText, SqlParameter[] sqlParams, ref string? mess, bool KD = false)
        {
            mess = null;
            Dictionary<object, object> keyValues = new();
            //检查是否包含返回参数，如果没有就不用执行了
            if (sqlParams == null) return keyValues;
            string connstr = Myconnstr(KD);
            using SqlConnection connection = new SqlConnection(connstr);
            try
            {
                connection.Open();
                using var cmd = connection.CreateCommand();
                //cmd.CommandTimeout = 0;
                PrepareCommand(cmd, CommandType.StoredProcedure, cmdText, sqlParams);
                cmd.Transaction = connection.BeginTransaction();
                try
                {
                    cmd.ExecuteNonQuery();
                    cmd.Transaction.Commit();
                    foreach (DbParameter param in sqlParams)
                    {
                        if (param.Direction == ParameterDirection.Output || param.Direction == ParameterDirection.ReturnValue)
                        {
                            if (param.Value != null)
                            {
                                keyValues.Add(param.ParameterName, param.Value);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    cmd.Transaction.Rollback();
                    mess = ex.Message;
                    LogHelper.WriteLog(string.Format("执行存储过程，并获得返回值的GetProcedurePairs方法发生错误在：{0}", ex.Message + "\n" + cmdText));
                }
                finally
                {
                    cmd.Dispose();
                }
            }
            catch (Exception ex)
            {
                mess = ex.Message;
                LogHelper.WriteLog(string.Format("执行存储过程，并获得返回值的GetProcedurePairs方法发生错误：{0}", ex.Message));
            }
            finally
            {
                connection.Dispose();
            }
            return keyValues;
            //throw new NotImplementedException();
        }

        /// <summary>
        /// 为查询类赋值
        /// </summary>
        /// <param name="cmd"></param>
        /// <param name="cmdType"></param>
        /// <param name="cmdText"></param>
        /// <param name="cmdParms"></param>
        private static void PrepareCommand(IDbCommand cmd, CommandType cmdType, string cmdText, SqlParameter[]? cmdParms)
        {
            cmd.CommandText = cmdText;
            cmd.CommandType = cmdType;
            if (cmdParms != null)
            {
                foreach (DbParameter parm in cmdParms)
                    cmd.Parameters.Add(parm);
            }
        }
        /// <inheritdoc/>

        public bool InsertBill(DataTable idata, string TableName, ref string? reason, bool KD = false)
        {
            bool isok = false;
            reason = null;
            if (TableName == null || TableName == "")
            {
                reason += "未提供数据表的表名";
            }
            if (idata == null)
            {
                reason += "目标表不能为空";
            }
            if (idata!.Rows.Count == 0)
            {
                reason += "目标表中没有可导入数据";
            }
            if (!string.IsNullOrWhiteSpace(reason))
            {
                return isok;
            }
            string connstr = Myconnstr(KD);
            using SqlConnection connection = new SqlConnection(connstr);
            try
            {
                connection.Open();
                using (SqlBulkCopy sqlBulk = new(connection))
                {
                    sqlBulk.DestinationTableName = TableName;
                    foreach (DataColumn column in idata.Columns)
                    {
                        string NewEntryColunm = column.ColumnName;
                        sqlBulk.ColumnMappings.Add(NewEntryColunm, NewEntryColunm); //由于提前已经准备好单据了，这两个参数保持一致就行了
                    }
                    sqlBulk.BatchSize = idata.Rows.Count;
                    sqlBulk.WriteToServer(idata);
                    sqlBulk.Close();
                }
                isok = true;
            }
            catch (Exception ex)
            {
                reason = ex.Message;
                LogHelper.WriteLog(string.Format("将整理好的表单批量导入数据库的InsertBill方法在WriteToServer处发生错误：{0}", ex.Message));
            }
            finally
            {
                connection.Dispose();
            }
            return isok;
        }
    }
}
