using IRaCIS.Application.Interfaces;
using IRaCIS.Application.Contracts;
using IRaCIS.Core.Domain.Share;
using System.Linq.Expressions;
using System.Linq.Dynamic.Core;

using Microsoft.AspNetCore.Mvc;

namespace IRaCIS.Application.Services
{ /// <summary>
  /// Dashboard统计、全局工作量统计、入组两个维度统计（按照项目、按照人）
  /// </summary>

    [ApiExplorerSettings(GroupName = "Dashboard&Statistics")]
    public class StatisticsService : BaseService, IStatisticsService
    {
        private readonly IRepository<Doctor> _doctorRepository;
        private readonly IRepository<Trial> _trialRepository;
        private readonly IRepository<Enroll> _enrollRepository;
        private readonly IRepository<Workload> _workloadRepository;
        private readonly IRepository<CRO> _croCompanyRepository;
        private readonly IRepository<Dictionary> _dictionaryRepository;
        private readonly IRepository<Hospital> _hospitalRepository;
        private readonly IRepository<EnrollDetail> _enrollDetailRepository;
        private readonly IRepository<User> _userRepository;
        private readonly IRepository<TrialUser> _userTrialRepository;


        public StatisticsService(IRepository<Doctor> doctorRepository, IRepository<Trial> trialRepository,
             IRepository<Enroll> intoGroupRepository, IRepository<Workload> workloadRepository,
             IRepository<CRO> croCompanyRepository,
            IRepository<Dictionary> dictionaryRepository,
            IRepository<Hospital> hospitalRepository,
            IRepository<EnrollDetail> enrollDetailRepository, IRepository<User> userRepository,
            IRepository<TrialUser> userTrialRepository)
        {
            _doctorRepository = doctorRepository;
            _trialRepository = trialRepository;
            _enrollRepository = intoGroupRepository;
            _workloadRepository = workloadRepository;
            _croCompanyRepository = croCompanyRepository;
            _dictionaryRepository = dictionaryRepository;
            _hospitalRepository = hospitalRepository;
            _enrollDetailRepository = enrollDetailRepository;
            _userRepository = userRepository;
            _userTrialRepository = userTrialRepository;

        }

        /// <summary> 根据项目和医生，分页获取工作量统计[New] </summary>
        [HttpPost]
        public async Task<PageOutput<WorkloadByTrialAndReviewerDTO>> GetWorkloadByTrialAndReviewer(
            StatisticsWorkloadQueryParam param)
        {



            var bDate = new DateTime(param.BeginDate.Year, param.BeginDate.Month, param.BeginDate.Day);
            var eDate = new DateTime(param.EndDate.Year, param.EndDate.Month, param.EndDate.Day);
            eDate = eDate.AddDays(1);
            Expression<Func<Workload, bool>> workloadLambda = x => x.DataFrom == (int)WorkLoadFromStatus.FinalConfirm;
            workloadLambda = workloadLambda.And(x => x.WorkTime >= bDate && x.WorkTime < eDate);

            Expression<Func<Trial, bool>> trialLambda = x => true;
            if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.SuperAdmin) //超级管理员按照条件查询所有
            {
                if (param.CroId != null)
                {
                    trialLambda = trialLambda.And(u => u.CROId == param.CroId);
                }
            }

            else  //不管是精鼎的pm还是我们的pm  还是运维人员 只能看到自己参与项目的统计
            {
                List<Guid> trialIdList = _userTrialRepository.Where(u => u.UserId == _userInfo.Id).Select(u => u.TrialId).ToList();
                trialLambda = trialLambda.And(u => trialIdList.Contains(u.Id));
            }
            if (!string.IsNullOrWhiteSpace(param.TrialCode))
            {
                trialLambda = trialLambda.And(u => u.TrialCode.Contains(param.TrialCode));
            }

            Expression<Func<Doctor, bool>> doctorLambda = x => true;
            if (!string.IsNullOrWhiteSpace(param.Reviewer))
            {

                var reviewer = param.Reviewer.Trim();
                doctorLambda = doctorLambda.And(u => u.ChineseName.Contains(reviewer)
                                                     || u.FirstName.Contains(reviewer)
                                                     || u.LastName.Contains(reviewer)
                                                     || u.ReviewerCode.Contains(reviewer)
                );

            }
            if (Guid.Empty != param.HospitalId && param.HospitalId != null)
            {
                doctorLambda = doctorLambda.And(u => u.HospitalId == param.HospitalId);
            }

