using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace ORM
{
    public partial class SqlSugarRepository<TEntity> : SimpleClient<TEntity> where TEntity : class, new()
    {
        /// <summary>
        /// 实体集合
        /// </summary>
        public ISugarQueryable<TEntity> Entities => Context.Queryable<TEntity>();

        /// <summary>
        /// 构造函数
        /// </summary>
        public SqlSugarRepository(ISqlSugarClient context = null) : base(context)
        {
            // 绑定数据库操作对象
            Context = SqlSugarContext.DbContext;
            // 备忘：GetConnectionScopeWithAttr会导致不能触发Aop.OnLogExecuting、Aop.OnLogExecuted等事件
            // 详见：https://www.donet5.com/Home/Doc?typeId=2405（之2.1、方法说明）
            // 详见：https://www.donet5.com/Home/Doc?typeId=2246（之2.2、根据特性获取）和（之4、多租户设置AOP）
            // base.Context = SqlSugarContext.DbContext.GetConnectionScopeWithAttr<TEntity>(); 
            // 根据特性获取，适合一个实体和库是一对一的情况
        }


        #region 查询
        /// <summary>
        /// 检查是否存在
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public bool IsExists(Expression<Func<TEntity, bool>> whereExpression)
        {
            return Entities.Any(whereExpression);
        }

        /// <summary>
        /// 检查是否存在
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public async Task<bool> IsExistsAsync(Expression<Func<TEntity, bool>> whereExpression)
        {
            return await Entities.AnyAsync(whereExpression);
        }

        /// <summary>
        /// 通过主键获取实体
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public TEntity Single(dynamic Id)
        {
            return Entities.InSingle(Id);
        }

        /// <summary>
        /// 获取一个实体
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public TEntity Single(Expression<Func<TEntity, bool>> whereExpression)
        {
            return Entities.Single(whereExpression);
        }

        /// <summary>
        /// 获取一个实体
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public Task<TEntity> SingleAsync(Expression<Func<TEntity, bool>> whereExpression)
        {
            return Entities.SingleAsync(whereExpression);
        }

        /// <summary>
        /// 获取一个实体
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public TEntity FirstOrDefault(Expression<Func<TEntity, bool>> whereExpression)
        {
            return Entities.First(whereExpression);
        }

        /// <summary>
        /// 获取一个实体
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public async Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> whereExpression)
        {
            return await Entities.FirstAsync(whereExpression);
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <returns></returns>
        public List<TEntity> ToList()
        {
            return Entities.ToList();
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <returns></returns>
        public Task<List<TEntity>> ToListAsync()
        {
            return Entities.ToListAsync();
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public List<TEntity> ToList(Expression<Func<TEntity, bool>> whereExpression)
        {
            return Entities.Where(whereExpression).ToList();
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public Task<List<TEntity>> ToListAsync(Expression<Func<TEntity, bool>> whereExpression)
        {
            return Entities.Where(whereExpression).ToListAsync();
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <param name="orderByExpression"></param>
        /// <param name="orderByType"></param>
        /// <returns></returns>
        public List<TEntity> ToList(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
        {
            return Entities.OrderByIF(orderByExpression != null, orderByExpression, orderByType).Where(whereExpression).ToList();
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <param name="orderByExpression"></param>
        /// <param name="orderByType"></param>
        /// <returns></returns>
        public Task<List<TEntity>> ToListAsync(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
        {
            return Entities.OrderByIF(orderByExpression != null, orderByExpression, orderByType).Where(whereExpression).ToListAsync();
        }
        #endregion 查询


        #region 新增
        /// <summary>
        /// 新增多条记录
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public int Insert(TEntity[] entities)
        {
            return Context.Insertable(entities).ExecuteCommand();
        }

        /// <summary>
        /// 新增多条记录
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public Task<int> InsertAsync(TEntity[] entities)
        {
            return Context.Insertable(entities).ExecuteCommandAsync();
        }

        /// <summary>
        /// 新增多条记录
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public int Insert(IEnumerable<TEntity> entities)
        {
            return Context.Insertable(entities.ToArray()).ExecuteCommand();
        }

        /// <summary>
        /// 新增多条记录
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public Task<int> InsertAsync(IEnumerable<TEntity> entities)
        {
            if (entities != null && entities.Any())
            {
                return Context.Insertable(entities.ToArray()).ExecuteCommandAsync();
            }
            return Task.FromResult(0);
        }
        #endregion 新增


        #region 更新
        /// <summary>
        /// 更新单条记录指定列
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="updateColumn"></param>
        /// <returns></returns>
        public int Update(TEntity entity, object updateColumn)
        {
            return Context.Updateable(entity).UpdateColumns(MergeUpdateColumns(updateColumn)).ExecuteCommand();
        }

        /// <summary>
        ///  更新单条记录指定列
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="updateColumn"></param>
        /// <returns></returns>
        public Task<int> UpdateAsync(TEntity entity, object updateColumn)
        {
            return Context.Updateable(entity).UpdateColumns(MergeUpdateColumns(updateColumn)).ExecuteCommandAsync();
        }

        /// <summary>
        /// 更新单条记录指定列
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="updateColumn"></param>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public int Update(TEntity entity, object updateColumn, Expression<Func<TEntity, bool>> whereExpression)
        {
            return Context.Updateable(entity).UpdateColumns(MergeUpdateColumns(updateColumn)).Where(whereExpression).ExecuteCommand();
        }

        /// <summary>
        /// 更新单条记录指定列
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="updateColumn"></param>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public Task<int> UpdateAsync(TEntity entity, object updateColumn, Expression<Func<TEntity, bool>> whereExpression)
        {
            return Context.Updateable(entity).UpdateColumns(MergeUpdateColumns(updateColumn)).Where(whereExpression).ExecuteCommandAsync();
        }

        /// <summary>
        /// 更新多条记录
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public int Update(TEntity[] entities)
        {
            return Context.Updateable(entities).ExecuteCommand();
        }

        /// <summary>
        /// 更新多条记录
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public Task<int> UpdateAsync(TEntity[] entities)
        {
            return Context.Updateable(entities).ExecuteCommandAsync();
        }

        /// <summary>
        /// 更新多条记录指定列
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="updateColumn"></param>
        /// <returns></returns>
        public int Update(TEntity[] entities, object updateColumn)
        {
            return Context.Updateable(entities).UpdateColumns(MergeUpdateColumns(updateColumn)).ExecuteCommand();
        }

        /// <summary>
        /// 更新多条记录指定列
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="updateColumn"></param>
        /// <returns></returns>
        public Task<int> UpdateAsync(TEntity[] entities, object updateColumn)
        {
            return Context.Updateable(entities).UpdateColumns(MergeUpdateColumns(updateColumn)).ExecuteCommandAsync();
        }

        /// <summary>
        /// 合并指定更新列和附加更新列
        /// </summary>
        /// <param name="updateColumn"></param>
        /// <returns></returns>
        private string[] MergeUpdateColumns(object updateColumn)
        {
            List<string> columnList = new List<string>();
            if (updateColumn.GetType() == typeof(string))
            {
                columnList.Add((string)updateColumn);
            }
            else if (updateColumn.GetType() == typeof(string[]))
            {
                columnList.AddRange((string[])updateColumn);
            }
            return columnList.ToArray();
        }
        #endregion 更新


        #region 删除
        /// <summary>
        /// 删除一条记录
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public int Delete(object key)
        {
            return Context.Deleteable<TEntity>().In(key).ExecuteCommand();
        }

        /// <summary>
        /// 删除一条记录
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public Task<int> DeleteAsync(object key)
        {
            return Context.Deleteable<TEntity>().In(key).ExecuteCommandAsync();
        }

        /// <summary>
        /// 删除多条记录
        /// </summary>
        /// <param name="keys"></param>
        /// <returns></returns>
        public int Delete(object[] keys)
        {
            return Context.Deleteable<TEntity>().In(keys).ExecuteCommand();
        }

        /// <summary>
        /// 删除多条记录
        /// </summary>
        /// <param name="keys"></param>
        /// <returns></returns>
        public Task<int> DeleteAsync(object[] keys)
        {
            return Context.Deleteable<TEntity>().In(keys).ExecuteCommandAsync();
        }
        #endregion 删除


        #region 事务
        /// <summary>
        /// 开启事务
        /// </summary>
        public void BeginTran()
        {
            Context.Ado.BeginTran();
        }

        /// <summary>
        /// 提交事务
        /// </summary>
        public void CommitTran()
        {
            Context.Ado.CommitTran();
        }

        /// <summary>
        /// 回滚事务
        /// </summary>
        public void RollbackTran()
        {
            Context.Ado.RollbackTran();
        }
        #endregion 事务

    }
}
