using DapperExtensions.Lambda;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.Json;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Configuration;
using System.Data;

namespace Mall.DataAccess.Utils
{
    /// <summary>
    /// 数据库工具类
    /// </summary>
    public class DBUtils
    {
        private static ConcurrentDictionary<DataBaseType, IDBHelper> _iDBHelpers = new ConcurrentDictionary<DataBaseType, IDBHelper>();

        /// <summary>
        /// 创建数据库连接
        /// </summary>
        /// <param name="strKey">连接字符串</param>
        /// <param name="dbType">数据库类型</param>
        /// <returns></returns>
        public static IDbConnection CreateDBConnection(string strKey, out DataBaseType dbType)
        {
            dbType = DataBaseType.SqlServer;
            IDbConnection connection = null;

            var configuration = new ConfigurationBuilder()
            .Add(new JsonConfigurationSource { Path = "appsettings.json" })
            .Build();
            string strConn = configuration.GetConnectionString(strKey);
            string providerName = configuration.GetConnectionString(strKey+ "PName");
            //ConnectionStringSettings connectionStringSettings = ConfigurationManager.ConnectionStrings[strKey];
            //string strConn = connectionStringSettings.ConnectionString;
            //string providerName = connectionStringSettings.ProviderName;

            if (string.IsNullOrEmpty(providerName))
            {
                throw new Exception(strKey + "连接字符串未定义 ProviderName");
            }
            else if (providerName == "System.Data.SqlClient")
            {
                dbType = DataBaseType.SqlServer;
                connection = new System.Data.SqlClient.SqlConnection(strConn);
            }
            //else if (providerName == "Oracle.DataAccess.Client" )
            //{
            //    dbType = dbType.Oracle;
            //    connection = new Oracle.DataAccess.Client.OracleConnection(strConn);
            //}
            //else if (providerName == "System.Data.OracleClient")
            //{
            //    dbType = dbType.Oracle;
            //    connection = new System.Data.OracleClient.OracleConnection(strConn);
            //}
            else if (providerName == "MySql.Data.MySqlClient")
            {
                dbType = DataBaseType.MySql;
                connection = new MySql.Data.MySqlClient.MySqlConnection(strConn);
            }
            else if (providerName == "System.Data.OleDb")
            {
                dbType = DataBaseType.Aceess;
                connection = new System.Data.OleDb.OleDbConnection(strConn);
            }
            else
            {
                throw new Exception(strKey + "连接字符串未识别 ProviderName");
            }
            return connection;
        }

        /// <summary>
        /// 创建数据库连接
        /// </summary>
        /// <param name="dbType">数据库类型</param>
        /// <param name="strKey">连接字符串</param>
        /// <returns></returns>
        public static IDbConnection CreateDBConnection(DataBaseType dbType, string strKey)
        {
            IDbConnection connection = null;
            ConnectionStringSettings connectionStringSettings = ConfigurationManager.ConnectionStrings[strKey];
            string strConn = connectionStringSettings.ConnectionString;

            switch (dbType)
            {
                case DataBaseType.SqlServer:
                    connection = new System.Data.SqlClient.SqlConnection(strConn);
                    break;
                case DataBaseType.MySql:
                    connection = new MySql.Data.MySqlClient.MySqlConnection(strConn);
                    break;
                //case dbType.Oracle:
                //connection = new Oracle.DataAccess.Client.OracleConnection(strConn);
                //connection = new System.Data.OracleClient.OracleConnection(strConn);
                //break;
                case DataBaseType.Aceess:
                    connection = new System.Data.OleDb.OleDbConnection(strConn);
                    break;
            }
            return connection;
        }

        /// <summary>
        /// 获取数据库类型
        /// </summary>
        /// <param name="providerKey">提供程序Key</param>
        /// <returns></returns>
        public static DataBaseType GetDBTypeByConnKey(string providerKey)
        {
            DataBaseType dbType = DataBaseType.MySql;
            ConnectionStringSettings connectionStringSettings = ConfigurationManager.ConnectionStrings[providerKey];
            string strConn = connectionStringSettings.ConnectionString;
            string providerName = connectionStringSettings.ProviderName;
            if (string.IsNullOrEmpty(providerName))
            {
                throw new Exception(providerKey + "连接字符串未定义 ProviderName");
            }
            else if (providerName == "System.Data.SqlClient")
            {
                dbType = DataBaseType.SqlServer;
            }
            //else if (providerName == "Oracle.DataAccess.Client" )
            //{
            //    dbType = dbType.Oracle;
            //    connection = new Oracle.DataAccess.Client.OracleConnection(strConn);
            //}
            //else if (providerName == "System.Data.OracleClient")
            //{
            //    dbType = dbType.Oracle;
            //    connection = new System.Data.OracleClient.OracleConnection(strConn);
            //}
            else if (providerName == "MySql.Data.MySqlClient")
            {
                dbType = DataBaseType.MySql;
            }
            else if (providerName == "System.Data.OleDb")
            {
                dbType = DataBaseType.Aceess;
            }
            else
            {
                throw new Exception(providerKey + "连接字符串未识别 ProviderName");
            }
            return dbType;
        }