            var workloadQuery = from workLoad in _workloadRepository.Where(workloadLambda)
                                join trial in _trialRepository.Where(trialLambda) on workLoad.TrialId equals trial.Id
                                join doctor in _doctorRepository.Where(doctorLambda) on workLoad.DoctorId equals doctor.Id
                                group workLoad by new { workLoad.DoctorId, workLoad.TrialId } into gWorkLoad

                                select new
                                {
                                    DoctorId = gWorkLoad.Key.DoctorId,
                                    TrialId = gWorkLoad.Key.TrialId,
                                    Downtime = gWorkLoad.Sum(t => t.Downtime),
                                    Training = gWorkLoad.Sum(t => t.Training),
                                    Timepoint = gWorkLoad.Sum(t => t.Timepoint),
                                    TimepointIn24H = gWorkLoad.Sum(t => t.TimepointIn24H),
                                    TimepointIn48H = gWorkLoad.Sum(t => t.TimepointIn48H),
                                    Global = gWorkLoad.Sum(t => t.Global),
                                    Adjudication = gWorkLoad.Sum(t => t.Adjudication),
                                    AdjudicationIn24H = gWorkLoad.Sum(t => t.AdjudicationIn24H),
                                    AdjudicationIn48H = gWorkLoad.Sum(t => t.AdjudicationIn48H),
                                    RefresherTraining = gWorkLoad.Sum(t => t.RefresherTraining),

                                };
            var query = from w in workloadQuery
                        join trial in _trialRepository.Where(trialLambda) on w.TrialId equals trial.Id into t
                        from trialItem in t.DefaultIfEmpty()
                        join doctor in _doctorRepository.Where(doctorLambda) on w.DoctorId equals doctor.Id into tt
                        from doctorItem in tt.DefaultIfEmpty()
                        join cro in _croCompanyRepository.AsQueryable() on trialItem.CROId equals cro.Id into ttt
                        from croItem in ttt.DefaultIfEmpty()
                        select new WorkloadByTrialAndReviewerDTO
                        {
                            Id = Guid.NewGuid(),
                            TrialId = trialItem.Id,
                            Indication = trialItem.Indication,
                            TrialCode = trialItem.TrialCode,
                            CroId = trialItem.CROId,
                            Cro = croItem.CROName,
                            ReviewerCode = doctorItem.ReviewerCode,
                            ChineseName = doctorItem.ChineseName,
                            FirstName = doctorItem.FirstName,
                            LastName = doctorItem.LastName,
                            FullName = doctorItem.FullName,
                            Training = w.Training,
                            Timepoint = w.Timepoint,
                            TimepointIn24H = w.TimepointIn24H,
                            TimepointIn48H = w.TimepointIn48H,
                            Adjudication = w.Adjudication,
                            AdjudicationIn24H = w.AdjudicationIn24H,
                            AdjudicationIn48H = w.AdjudicationIn48H,
                            Global = w.Global,
                            Downtime = w.Downtime,
                            RefresherTraining = w.RefresherTraining,

                            PersonalTotal = w.Timepoint + w.TimepointIn24H + w.TimepointIn48H + w.Adjudication + w.AdjudicationIn24H +
                            w.AdjudicationIn48H + w.Global
                        };


            return await query.ToPagedListAsync(param.PageIndex, param.PageSize, string.IsNullOrWhiteSpace(param.SortField) ? "ReviewerCode" : param.SortField, param.Asc);

            //var propName = param.SortField == "" ? "ReviewerCode" : param.SortField;
            //query = param.Asc
            //  ? query.OrderBy(propName).ThenBy(t => t.TrialCode).ThenBy(u => u.ReviewerCode)
            //  : query.OrderByDescending(propName).ThenBy(t => t.TrialCode).ThenBy(u => u.ReviewerCode);


            //if (propName == "FirstName" || propName == "LastName")
            //{
            //    query = param.Asc
            //  ? query.OrderBy(t => t.LastName).ThenBy(t => t.FirstName)
            //  : query.OrderByDescending(t => t.LastName).ThenBy(t => t.FirstName);
            //}
            //var count = query.Count();

            //query = query
            //    .Skip((param.PageIndex - 1) * param.PageSize)
            //    .Take(param.PageSize);
            //var doctorViewList = query.ToList();

            //return new PageOutput<WorkloadByTrialAndReviewerDTO>(param.PageIndex, param.PageSize, count, doctorViewList);
        }



