using Microsoft.EntityFrameworkCore;
using Ropin.Inspection.Model;
using Ropin.Inspection.Model.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace Ropin.Inspection.Repository
{
    // 仓储
    public class RepositoryBase<T, TId> : IRepositoryBase<T>, IRepositoryBaseById<T, TId> where T : class
    {
        private readonly DbSet<T> _dbSet;

        public InspectionDbContext DbContext { get; set; }

        public RepositoryBase(InspectionDbContext dbContext)
        {
            DbContext = dbContext;
            _dbSet = DbContext.Set<T>();
        }
        public void Create(T entity)
        {
            DbContext.Set<T>().Add(entity);
        }
        public async Task CreateOneAsync(T entity)
        {
            await DbContext.Set<T>().AddAsync(entity);
        }


        public void Delete(T entity)
        {
            DbContext.Set<T>().Remove(entity);
        }
        public async Task<int> RemoveAsync(T entity)
        {
            this._dbSet.Remove(entity);
            return await this.DbContext.SaveChangesAsync();
        }
        public async Task<int> RemoveRangeAsync(IEnumerable<T> entities)
        {
            this._dbSet.RemoveRange(entities);
            return await this.DbContext.SaveChangesAsync();
        }

        public IEnumerable<T> GetAll()
        {
            return DbContext.Set<T>().AsEnumerable();
        }

        public Task<IEnumerable<T>> GetAllAsync()
        {
            //??
            return Task.FromResult(DbContext.Set<T>().AsEnumerable());
        }

        public Task<IEnumerable<T>> GetByConditionAsync(Expression<Func<T, bool>> expression)
        {
            return Task.FromResult(DbContext.Set<T>().Where(expression).AsEnumerable());
        }

        public async Task<T> GetByIdAsync(TId id)
        {
            return await DbContext.Set<T>().FindAsync(id);
        }

        public async Task<bool> DeleteAsync(TId id)
        {
            var v = await GetByIdAsync(id);
            DbContext.Set<T>().Remove(v);
            return await SaveAsync();
        }

        public async Task<bool> IsExistAsync(TId id)
        {
            return await DbContext.Set<T>().FindAsync(id) != null;
        }

        public async Task<bool> SaveAsync()
        {
            return await DbContext.SaveChangesAsync() > 0;
        }

        public void Update(T entity)
        {
            DbContext.Set<T>().Update(entity);
        }

        //public async Task<bool> UpdateOneAsync(T entity)
        //{
        //    Update(entity);
        //    return await SaveAsync();
        //}

        //public async Task<bool> DeleteOneAsync(T entity)
        //{
        //    Update(entity);
        //    return await SaveAsync();
        //}
        public virtual async Task<int> CreateRangeAsync(IEnumerable<T> entities)
        {
            await DbContext.Set<T>().AddRangeAsync(entities);
            return await DbContext.SaveChangesAsync();
        }


        /// <summary>
        /// 分页查询异步
        /// </summary>
        /// <param name="whereLambda">查询添加(可有,可无)</param>
        /// <param name="ordering">排序条件(一定要有,多个用逗号隔开,倒序开头用-号)</param>
        /// <param name="pageIndex">当前页码</param>
        /// <param name="pageSize">每页大小</param>
        /// <returns></returns>
        public async Task<PageData<T>> GetPageAsync(Expression<Func<T, bool>> whereLambda, string ordering,bool IsPagination, int pageIndex, int pageSize, bool isNoTracking = true)
        {
            // 分页 一定注意: Skip 之前一定要 OrderBy
            if (string.IsNullOrEmpty(ordering))
            {
                ordering = nameof(T) + "D_CreateOn";//默认以创建时间排序
            }
            var data = _dbSet.OrderByBatch(ordering);
            if (whereLambda != null)
            {
                data = isNoTracking ? data.Where(whereLambda).AsNoTracking() : data.Where(whereLambda);
            }
            //查看生成的sql,找到大数据下分页巨慢原因为order by 耗时
            //var sql = data.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToSql();
            //File.WriteAllText(@"D:\sql.txt",sql);
            PageData<T> pageData = new PageData<T>
            {
                Totals = await data.CountAsync(),
                Rows = IsPagination?await data.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync(): await data.ToListAsync()

            };
            return pageData;
        }
    }
}