        /// <summary>
        /// 参数转换
        /// </summary>
        /// <param name="parmList">参数字典</param>
        /// <param name="dbType">数据库类型枚举</param>
        /// <returns></returns>
        public static List<IDataParameter> ConvertToDbParameter(Dictionary<string, Parameter> parmList, DataBaseType dbType)
        {
            List<IDataParameter> dbParamList = new List<IDataParameter>();
            foreach (var item in parmList)
            {
                dbParamList.Add(ConvertToIDataParameter(item.Value.ParameterName, item.Value.ParameterValue, dbType));
            }
            return dbParamList;
        }


        /// <summary>
        /// 参数转换
        /// </summary>
        /// <param name="parameterName">参数名称</param>
        /// <param name="value">参数值</param>
        /// <param name="dbType">数据库类型枚举</param>
        /// <returns></returns>
        public static IDataParameter ConvertToIDataParameter(string parameterName, object value, DataBaseType dbType)
        {
            switch (dbType)
            {
                case DataBaseType.SqlServer:
                    return new System.Data.SqlClient.SqlParameter(parameterName, value);
                case DataBaseType.MySql:
                    return new MySql.Data.MySqlClient.MySqlParameter(parameterName, value);
                case DataBaseType.Oracle:
                    return new System.Data.OleDb.OleDbParameter(parameterName, value);
                default:
                    return new System.Data.SqlClient.SqlParameter(parameterName, value);
            }
        }

        /// <summary>
        /// 创建数据库连接
        /// </summary>
        /// <param name="dbConnection">数据库连接对象</param>
        /// <param name="transaction">事务对象</param>
        /// <returns></returns>
        public static DbConnObj GetConnObj(IDbConnection dbConnection, IDbTransaction transaction = null)
        {
            DbConnObj dbConnObj = new DbConnObj();
            if (null != transaction)
            {
                dbConnObj.DbConnection = transaction.Connection;
                dbConnObj.DbTransaction = transaction;
            }
            else if (null != dbConnection)
            {
                dbConnObj.DbConnection = dbConnection;
            }
            return dbConnObj;
        }

        /// <summary>
        /// 获取数据库对象
        /// </summary>
        /// <param name="dbType">数据库类型枚举</param>
        /// <returns></returns>
        public static IDBHelper GetDBHelper(DataBaseType dbType)
        {
            IDBHelper dbHelper;
            if (!_iDBHelpers.TryGetValue(dbType, out dbHelper))
            {
                switch (dbType)
                {
                    case DataBaseType.SqlServer:
                        dbHelper = new Mall.DataAccess.SqlDBHelper.DBAdaptor();
                        break;
                    case DataBaseType.MySql:
                        dbHelper = new Mall.DataAccess.MySqlDBHelper.MySqlAdaptor();
                        break;
                    //case DataBaseType.Oracle:
                    //dbHelper = new Mall.DataAccess.OracleDBHelper.OracleAdaptor();
                    //break;
                    default:
                        dbHelper = new Mall.DataAccess.SqlDBHelper.DBAdaptor();
                        break;
                }
                _iDBHelpers[dbType] = dbHelper;
            }
            return dbHelper;
        }
    }

    /// <summary>
    /// 数据库连接对象类
    /// </summary>
    public class DbConnObj
    {
        /// <summary>
        /// 数据库事物对象
        /// </summary>
        public IDbTransaction DbTransaction { get; set; }

        /// <summary>
        /// 数据库连接对象
        /// </summary>
        public IDbConnection DbConnection { get; set; }

        /// <summary>
        /// 数据库类型
        /// </summary>
        public DataBaseType DbType { get; set; }
    }
}