        /// <summary> 项目入组 医生维度统计[New] </summary>
        [HttpPost]
        public async Task<PageOutput<EnrollStatByReviewerDTO>> GetEnrollStatByReviewer(EnrollStatByReviewerQueryDTO param)
        {
            var bDate = new DateTime(param.BeginDate.Year, param.BeginDate.Month, 1);
            var eDate = new DateTime(param.EndDate.Year, param.EndDate.Month, 1);
            eDate = eDate.AddMonths(1);

            Expression<Func<Enroll, bool>> enrollLambda = x => true;
            enrollLambda = enrollLambda.And(x => x.EnrollTime >= bDate && x.EnrollTime < eDate);

            Expression<Func<Hospital, bool>> hospitalLambda = x => true;
            if (Guid.Empty != param.HospitalId && param.HospitalId != null)
            {
                hospitalLambda = hospitalLambda.And(u => u.Id == param.HospitalId);
            }

            Expression<Func<Doctor, bool>> doctorLambda = x => true;
            if (!string.IsNullOrWhiteSpace(param.Reviewer))
            {

                var reviewer = param.Reviewer.Trim();
                doctorLambda = doctorLambda.And(u => u.ChineseName.Contains(reviewer)
                                                     || u.FirstName.Contains(reviewer)
                                                     || u.LastName.Contains(reviewer)
                                                     || u.ReviewerCode.Contains(reviewer)
                );
            }

            var enrollQueryable =
                from enroll in _enrollRepository.Where(enrollLambda)
                group enroll by new { enroll.DoctorId }
                into g
                select new
                {
                    DoctorId = g.Key.DoctorId,
                    Submitted = g.Sum(t =>
                        t.EnrollStatus == EnrollStatus.HasCommittedToCRO ? 1 : 0),
                    Approved = g.Sum(t =>
                        t.EnrollStatus == EnrollStatus.InviteIntoGroup ? 1 : 0),
                    Reading = g.Sum(t =>
                        t.EnrollStatus == EnrollStatus.DoctorReading ? 1 : 0),
                    Finished = g.Sum(t =>
                        t.EnrollStatus >= EnrollStatus.Finished ? 1 : 0),
                };


            var query = from w in enrollQueryable

                        join doctor in _doctorRepository.Where(doctorLambda) on w.DoctorId equals doctor.Id
                        join hospital in _hospitalRepository.Where(hospitalLambda) on doctor.HospitalId equals hospital.Id
                        select new EnrollStatByReviewerDTO
                        {
                            Id = Guid.NewGuid(),
                            Hospital = hospital.HospitalName,
                            ReviewerCode = doctor.ReviewerCode,
                            ChineseName = doctor.ChineseName,
                            FirstName = doctor.FirstName,
                            LastName = doctor.LastName,
                            FullName = doctor.FullName,
                            Pending = w.Submitted,
                            Approved = w.Approved,
                            Reading = w.Reading,
                            Finished = w.Finished,

                            Total = w.Submitted + w.Approved + w.Reading + w.Finished
                        };


            var pageData = await query.ToPagedListAsync(param.PageIndex, param.PageIndex, param.SortField == "" ? "ReviewerCode" : param.SortField, param.Asc);

            if (param.SortField == "EntryRate")
            {
                pageData.CurrentPageData.OrderBy(t => t.EntryRate);
            }

            return pageData;

            //var count = query.Count();
            //query = query
            //    .Skip((param.PageIndex - 1) * param.PageSize)
            //    .Take(param.PageSize);
            //var list = query.ToList();

            //if (param.SortField == "EntryRate")
            //{
            //    list = param.Asc
            //        ? list.OrderBy(t => t.EntryRate).ToList()
            //        : list.OrderByDescending(t => t.EntryRate).ToList();
            //}

            //return new PageOutput<EnrollStatByReviewerDTO>(param.PageIndex, param.PageSize, count, list);
        }

        [HttpPost]
        public PageOutput<EnrollStatByTrialDTO> GetEnrollStatByTrial(EnrollStatByTrialQueryDTO param)
        {

            #region 筛选条件 

            Expression<Func<Trial, bool>> trialLambda = x => true;

            if (param.Expedited != null)
            {
                trialLambda = trialLambda.And(o => o.Expedited == param.Expedited);
            }

            if (!string.IsNullOrEmpty(param.TrialCode))
            {
                var code = param.TrialCode.Trim();
                trialLambda = trialLambda.And(o => o.TrialCode.Contains(code));
            }

            if (!string.IsNullOrWhiteSpace(param.Indication))
            {
                var indication = param.Indication.Trim();
                trialLambda = trialLambda.And(o => o.Indication.Contains(indication));
            }

            if (param.CROId != null)
            {
                trialLambda = trialLambda.And(o => o.CROId == param.CROId);
            }


            if (param.BeginDate != null && param.EndDate != null)
            {
                var bDate = new DateTime(param.BeginDate.Value.Year, param.BeginDate.Value.Month, param.BeginDate.Value.Day);
                var eDate = new DateTime(param.EndDate.Value.Year, param.EndDate.Value.Month, param.BeginDate.Value.Day);
                eDate = eDate.AddMonths(1);

                trialLambda = trialLambda.And(o => o.CreateTime >= bDate && o.CreateTime < eDate);

            }

            #endregion

            var trialEnrollStatQuery = _enrollRepository.AsQueryable()
                .Where(t => t.EnrollStatus >= EnrollStatus.ConfirmIntoGroup).GroupBy(t => t.TrialId).Select(g => new
                {
                    TrialId = g.Key,
                    EnrollCount = g.Count()
                });

            var trialQuery = from trial in _trialRepository.Where(trialLambda)
                             join cro in _croCompanyRepository.AsQueryable() on trial.CROId equals cro.Id into t
                             from cro in t.DefaultIfEmpty()

                             join trialEnroll in trialEnrollStatQuery on trial.Id equals trialEnroll.TrialId
                             select new EnrollStatByTrialDTO
                             {
                                 TrialId = trial.Id,
                                 Cro = cro != null ? cro.CROName : "",
                                 Expedited = trial.Expedited,
                                 Indication = trial.Indication,
                                 TrialCode = trial.TrialCode,
                                 EnrollCount = trialEnroll.EnrollCount,
                                 CreateTime = trial.CreateTime
                             };

            var propName = param.SortField == "" ? "TrialCode" : param.SortField;
            trialQuery = param.Asc
                ? trialQuery.OrderBy(propName)
                : trialQuery.OrderBy(propName + " desc");

            var count = trialQuery.Count();

            trialQuery = trialQuery
                .Skip((param.PageIndex - 1) * param.PageSize)
                .Take(param.PageSize);

            var trialList = trialQuery.ToList();

            var trialIds = trialList.Select(t => t.TrialId).ToList();

            var enrollReviewerQuery = from enroll in _enrollRepository.AsQueryable()
                    .Where(t => t.EnrollStatus >= EnrollStatus.ConfirmIntoGroup && trialIds.Contains(t.TrialId))
                                      join reviewer in _doctorRepository.AsQueryable() on enroll.DoctorId equals reviewer.Id

                                      select new
                                      {
                                          TrialId = enroll.TrialId,
                                          NameCN = reviewer.ChineseName,
                                          Name = reviewer.LastName + " / " + reviewer.FirstName
                                      };
            var enrollReviewerByTrialList = enrollReviewerQuery.ToList().GroupBy(t => t.TrialId).Select(g => new
            {
                TrialId = g.Key,
                ReviewerNameCNList = g.Select(t => t.NameCN).ToList(),
                ReviewerNameList = g.Select(t => t.Name).ToList()
            }).ToList();


            trialList.ForEach(t =>
            {
                var trialDoctors = enrollReviewerByTrialList.FirstOrDefault(u => u.TrialId == t.TrialId);

                if (trialDoctors != null)
                {
                    t.ReviewerNameCNList = trialDoctors.ReviewerNameCNList;
                    t.ReviewerNameList = trialDoctors.ReviewerNameList;
                }
            });


            return new PageOutput<EnrollStatByTrialDTO>(param.PageIndex, param.PageSize, count, trialList);

        }

        /// <summary> 用户参与项目 统计[New] </summary>
        [HttpPost]
        public PageOutput<UserParticipateTrialStat> GetParticipateTrialStat(ParticipateQueryDto param)
        {

            Expression<Func<User, bool>> userLambda = x => true;
            Expression<Func<TrialUser, bool>> userTrialLambda = x => true;
            if (!string.IsNullOrEmpty(param.UserInfo))
            {
                var userInfo = param.UserInfo.Trim();
                userLambda = userLambda.And(o => o.UserCode.Contains(userInfo) || (o.LastName + ' ' + o.FirstName).Contains(userInfo) || o.UserName.Contains(userInfo));
            }

            if (!string.IsNullOrWhiteSpace(param.OrganizationName))
            {
                var organizationName = param.OrganizationName.Trim();
                userLambda = userLambda.And(o => o.OrganizationName.Contains(organizationName));
            }

            var userTypeEnumStr = _userInfo.UserTypeEnumStr;
            var userId = _userInfo.Id;


            //PM  进来只能看到他负责的项目下的参与人员列表
            if (userTypeEnumStr == UserTypeEnum.ProjectManager.ToString())
            {
                //参与到的项目
                var trialFilter = _userTrialRepository.Where(t => t.UserId == userId)
                        .Select(u => u.TrialId);
                userTrialLambda = userTrialLambda.And(t => trialFilter.Contains(t.TrialId));
            }
            //.Select(u => new { u.TrialId, u.UserId }).Distinct()
            var trialStatQuery = _userTrialRepository.Where(userTrialLambda)
                .GroupBy(t => t.UserId).Select(
                    g => new
                    {
                        UserId = g.Key,
                        TrialCount = g.Count()
                    });

            var userQuery = from trialStat in trialStatQuery
                            join user in _userRepository.Where(userLambda) on trialStat.UserId equals user.Id
                            select new UserParticipateTrialStat
                            {
                                Email = user.EMail,
                                Name = user.LastName + ' ' + user.FirstName,
                                UserName = user.UserName,
                                OrganizationName = user.OrganizationName,
                                Phone = user.Phone,
                                TrialCount = trialStat.TrialCount,
                                UserCode = user.UserCode,
                                UserId = user.Id
                            };

            var propName = param.SortField == "" ? "OrganizationName" : param.SortField;
            userQuery = param.Asc
                ? userQuery.OrderBy(propName)
                : userQuery.OrderBy(propName + " desc");

            var count = userQuery.Count();

            userQuery = userQuery
                .Skip((param.PageIndex - 1) * param.PageSize)
                .Take(param.PageSize);
            var list = userQuery.ToList();

            return new PageOutput<UserParticipateTrialStat>(param.PageIndex, param.PageSize, count, list);
        }
        /// <summary> 用户参与项目 列表[New] </summary>
        [HttpGet("{userId:guid}")]
        public List<UserParticipateTrialDetail> GetParticipateTrialList(Guid userId)
        {

            Expression<Func<TrialUser, bool>> userTrialLambda = x => x.UserId == userId;

            var userTypeEnum = _userInfo.UserTypeEnumStr;
            var loginUserId = _userInfo.Id;


            //PM  进来只能看到他负责的项目下的参与人员列表
            if (userTypeEnum == UserTypeEnum.ProjectManager.ToString())
            {
                //参与到的项目
                var trialFilter = _userTrialRepository.Where(t => t.UserId == loginUserId)
                       .Select(u => u.TrialId);
                userTrialLambda = userTrialLambda.And(t => trialFilter.Contains(t.TrialId));
            }

            var query = from userTrial in _userTrialRepository.Where(userTrialLambda)
                        join trial in _trialRepository.AsQueryable() on userTrial.TrialId equals trial.Id
                        join cro in _croCompanyRepository.AsQueryable() on trial.CROId equals cro.Id into cc
                        from cro in cc.DefaultIfEmpty()
                        select new UserParticipateTrialDetail()
                        {
                            Code = trial.TrialCode,
                            CROName = cro.CROName,
                            Expedited = trial.Expedited,
                            Indication = trial.Indication,
                            UserType = userTrial.User.UserTypeRole.UserTypeShortName,
                            TrialId = trial.Id

                        };

            return query.ToList();
        }


        #region Dashboard 数据统计
        /// <summary> 读片数分类统计[New] </summary>
        public ReadingDataDTO GetReadingDataByType()
        {
            int tp = 0; int ad = 0; int g = 0;
            var finalConfirmWorkload = _workloadRepository.Where(u => u.DataFrom == (int)WorkLoadFromStatus.FinalConfirm).ToList();
            foreach (var item in finalConfirmWorkload)
            {
                tp += (item.Timepoint + item.TimepointIn24H + item.TimepointIn48H);
                ad += (item.Adjudication + item.AdjudicationIn24H + item.AdjudicationIn48H);
                g += item.Global;
            }
            return new ReadingDataDTO
            {
                Timepoint = tp,
                Adjudication = ad,
                Global = g
            };
        }
        /// <summary> 获取最近几个月份的数据[New] </summary>
        [HttpGet, Route("{monthCount:int}")]
        public List<ReadingDataMonthDTO> GetReadingDataByMonth(int monthCount)
        {
            DateTime now = DateTime.Now.AddMonths(-1);
            DateTime eTime = new DateTime(now.Year, now.Month, 20);

            DateTime now6 = now.AddMonths(-1 * (monthCount - 1));
            DateTime bTime = new DateTime(now.AddMonths(-(monthCount - 1)).Year,
                now.AddMonths(-(monthCount - 1)).Month, 1, 0, 0, 0, 0);

            var query = from workload in _workloadRepository
                .Where(u => u.DataFrom == (int)WorkLoadFromStatus.FinalConfirm &&
                u.WorkTime >= bTime && u.WorkTime < eTime)
                        group workload by workload.YearMonth
                                    into gWorkLoad
                        select new ReadingDataMonthDTO
                        {
                            Month = gWorkLoad.Key,
                            Timepoint = gWorkLoad.Sum(t => t.Timepoint) + gWorkLoad.Sum(t => t.TimepointIn24H)
                            + gWorkLoad.Sum(t => t.TimepointIn48H),
                            Adjudication = gWorkLoad.Sum(t => t.Adjudication) + gWorkLoad.Sum(t => t.AdjudicationIn24H)
                            + gWorkLoad.Sum(t => t.AdjudicationIn48H),
                            Global = gWorkLoad.Sum(t => t.Global)
                        };
            var workloadList = query.OrderByDescending(u => u.Month).ToList();
            List<ReadingDataMonthDTO> result = new List<ReadingDataMonthDTO>();

            for (int i = 0; i < monthCount; i++)
            {
                var tempTime = now.AddMonths(-1 * i);
                var existedItem = workloadList.Find(u => u.Month ==
                (tempTime.Year + "-" + tempTime.Month.ToString().PadLeft(2, '0')));
                if (existedItem != null)
                {
                    result.Add(new ReadingDataMonthDTO
                    {
                        Month = existedItem.Month,
                        Timepoint = existedItem.Timepoint,
                        Adjudication = existedItem.Adjudication,
                        Global = existedItem.Global
                    });
                }
                else
                {
                    result.Add(new ReadingDataMonthDTO
                    {
                        Month = tempTime.Year + "-" + tempTime.Month.ToString().PadLeft(2, '0'),
                        Timepoint = 0,
                        Adjudication = 0,
                        Global = 0
                    });
                }
            }
            return result;
        }
        /// <summary> 读片数量排行前几的数据[New] </summary>
        [HttpGet("{topCount:int}")]
        public List<ReadingDataRankDTO> GetReadingDataRank(int topCount)
        {
            var query = from workload in _workloadRepository
                .Where(u => u.DataFrom == (int)WorkLoadFromStatus.FinalConfirm)
                        group workload by workload.DoctorId
                                    into gWorkLoad

                        select new ReadingDataRankDTO
                        {
                            TotalReadingCount = gWorkLoad.Sum(t => t.Timepoint) + gWorkLoad.Sum(t => t.TimepointIn24H)
                            + gWorkLoad.Sum(t => t.TimepointIn48H) + gWorkLoad.Sum(t => t.Adjudication) + gWorkLoad.Sum(t => t.AdjudicationIn24H)
                            + gWorkLoad.Sum(t => t.AdjudicationIn48H) + gWorkLoad.Sum(t => t.Global),
                            ReviewerId = gWorkLoad.Key,
                            Timepoint = gWorkLoad.Sum(t => t.Timepoint) + gWorkLoad.Sum(t => t.TimepointIn24H)
                            + gWorkLoad.Sum(t => t.TimepointIn48H),
                            Adjudication = gWorkLoad.Sum(t => t.Adjudication) + gWorkLoad.Sum(t => t.AdjudicationIn24H)
                            + gWorkLoad.Sum(t => t.AdjudicationIn48H),
                            Global = gWorkLoad.Sum(t => t.Global)
                        };
            var workloadList = query.OrderByDescending(u => u.TotalReadingCount).Take(topCount).ToList();
            var reviewerList = from w in workloadList
                               join doctor in _doctorRepository.Where() on w.ReviewerId equals doctor.Id into tt
                               from doctorItem in tt.DefaultIfEmpty()
                               select new ReadingDataRankDTO
                               {
                                   TotalReadingCount = w.TotalReadingCount,
                                   ReviewerId = w.ReviewerId,
                                   Timepoint = w.Timepoint,
                                   Adjudication = w.Adjudication,
                                   Global = w.Global,
                                   ReviewerCode = doctorItem.ReviewerCode,
                                   FirstName = doctorItem.FirstName,
                                   LastName = doctorItem.LastName,
                                   ChineseName = doctorItem.ChineseName
                               };
            return reviewerList.ToList();
        }

        /// <summary> 按Rank统计Reviewer 数量[New] </summary>
        public List<RankReviewersDTO> GetReviewersByRank()
        {
            var query = from q in (from reviewer in _doctorRepository.AsQueryable()
                                       //.Find(u => u.ReviewStatus == 1 && u.CooperateStatus == 1)
                                   group reviewer by reviewer.RankId
                                   into gReviewer
                                   select new
                                   {
                                       RankId = gReviewer.Key,
                                       ReviewerCount = gReviewer.Count()
                                   })

                        join dic in _dictionaryRepository.Where() on q.RankId equals dic.Id into tt
                        from dicItem in tt.DefaultIfEmpty()
                        select new RankReviewersDTO
                        {
                            RankId = q.RankId,
                            ReviewerCount = q.ReviewerCount,
                            RankName = dicItem == null ? "Other" : dicItem.Value
                        };

            var rankList = query.ToList();
            var staffList = rankList.Where(u => u.RankName == "Staff" || u.RankName == "Other");
            int staffCount = 0;
            foreach (var item in staffList)
            {
                staffCount += item.ReviewerCount;
            }
            rankList.RemoveAll(u => u.RankName == "Staff" || u.RankName == "Other");

            rankList.Add(new RankReviewersDTO { RankId = Guid.NewGuid(), RankName = "Staff", ReviewerCount = staffCount });

            return rankList;
        }
        ///<summary> 最近几个季度入组人次[New]  type==0  按照月份 </summary>
        [HttpGet("{type:int}/{count:int}")]
        public List<EnrollQuartDataDTO> GetEnrollDataByQuarter(int type, int count)
        {
            //等于0按照月份  否则按照季度
            if (type != 0)
            {
                var quarterCount = count;
                var year = DateTime.Now.AddMonths(-(quarterCount - 1) * 3 - DateTime.Now.Month % 3 + 1).Year;
                var month = DateTime.Now.AddMonths(-(quarterCount - 1) * 3 - DateTime.Now.Month % 3 + 1).Month;

                var beginMonth = new DateTime(year, month, 1);

                var endMonth = DateTime.Now;
                var querySql = from enrollDetail in _enrollDetailRepository.Where(t =>
                        t.CreateTime > beginMonth && t.CreateTime < endMonth &&
                        t.EnrollStatus == EnrollStatus.ConfirmIntoGroup)
                               select new
                               {

                                   OptTime = enrollDetail.CreateTime,
                                   Year = enrollDetail.CreateTime.Year,
                                   Month = enrollDetail.CreateTime.Month,
                               };

                var result = querySql.GroupBy(t => new { t.Year, t.Month }).Select(s => new EnrollDataDTO
                {
                    Year = s.Key.Year,
                    Month = s.Key.Month,
                    EnrollCount = s.Count()
                }).ToList();


                #region 填充数据

                List<EnrollDataDTO> returnList = new List<EnrollDataDTO>();
                for (int i = 0; i < DateTime.Now.Month % 3 + (quarterCount - 1) * 3; i++)
                {
                    var tempTime = DateTime.Now.AddMonths(-1 * i);
                    var existedItem = result.FirstOrDefault(u => u.YearMonth == tempTime.ToString("yyyy-MM"));
                    if (existedItem != null)
                    {
                        returnList.Add(new EnrollDataDTO
                        {
                            Month = existedItem.Month,
                            Year = existedItem.Year,
                            EnrollCount = existedItem.EnrollCount
                        });
                    }
                    else
                    {
                        returnList.Add(new EnrollDataDTO
                        {
                            Month = tempTime.Month,
                            Year = tempTime.Year,
                            EnrollCount = 0
                        });
                    }
                }

                #endregion

                var returnResult = returnList.GroupBy(t => t.QuarterStr).Select(u => new EnrollQuartDataDTO()
                {
                    ViewStr = u.Key,
                    EnrollCount = u.Sum(t => t.EnrollCount)
                }).ToList();

                return returnResult;
            }
            else
            {
                var year = DateTime.Now.AddMonths(-(count - 1)).Year;
                var month = DateTime.Now.AddMonths(-(count - 1)).Month;

                var beginMonth = new DateTime(year, month, 1);

                var endMonth = DateTime.Now;
                var querySql = from enrollDetail in _enrollDetailRepository.Where(t =>
                        t.CreateTime > beginMonth && t.CreateTime < endMonth &&
                        t.EnrollStatus == EnrollStatus.ConfirmIntoGroup)
                               select new
                               {

                                   OptTime = enrollDetail.CreateTime,
                                   Year = enrollDetail.CreateTime.Year,
                                   Month = enrollDetail.CreateTime.Month,
                               };

                var result = querySql.GroupBy(t => new { t.Year, t.Month }).Select(s => new EnrollDataDTO
                {
                    Year = s.Key.Year,
                    Month = s.Key.Month,
                    EnrollCount = s.Count()
                }).ToList();

                #region 填充数据

                List<EnrollDataDTO> returnList = new List<EnrollDataDTO>();
                for (int i = 0; i < count; i++)
                {
                    var tempTime = DateTime.Now.AddMonths(-1 * i);
                    var existedItem = result.FirstOrDefault(u => u.YearMonth == tempTime.ToString("yyyy-MM"));
                    if (existedItem != null)
                    {
                        returnList.Add(new EnrollDataDTO
                        {
                            Month = existedItem.Month,
                            Year = existedItem.Year,
                            EnrollCount = existedItem.EnrollCount
                        });
                    }
                    else
                    {
                        returnList.Add(new EnrollDataDTO
                        {
                            Month = tempTime.Month,
                            Year = tempTime.Year,
                            EnrollCount = 0
                        });
                    }
                }

                #endregion

                var returnResult = returnList.GroupBy(t => t.YearMonth).Select(u => new EnrollQuartDataDTO()
                {
                    ViewStr = u.Key,
                    EnrollCount = u.Sum(t => t.EnrollCount)
                }).ToList();

                return returnResult;
            }

        }
        ///<summary> 参与项目数排行 [New] </summary>
        [HttpGet("{topCount:int}")]
        public List<TrialDataRankDTO> GetTrialCountRank(int topCount)
        {
            var queryList = (from enrollDetail in _enrollDetailRepository.Where(t =>
                    t.EnrollStatus == EnrollStatus.ConfirmIntoGroup)
                             group enrollDetail by enrollDetail.DoctorId
                into g
                             select new
                             {
                                 ReviewerId = g.Key,
                                 TrialCount = g.Count()
                             }).OrderByDescending(u => u.TrialCount).Take(topCount).ToList();

            var trialDataRank = from stat in queryList
                                join doctor in _doctorRepository.AsQueryable() on stat.ReviewerId equals doctor.Id
                                select new TrialDataRankDTO()
                                {
                                    TrialCount = stat.TrialCount,
                                    ChineseName = doctor.ChineseName,
                                    FirstName = doctor.FirstName,
                                    LastName = doctor.LastName,
                                    ReviewerId = doctor.Id,
                                    ReviewerCode = doctor.ReviewerCode
                                };
            return trialDataRank.ToList();

        }
        ///<summary> 最新工作量 （已确定的）[New] </summary>
        [HttpGet("{searchCount:int}")]
        public List<LatestWorkLoadDTO> GetLatestWorkLoadList(int searchCount)
        {
            var workloadList = _workloadRepository.AsQueryable()
                .Where(t => t.DataFrom == (int)WorkLoadFromStatus.FinalConfirm &&
                            (t.Adjudication + t.AdjudicationIn24H + t.AdjudicationIn48H) > 0 &&
                            (t.Timepoint + t.TimepointIn24H + t.TimepointIn48H) > 0)
                .OrderByDescending(t => t.CreateTime).Take(searchCount).ToList();


            var reviewerList = from w in workloadList
                               join doctor in _doctorRepository.Where() on w.DoctorId equals doctor.Id into tt
                               from doctorItem in tt.DefaultIfEmpty()
                               join trial in _trialRepository.AsQueryable() on w.TrialId equals trial.Id into cc
                               from trialItem in cc.DefaultIfEmpty()
                               select new LatestWorkLoadDTO
                               {

                                   ReviewerId = w.DoctorId,
                                   Timepoint = w.Timepoint + w.TimepointIn48H + w.TimepointIn24H,
                                   Adjudication = w.Adjudication + w.AdjudicationIn48H + w.AdjudicationIn24H,
                                   Global = w.Global,
                                   ReviewerCode = doctorItem.ReviewerCode,
                                   FirstName = doctorItem.FirstName,
                                   LastName = doctorItem.LastName,
                                   ChineseName = doctorItem.ChineseName,

                                   TrialCode = trialItem.TrialCode
                               };
            return reviewerList.ToList();


        }



        #endregion

    }
}
